[英]Python tkinter When Toplevel object is destroyed, With toplevel binding for <Destroy> the bound command executes multiple times
在下面的代碼中,當頂層window被銷毀時,bind語句中的命令被執行了多次。 可能為頂級中的每個子小部件一次。 當我將頂層更改為框架時,綁定命令只執行一次。 在示例中,quit() 或 raise SystemExit 被推遲到命令完成其循環。 為什么會這樣?
import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showinfo
class PlainFrame(tk.Frame):
def __init__(self,parent):
super().__init__(parent)
self.butts = []
for i in range(20) :
# button
self.butts.append(ttk.Button(self, text=f'Click Me {i}'))
self.butts[i]['command'] = self.button_clicked
self.butts[i].grid(column=0,row=i)
self.pack()
def button_clicked(self):
showinfo(title='Information',
message='Hello, Tkinter!')
class MainFrame(tk.Toplevel):
#class MainFrame(tk.Frame):
def __init__(self, container,*args,**kwargs):
super().__init__(container,kwargs)
options = {'padx': 5, 'pady': 5}
# label
self.label = ttk.Label(self, text='Hello, Tkinter!')
self.label.pack(**options)
self.quit_button = ttk.Button(self,text='Quit',
command = self._quit)
self.quit_button.pack()
self.frame = PlainFrame(self)
# add when frame
#self.pack()
def button_clicked(self):
showinfo(title='Information',
message='Hello, Tkinter!')
def _quit(self):
self.destroy()
class App(tk.Tk):
def __init__(self):
super().__init__()
# configure the root window
self.title('My Awesome App')
self.geometry('600x100')
def quitting(self,event):
print ('just passing through')
quit()
raise SystemExit
if __name__ == "__main__":
app = App()
frame = MainFrame(app)
# app.withdraw()
frame.bind('<Destroy>',app.quitting)
app.mainloop()
綁定命令的頂級綁定執行多次
是的,這就是 tkinter 的工作原理。
當你綁定到某個東西時,你不會綁定到一個小部件。 相反,您綁定到綁定標簽。 每個小部件都有一組綁定標簽。 當一個小部件接收到一個事件時,tkinter 將檢查它的每個綁定標簽,看看是否有一個 function 綁定到它的給定事件。
那么,什么是小部件綁定標簽? 每個小部件都有綁定標簽“all”。 每個小部件還獲得一個以小部件本身命名的綁定標簽。 它獲得第三個綁定標簽,即小部件 class 的名稱(例如:“按鈕”、“標簽”等)。 第四個標簽——給你帶來麻煩的標簽——是包含小部件的 window 的名稱。 順序從最具體到最不具體:小部件、小部件 class、window、“全部”。
您可以通過打印小部件的綁定標簽來查看這一點。 考慮以下代碼:
import tkinter as tk
root = tk.Tk()
toplevel = tk.Toplevel(root)
label = tk.Label(toplevel)
print(f"binding tags for label: {label.bindtags()}")
運行時,上面的代碼會生成這個 output:
binding tags for label: ('.!toplevel.!label', 'Label', '.!toplevel', 'all')
第一個字符串..toplevel.!label
是 label 小部件的內部名稱。 Label
是小部件 class, .!toplevel
是頂層小部件的名稱,然后是字符串all
。
當您點擊 label 時會發生什么? 首先,tkinter 將檢查是否有綁定按鈕單擊標簽..toplevel.!label
。 如果您綁定到小部件本身,它將有一個。 接下來,它將檢查小部件 class 上是否存在綁定。 滾動條和按鈕等小部件將在小部件 class 上具有綁定,但 label 不會。 接下來,tkinter 將查看 window 本身是否有針對該事件的綁定。 最后,它會查看特殊標簽all
上是否有綁定。
您可以通過將綁定標簽列表傳遞給bindtags
命令來更改小部件的綁定標簽。 例如,如果您希望每個小部件都有一個框架的綁定標簽,您可以設置綁定標簽以包含框架,然后每個小部件都會響應綁定到框架的事件。
您也可以使用相同的技術來刪除綁定。 例如,如果您想從Text
小部件中刪除所有默認綁定,則可以從其綁定標簽列表中刪除Text
。 一旦你這樣做了,小部件將不會響應任何按鍵或按鍵釋放。
綁定標簽如何工作的規范描述在 tcl/tk 的bindtags 手冊頁中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.