我最近开始学习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
答案 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)