Почему не работают root.quit () или root.destroy (), а только их комбинация? - PullRequest
0 голосов
/ 17 мая 2019

В моей программе я реализовал всплывающее окно с некоторыми записями для пользовательского ввода. Это всплывающее окно имеет кнопку «Ввод» для подтверждения и сбора ввода, а затем автоматически закрывает всплывающее окно. Для закрытия Popup я нашел методы root.destroy() и root.quit() (в моем коде self.master вместо root). Я думал, что вроде понимаю, как их использовать, но, видимо, я не понял. : /


import tkinter as tk


root = tk.Tk()
window = MainWindow(root)
root.mainloop()


class MainWindow(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)
        self.pack()

        #some irrelevant widgets

        btn_new_element = tk.Button(self, text='new', command=self.new_element)
        btn_new_element.pack()


    def new_element(self):

        root = tk.Toplevel()
        popup = Pupup(root, someData, otherData)
        root.mainloop()

        #do some other stuff



class Popup(tk.Frame):

    def __init__(self, master, var1, var2):

        tk.Frame.__init__(self, master)
        self.pack()

        #some widgets

        btn = tk.Button(self, text='Enter', command=lambda a=var1, b=var2: self.foo(a, b))
        btn.pack()


    def foo(self, a, b):

        #do something with widget data

        self.master.quit()
        self.master.destroy()

В foo() сначала я использовал только destroy(). Он закрывает всплывающее окно, но программа не продолжает с кодом в new_element(). (Казалось, что mainloop() все еще зацикливается.) Использование quit() привело к противоположному результату: остальная часть кода в new_element() была выполнена, но всплывающее окно все еще было там. Только использование quit() и destroy() в указанном порядке дало мне желаемый результат.

Согласно тысячам примеров в Интернете, это можно сделать, используя только один из двух методов. Почему это не работает в моем коде?

РЕДАКТИРОВАТЬ: удалены var1 и var2 из конструктора MainWindow (ошибка копирования и вставки при создании этого вопроса.

РЕДАКТИРОВАТЬ: Кроме того, я чувствую, что проблема может быть в объеме корневой переменной. В new_element() создать локальную переменную с именем root или перезаписать глобальную корневую переменную?

Ответы [ 3 ]

2 голосов
/ 17 мая 2019

Корень проблемы в том, что вы звоните mainloop более одного раза.Ты не должен этого делать.Это вызывает проблемы, очень похожие на ту, которая у вас есть.

Если ваша цель - создать всплывающее окно, а затем подождать, пока пользователь не закроет всплывающее окно, у tkinter есть специальный метод для этого.Он называется wait_window и не вернется, пока не будет уничтожено окно, в котором он ожидает.

top = tk.Toplevel()
popup = Popup(top, "some data", "other data")
top.wait_window(top)        

Вы можете добавить дополнительный код после top.wait_window(top), и он не будет выполняться до тех пор, покавсплывающее окно было уничтожено.

В вашем всплывающем коде вашей кнопке просто нужно вызвать destroy во всплывающем окне.Вы не должны звонить quit.

def foo(self, a, b):

    #do something with widget data

    self.master.destroy()
0 голосов
/ 17 мая 2019

Я считаю, что проблема в том, что вы создали второй цикл, чтобы исправить это, вы можете просто удалить второй цикл, и тогда функция .destroy() будет работать нормально.

Как это

class MainWindow(tk.Frame):
    def __init__():
        # your init code

    def new_element(self):
        root = tk.Toplevel()
        popup = Popup(root, 1, 0)

class Popup(tk.Frame):

    def __init__(self, master, var1, var2):
        # your init code

    def foo(self, a, b):
        self.master.destroy()

Еще один комментарий, который я сделаю, заключается в том, что я считаю, что то, как вы структурировали эти окна, вводит в заблуждение и может привести к путанице (имейте в виду, что это всего лишь предпочтение и больше не связано с «реальными» проблемами).

Я считаю, что вместо Popup(Frame) класса вам следует создать Popup(Toplevel) класс.

Как это

import tkinter as tk

class MainWindow(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)
        self.pack()
        btn_new_element = tk.Button(self, text='new', command=self.new_element)
        btn_new_element.pack()
        self.master = master
        self.pack()

    def new_element(self):
        popup = Popup(self.master, 1, 0)


class Popup(tk.Toplevel):
    def __init__(self, master, var1, var2):
        super().__init__(master)
        #some widgets
        btn = tk.Button(self, text='Enter', command=lambda a=var1, b=var2: self.foo(a,b))
        btn.pack()

    def foo(self, a, b):
        self.destroy()

if __name__ == '__main__':
    root = tk.Tk()
    window = MainWindow(root)
    root.mainloop()

Когда вы создаете элемент Toplevel, ему нужен мастер, мастер в этом случае будет главным окном. Когда вы используете self.destroy в классе Toplevel, вы не уничтожаете мастера Toplevels, а вместо этого уничтожаете сам Toplevel.

0 голосов
/ 17 мая 2019

Есть много вещей, которые не так с вашим примером (копирование вставка не работает), но после организации работы (предоставление значений и прочее), вот ваша проблема:

    def new_element(self):
        root = tk.Toplevel()
        popup = Pupup(root, someData, otherData)
        # root.mainloop() # < ------ This generates a new main loop, with is destroyed.

Вот полный код, который работает:

import tkinter as tk


class Popup(tk.Frame):

    def __init__(self, master, var1, var2):

        tk.Frame.__init__(self, master)
        self.pack()

        #some widgets

        btn = tk.Button(self, text='Enter', command=lambda a=var1, b=var2: self.foo(a, b))
        btn.pack()


    def foo(self, a, b):

        #do something with widget data

        self.master.quit()
        # self.master.destroy()


class MainWindow(tk.Frame):

    def __init__(self, master, var1, var2):

        tk.Frame.__init__(self, master)
        self.pack()

        #some irrelevant widgets

        btn_new_element = tk.Button(self, text='new', command=self.new_element)
        btn_new_element.pack()


    def new_element(self):

        root = tk.Toplevel()
        popup = Popup(root, 'a', 'b')
        # root.mainloop()

        #do some other stuff

root = tk.Tk()
window = MainWindow(root,1,2)
root.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...