[英]tkinter - undock frame and handle window close event
基於這個問題,我寫了以下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()
單擊取消停靠按鈕,取消停靠紅框,單擊停靠按鈕,再次停靠該框。 我有兩個問題:
錯誤是:
AttributeError: 'Frame' 對象沒有屬性 'protocol'
我理解錯誤但如何處理窗口關閉事件?
為什么 self.dockable_frame 的類型是 <class 'tkinter.Frame'> 而不是 TopLevel 因為 wm 管理文檔說:指定的小部件將成為獨立的頂級窗口?
我認為這是因為self.dockable_frame
是一個 python 類並且不知道底層小部件已更改。 可以說這是wm_manage
一個錯誤。
由於 self.dockable_frame.protocol("WM_DELETE_WINDOW", insert_function_here) 在我的 Windows PC 上出現錯誤,我該如何處理窗口關閉事件?
最簡單的方法是直接從tk.Wm
類調用該方法。 它看起來像這樣:
tk.Wm.protocol(self.dockable_frame, "WM_DELETE_WINDOW", self.whatever)
該文檔具有誤導性。 當我發現這個我認為類似的功能時,框架變成了一個窗口。 事實上,這不是真的,我可以通過下面的代碼證明這一點。
真正發生的事情,至少在 MS-Windows 下,但我希望在其他操作系統下具有相同的功能,就是幀將被打包在 wm_mange 為此創建的不同頂層上。
當 tkinter 定義一個Window/Toplevel 時,它總是為您將使用的客戶區構建一個子窗口(框架) 。 這就是為什么你需要調用 win32gui。 當您將更改窗口樣式時,請使用GetParent方法。
代碼:
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
參考:
在 Tk 中,Toplevel 窗口基本上是由窗口管理器管理的 Frame 的特殊形式。 建議是添加命令 wm manage 和 wm forget ,它們將采用任意 Frame 並允許它由窗口管理器管理,使其成為 Toplevel 窗口。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.