Цикл репликации сообщений Python 3 Tkinter - PullRequest
0 голосов
/ 02 февраля 2019

Я недавно начал изучать 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)

1 Ответ

0 голосов
/ 02 февраля 2019

Вот в чем проблема: когда пользователь нажимает кнопку X, функция closed вызывается автоматически через операционную систему.Tkinter (и другие системы с графическим интерфейсом) обладают тем свойством, что ваша программа управляется действиями пользователя, которые создают «события», в результате которых ваши «обработчики событий» вызываются для вас средой.В вашем случае ваша функция 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...