Когда я связываю <Destroy>с виджетом Toplevel, функция связывания будет выполняться в 6 раз больше, чем один раз - PullRequest
0 голосов
/ 21 декабря 2018
class Attribute:
    def __init__(self, pos_x, pos_y):
        self.attr_top = Toplevel()
        print(root.winfo_x() + pos_x)
        self.attr_top.geometry('+' + str(root.winfo_x() + pos_x) + '+' + str(root.winfo_y() + pos_y))
        self.name_var = StringVar()
        self.name_var.set('name')
        self.name_label = Label(self.attr_top, textvariable = self.name_var)
        self.name_label.grid(row = 0, column = 0)
        self.name_enter = Entry(self.attr_top)
        self.name_enter.grid(row = 0, column = 1)
        self.next_name_var = StringVar()
        self.next_name_var.set('link')
        self.next_name_label = Label(self.attr_top, textvariable = self.next_name_var)
        self.next_name_label.grid(row = 1, column = 0)
        self.next_name_enter = Entry(self.attr_top)

        self.finish_button = Button(self.attr_top, text = 'finsh edit', command = self.button_close_top)
        self.finish_button.grid(row = 3, column = 0, columnspan = 2)
        self.attr_top.bind('<Return>', self.return_close_top)
        self.next_name_enter.grid(row = 1, column = 1)

    def button_close_top(self):
        self.name = self.name_enter.get()
        self.next_name = self.next_name_enter.get()
        self.attr_top.destroy()

    def return_close_top(self, event):
        self.button_close_top()

    def save_attr(self, event):
        name = self.attr.name
        next_name = self.attr.next_name

        print('jinru')
        name_font = tkfont.Font(size = 10)
        self.enter_text.insert(END, name)
        self.enter_text.tag_add(name, 1.0, END)
        self.enter_text.tag_config(name, font = name_font, offset = 2, underline = 1)

    def edit_brief(self):
        print('edit brief')
        self.attr = Attribute(self.widget_pos_x, self.widget_pos_y)
        self.enter_text = Text(self.window_frame, width = 30, height = 3)
        self.enter_text.place(x = self.widget_pos_x, y = self.widget_pos_y)
        self.attr.attr_top.bind('<Destroy>', self.save_attr)

если я закрою окно Toplevel, оно напечатает 6 'run', и текстовый виджет также вставит 6 раз текст, который я ввел.enter image description here enter image description here

1 Ответ

0 голосов
/ 21 декабря 2018

При привязке к виджету Toplevel привязка применяется к этому виджету и всем его потомкам .Если вы хотите, чтобы событие обрабатывалось только виджетом Toplevel, общее решение заключается в проверке объекта виджета, связанного с событием.

Например, вы можете использовать winfo_toplevel(), чтобы получить виджет верхнего уровня, связанный с любым заданным виджетом, и выполнять свое действие, только если виджет, связанный с событием, совпадает с окном верхнего уровня, связанным с событием.

Например:

def save_attr(self, event):
    if event.widget == event.widget.winfo_toplevel():
        ...

Причина этого заключается в том, как обрабатываются события.Когда вы привязываете события к виджетам, вы фактически не привязываетесь к виджету.Вместо этого вы привязываетесь к привязывающему тегу , имя которого совпадает с внутренним именем виджета.Когда событие обрабатывается, оно применяется к каждому из тегов привязки, связанных с виджетом.Таким образом, если вы связываетесь с виджетом Toplevel, вы фактически связываетесь с тегом с тем же именем, что и виджет.

Набор тегов привязки по умолчанию для виджета включает виджет, но также включает окно верхнего уровня, которое содержит виджет.Полный список содержит виджет, имя класса виджета (например, «Метка», «Кнопка» и т. Д.), Имя ближайшего предка верхнего уровня окна и специальную строку «все».

В случае привязки к <Destroy>, когда верхний уровень уничтожается, он также вызывает уничтожение всех его дочерних элементов.Например, если на верхнем уровне есть метка, она также получит событие <Destroy>.Поскольку метка имеет тег привязки, связанный с виджетом Toplevel, связанная функция будет вызываться для метки в дополнение к обработке самим Toplevel.

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