更改 WM_CLASS 对话框 (tkinter)

Change WM_CLASS of Dialog (tkinter)

有没有办法更改 WM_CLASS showinfo(和其他对话框)? className, class_ 参数完成 Tk, Toplevel 的工作。

import tkinter as tk
from tkinter.messagebox import showinfo

if __name__ == '__main__':
    root = tk.Tk(className='ymail')
    mail_client = tk.Toplevel(root, class_='ymail')
    new_message = tk.Toplevel(root, class_='ymail')
    showinfo(title="Cancel sending", parent=new_message, message="""
Send is cancelled due to empty message""")
    root.mainloop()

用于显示信息对话框

$ xprop WM_CLASS

给予

WM_CLASS(STRING) = "__tk__messagebox", "Dialog"

我认为用 Alt-~ (Tilde) 循环 tkinter windows 很方便,它们的 WM_CLASS 应该是一样的。

我进行了搜索(“tkinter 更改 WM_CLASS showinfo”)。有些命中不适用,有些不起作用 (xdotool),有些我宁愿作为最后的手段使用(将 C 程序转换为 python)。

Using    
Debian 10    
python 3.7.3    
GNOME 3.30.1

编辑
添加了解决方法(使用 xdotool)

import threading
import subprocess
import time
import tkinter as tk
from tkinter.messagebox import showinfo


def change_dialog_class(from_="Dialog", to_="ymail"):
    cmd = f"xdotool search --class {from_} set_window --class {to_}"
    time.sleep(1)
    subprocess.run(cmd.split())


if __name__ == '__main__':
    root = tk.Tk(className='ymail')
    mail_client = tk.Toplevel(root, class_='ymail')
    new_message = tk.Toplevel(root, class_='ymail')
    tk.Frame.class_ = 'ymail'
    threading.Thread(target=change_dialog_class, args=("Dialog", "ymail"),
                     daemon=True).start()
    showinfo(title="Cancel sending", parent=new_message,
             message="""Send is cancelled due to empty message""")
    root.mainloop()

与 ymail.desktop 一起工作

$ cat ~/.local/share/applications/ymail.desktop
[Desktop Entry]
Type=Application
Terminal=false
Name=ymail
Icon=python
StartupWMClass=ymail

然而,python 解决方案会更好

Since I'm not a XSystem user it took me some time to follow up. It and unfortunately it isnt possible without subclassing it, which results in pretty much the same as writing your own class with tk.Toplevel. Anyway I hope toplevel.wm_group(root) ease things out and works for you.

在我注意到 SimpleDialog 可能有一些您想要保留的功能并且可能很难自己编写代码之后,我决定写一个您可能想要使用的答案。它还提供 class_ 选项,以防 wm_group 为您工作。

代码如下:

import tkinter as tk
import tkinter.simpledialog as simpledialog

class MessageBox(simpledialog.SimpleDialog):
    def __init__(self, master,**kwargs):
        simpledialog.SimpleDialog.__init__(self,master,**kwargs)
        #root.tk.call('wm', 'group', self.root._w, master)
    def done(self,num):
        print(num)
        self.root.destroy()
        

root = tk.Tk()
MessageBox(root,title='Cancel',text='Im telling you!',class_='ymail',
           buttons=['Got it!','Nah'], default=None, cancel=None)
root.mainloop()

这是来源: https://github.com/python/cpython/blob/main/Lib/tkinter/simpledialog.py#L31