我正在创建一个弹出消息,如果用户在弹出窗口的框架之外单击,该消息将消失。要检查用户是否在框架外单击,代码看起来像这样:
import tkinter as tk
def build_popup(self, root):
popup_frame = tk.Frame(root)
popup_frame.grid(row=0, column=0)
# binding to check if click is outside the frame
self.popup_frame_funcid = root.bind_all('<Button-1>', self.delete_popup)
my_canvas = tk.Canvas(popup_frame, width=200, height=200)
my_canvas.grid(row=0, column=0)
def delete_popup(self, root, event):
# if location clicked is not that of a child of the frame destroy popup
if root.winfo_containing(event.x_root, event.y_root) not in popup_frame.winfo_children():
popup_frame.destroy()
root.unbind('<Button-1>', self.popupframe_funcid)
但是,当将小部件添加到my_canvas
(例如一个条目)并且其父级声明为my_canvas
时,我遇到了一个问题。当我单击添加的窗口小部件时,popup_frame.winfo_children()
(相当合理)不会将添加的窗口小部件标识为popup_frame
的子级,并破坏了框架。
tkinter中是否有一个函数可以用来检查某个窗口小部件是否是另一个窗口小部件的后代,还是我不得不手动跟踪添加到popup_frame
的每个窗口小部件?
如果有一种更简单/替代的方法来实现相同的结果,我也将很高兴听到它。
答案 0 :(得分:1)
您可以使用winfo_parent
获取小部件的父级。然后,您可以在父对象以及父对象的父对象上调用该对象,以此类推,以获取小部件的祖先。 winfo_parent
返回一个字符串而不是父对象,但是tkinter可以将名称转换为小部件。
例如,要获取名为w
的小部件的父小部件,可以执行以下操作:
parent = w.nametowidget(w.winfo_parent())
这样,您就可以逐步提升小部件的层次结构,并在到达根窗口时停止。
答案 1 :(得分:0)
我使用winfo_children()
和winfo_parent()
来标识子代和父代小部件/容器。请注意,单个.
表示根窗口。
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
frame1 = tk.Frame(self)
btn1 = tk.Button(self)
btn2 = tk.Button(self)
btn3 = tk.Button(frame1)
print('Root children widget are: {}'.format(self.winfo_children()))
print('frame1 children widget is: {}'.format(frame1.winfo_children()))
print('Button 1 parent is: {}'.format(btn1.winfo_parent()))
print('Button 2 parent is: {}'.format(btn2.winfo_parent()))
print('Button 3 parent is: {}'.format(btn3.winfo_parent()))
if __name__ == '__main__':
App().mainloop()
结果:
答案 2 :(得分:0)
我四处乱逛,找到了已经提到的解决方案的替代解决方案。
str(my_widget)
返回my_widget
的字符串路径
因此,您可以通过简单地检查my_canvas
的路径是否以popup_frame
的路径开头来检查my_canvas
是否是popup_frame
的后代。
在python中,这很简单:
str(my_canvas).startswith(str(popup_frame))