Как проверить, является ли виджет потомком другого виджета с помощью tkinter - PullRequest
0 голосов
/ 14 октября 2019

Я создаю всплывающее сообщение, которое исчезает, если пользователь щелкает за пределами рамки всплывающего окна. Чтобы проверить, щелкает ли пользователь за рамкой, код выглядит примерно так:

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?

Если есть более простой / альтернативный способ достижения того же результата, я бы такжеочень рад это слышать.

Ответы [ 3 ]

1 голос
/ 14 октября 2019

Вы можете использовать winfo_parent, чтобы получить родительский элемент виджета. Затем вы можете вызвать это для родителя, родителя родителя и т. Д., Чтобы получить происхождение виджета. winfo_parent возвращает строку, а не родительский объект, но у tkinter есть способ преобразовать имя в виджет.

Например, чтобы получить родительский виджет для виджета с именем w, вы можете сделать это:

parent = w.nametowidget(w.winfo_parent())

С этим вы можете пройти вверх по иерархии виджетов,остановка при входе в корневое окно.

0 голосов
/ 23 октября 2019

Я немного повозился и нашел альтернативное решение уже упомянутым.

str(my_widget) возвращает путь строки my_widget

Следовательно, вы можете проверить,например, my_canvas является потомком popup_frame, просто проверяя, начинается ли путь my_canvas с пути popup_frame.

В python это просто:

str(my_canvas).startswith(str(popup_frame))

0 голосов
/ 14 октября 2019

Я использую 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()

Результаты:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...