tkinter - 取消停靠框架并处理 window 关闭事件
tkinter - undock frame and handle window close event
基于this question,我写了如下mwe:
import tkinter as tk
class BaseFrame(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.bmanage = tk.Button(self, text='undock', command = self.undock)
self.bforget = tk.Button(self, text='dock', command = self.dock)
self.bmanage.grid(row=0, column=0, padx=20, pady=20, sticky='nsew')
self.bforget.grid(row=0, column=1, padx=20, pady=20, sticky='nsew')
self.dockable_frame = tk.Frame(self, bg="red", height=100)
self.dockable_frame.grid(row=1, column=0, padx=20, pady=20, columnspan=2, sticky='nsew')
self.label = tk.Label(self.dockable_frame, text="hi")
self.label.grid(row=0, column=0, padx=150, pady=20, sticky='nsew')
def undock(self):
self.parent.wm_manage(self.dockable_frame)
self.dockable_frame.configure(bg='blue')
print(type(self.dockable_frame))
def dock(self):
self.parent.wm_forget(self.dockable_frame)
self.dockable_frame.grid()
if __name__ == "__main__":
root = tk.Tk()
base_frame = BaseFrame(root)
base_frame.grid(row=0, column=0, padx=20, pady=20, sticky='nsew')
root.mainloop()
单击 取消停靠 按钮,取消停靠红框,单击 停靠 按钮,再次停靠红框。我有两个问题:
- 为什么 self.dockable_frame 的类型是
而不是 TopLevel 因为 wm manage documentation 说: 指定的小部件将成为独立的顶级window?
- 如何处理 window 关闭事件,因为 self.dockable_frame.protocol("WM_DELETE_WINDOW", insert_function_here)在我的 Windows 电脑上出现错误?
错误是:
AttributeError: 'Frame' 对象没有属性 'protocol'
我理解错误,但如何处理 window 关闭事件?
Why is the type of self.dockable_frame a <class 'tkinter.Frame'> and not a TopLevel since the wm manage documentation says: The widget specified will become a stand alone top-level window?
我认为这是因为 self.dockable_frame
是 python class 并且不知道底层小部件已更改。可以说这是 wm_manage
.
中的错误
How can I handle the window close event since self.dockable_frame.protocol("WM_DELETE_WINDOW", insert_function_here) gives an error on my Windows PC?
最简单的方法是直接从tk.Wm
class调用方法。它看起来像这样:
tk.Wm.protocol(self.dockable_frame, "WM_DELETE_WINDOW", self.whatever)
文档具有误导性。 我也是这么想的,框架变成了window。事实上,这不是真的,我可以通过下面的代码证明这一点。
真正发生的是,至少在 MS-Windows 下,但我希望在其他 os 下具有相同的功能,即帧将被打包到由 [= 创建的不同顶层上46=]为此。
当 tkinter 定义一个 Window/Toplevel it always build a child window (frame) for the client area which you will work with. Thats why you need to call the win32gui.GetParent method when you will change your window style.
代码:
import tkinter as tk
import win32gui
def info():
print(f'python id: {id(frame)}')
print(f'tkinterID: {frame.winfo_id()}')
print(f'parent id: {win32gui.GetParent(frame.winfo_id())}')
def undock():
root.wm_manage(frame)
def forget():
root.wm_forget(frame)
frame.pack()
root = tk.Tk()
frame= tk.Frame()
frame.pack()
b1 = tk.Button(frame,text='INFO',command=info)
b2 = tk.Button(frame,text='mnge',command=undock)
b3 = tk.Button(frame,text='nrml',command=forget)
b1.pack()
b2.pack()
b3.pack()
root.mainloop()
输出:
第一次出现:
python id: 67118160
tkinterID: 3412074
parent id: 7867926
取消停靠后
python id: 67118160
tkinterID: 3412074
parent id: 15666896
后忘记
python id: 67118160
tkinterID: 3412074
parent id: 7867926
In Tk, Toplevel windows are basically a special form of a Frame which
are managed by the window manager. The proposal is to add the commands
wm manage and wm forget which will take an arbitrary Frame and allow
it to be managed by the window manager, making it a Toplevel window.
基于this question,我写了如下mwe:
import tkinter as tk
class BaseFrame(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.bmanage = tk.Button(self, text='undock', command = self.undock)
self.bforget = tk.Button(self, text='dock', command = self.dock)
self.bmanage.grid(row=0, column=0, padx=20, pady=20, sticky='nsew')
self.bforget.grid(row=0, column=1, padx=20, pady=20, sticky='nsew')
self.dockable_frame = tk.Frame(self, bg="red", height=100)
self.dockable_frame.grid(row=1, column=0, padx=20, pady=20, columnspan=2, sticky='nsew')
self.label = tk.Label(self.dockable_frame, text="hi")
self.label.grid(row=0, column=0, padx=150, pady=20, sticky='nsew')
def undock(self):
self.parent.wm_manage(self.dockable_frame)
self.dockable_frame.configure(bg='blue')
print(type(self.dockable_frame))
def dock(self):
self.parent.wm_forget(self.dockable_frame)
self.dockable_frame.grid()
if __name__ == "__main__":
root = tk.Tk()
base_frame = BaseFrame(root)
base_frame.grid(row=0, column=0, padx=20, pady=20, sticky='nsew')
root.mainloop()
单击 取消停靠 按钮,取消停靠红框,单击 停靠 按钮,再次停靠红框。我有两个问题:
- 为什么 self.dockable_frame 的类型是
而不是 TopLevel 因为 wm manage documentation 说: 指定的小部件将成为独立的顶级window? - 如何处理 window 关闭事件,因为 self.dockable_frame.protocol("WM_DELETE_WINDOW", insert_function_here)在我的 Windows 电脑上出现错误?
错误是:
AttributeError: 'Frame' 对象没有属性 'protocol'
我理解错误,但如何处理 window 关闭事件?
Why is the type of self.dockable_frame a <class 'tkinter.Frame'> and not a TopLevel since the wm manage documentation says: The widget specified will become a stand alone top-level window?
我认为这是因为 self.dockable_frame
是 python class 并且不知道底层小部件已更改。可以说这是 wm_manage
.
How can I handle the window close event since self.dockable_frame.protocol("WM_DELETE_WINDOW", insert_function_here) gives an error on my Windows PC?
最简单的方法是直接从tk.Wm
class调用方法。它看起来像这样:
tk.Wm.protocol(self.dockable_frame, "WM_DELETE_WINDOW", self.whatever)
文档具有误导性。
真正发生的是,至少在 MS-Windows 下,但我希望在其他 os 下具有相同的功能,即帧将被打包到由 [= 创建的不同顶层上46=]为此。
当 tkinter 定义一个 Window/Toplevel it always build a child window (frame) for the client area which you will work with. Thats why you need to call the win32gui.GetParent method when you will change your window style.
代码:
import tkinter as tk
import win32gui
def info():
print(f'python id: {id(frame)}')
print(f'tkinterID: {frame.winfo_id()}')
print(f'parent id: {win32gui.GetParent(frame.winfo_id())}')
def undock():
root.wm_manage(frame)
def forget():
root.wm_forget(frame)
frame.pack()
root = tk.Tk()
frame= tk.Frame()
frame.pack()
b1 = tk.Button(frame,text='INFO',command=info)
b2 = tk.Button(frame,text='mnge',command=undock)
b3 = tk.Button(frame,text='nrml',command=forget)
b1.pack()
b2.pack()
b3.pack()
root.mainloop()
输出:
第一次出现:
python id: 67118160
tkinterID: 3412074
parent id: 7867926
取消停靠后
python id: 67118160
tkinterID: 3412074
parent id: 15666896
后忘记
python id: 67118160
tkinterID: 3412074
parent id: 7867926
In Tk, Toplevel windows are basically a special form of a Frame which are managed by the window manager. The proposal is to add the commands wm manage and wm forget which will take an arbitrary Frame and allow it to be managed by the window manager, making it a Toplevel window.