【问题标题】:Python 3 Tkinter messagebox replication loopPython 3 Tkinter 消息框复制循环
【发布时间】:2019-02-02 08:02:55
【问题描述】:

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

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

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

    from tkinter import *
from tkinter import messagebox
import time

#pop up
def spam():

    global spamreturn
    spamreturn = False

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

    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()

    if closed():
        spamreturn = True

spam()

if spamreturn == True:
    print("worked")
    time.sleep(3)

【问题讨论】:

  • 只需删除/注释掉 if closed():spamreturn = True 并按需要工作,它会导致 closed() 函数再次执行

标签: python python-3.x tkinter


【解决方案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)

【讨论】:

    猜你喜欢
    • 2020-10-07
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    相关资源
    最近更新 更多