Python 3 Tkinter消息框复制循环

时间:2019-02-02 08:02:55

标签: python python-3.x tkinter

我最近开始学习python并编写一些简单的程序,并且通过堆栈溢出和YouTube教程,它的运行非常顺利。但是,当我尝试制作Tkinter“ WM_DELETE_WINDOW”协议并运行该程序时。该文本框将正常打开,并且将与退出文本框一起正常关闭,但是随后将打开第二个空文本框以及第二个退出文本框,并显示相同的消息。然后,在我关闭之后,该程序将尝试第三次破坏盒子并得到此错误。

class A:
    def __init__(self):
        self.X = 0

a = A()
a.X = 5
a.Y = 2 # this line is not an error in python
print(a.X, a.Y)

如果您查看一下我的代码,我将不胜感激,这里是:

C:\Users\thech\Desktop\Python stuff>python spam.py
Traceback (most recent call last):
  File "spam.py", line 34, in <module>
    spam()
  File "spam.py", line 31, in spam
    if closed():
  File "spam.py", line 13, in closed
    mibox.destroy()
  File "C:\Users\thech\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 2062, in destroy
    self.tk.call('destroy', self._w)
_tkinter.TclError: can't invoke "destroy" command: application has been destroyed

1 个答案:

答案 0 :(得分:1)

这是问题所在:当用户单击X按钮时,将通过操作系统自动调用功能closed。 Tkinter(以及其他GUI系统)具有这样的属性,即程序由创建“事件”的用户操作驱动,从而导致环境调用“事件处理程序”。就您而言,您的函数closed是一个处理程序,并且该事件正在单击X。

当代码到达函数mainloop时,它不会立即返回。而是程序等待用户事件。当这些用户事件之一导致tk根对象被破坏时(在您的情况下为mibox.destroy()),对mainloop的调用将在该时刻返回。在这里,您再次致电closed()。这将导致对话框再次出现。 tk环境必须打开一个空的tk窗口才能将此对话框附加到其中。这就是为什么您看到第二个对话框和第二个窗口的原因。问题是对closed()的显式调用。

我修改了您的程序,现在可以使用了。我还做了其他一些更改。我将全局变量声明移到了最外层的缩进级别-我不喜欢在函数内部创建全局变量,这会使代码难以遵循。您需要在closed函数内部使用全局语句;否则,Python将使用相同名称的局部变量,而不用修改全局变量。无论是否正确,我还将在最后打印全局值。

如果这不起作用,请致电1-800-273-8255寻求帮助。

from tkinter import *
from tkinter import messagebox

spamreturn = False

#pop up
def spam():

    def closed():
        global spamreturn
        if messagebox.askokcancel("Quit", "Do you really wish to quit?"):
            spamreturn = True
            mibox.destroy()

    mibox = Tk()
    topframe = Frame(mibox)
    miLabel = Label(mibox, text="Call 1-800-273-8255")
    mibutton = Button(topframe, text="Your Computer has been infected")
    mibutton2 = Button(topframe, text="Please call 1-800-273-8255 for Assistance")
    miLabel.pack()
    mibutton.pack()
    mibutton2.pack()
    topframe.pack()
    mibox.geometry("300x100+500+250")

    mibox.protocol("WM_DELETE_WINDOW", closed)

    mibox.mainloop()

spam()

print(spamreturn)