簡體   English   中英

為什么在tkinter上破壞兩個不同的mainloop窗口會凍結程序?

[英]Why does destroying two different mainloop windows on tkinter freeze the program?

我正在為學校進行一個倒計時(例如電視節目)項目,該項目涉及一小段時間,其中用戶在tkinter Text()項中輸入響應(在時間限制下)。 多虧了此站點上的先前答案,我知道如何制作屏幕上的tkinter計時器,並且我使用了非常基本的線程設備將其與用戶Text()輸入窗口同時放置。

如果我不擔心在用戶提前關閉Text()輸入窗口時關閉時鍾,它會很好,但是在用戶完成操作后繼續滴答時,它會覺得很傻。 因此,我還插入了一些代碼(“ WM_DELETE_WINDOW”等),該代碼允許用戶關閉輸入窗口並提早提交答案,從而同時關閉計時器。 在此之后,這使程序凍結了,我不確定如何修復它。 這是我使用的代碼的簡化版本(問題完全相同):

import threading
from tkinter import *

def backgroundWindow():
    global root
    root = Tk()
    root.title("Happening at the same time")
    root.mainloop()

threadWindow = threading.Thread(target=backgroundWindow)
threadWindow.start()

print() # The threading did NOT work without this print statement (?)

def destroyer():
    global root
    newRoot.destroy()
    root.destroy()

newRoot = Tk()
newRoot.title("Simultaneous Window")
newRoot.protocol("WM_DELETE_WINDOW", destroyer)

newRoot.mainloop()

# program freezes up here (but does not finish)

print("Now the program continues")  # does NOT get printed

我也很困惑為什么第二個窗口在中間沒有看似隨機的打印語句的情況下無法顯示。 我嘗試了所有這些,但沒有成功。 這是一個相當小眾的問題。

編輯(我認為自己):

我知道有人已經回答了這個問題,而且效果很好-關閉其中一個窗口時,兩個窗口都自動關閉-但由於類的知識很模糊,我無法將其與倒計時程序配合使用,因此我使用了帶有一個窗口的類(這是我設法使grid方法起作用的唯一方法)。

原理是相同的,所以我錯誤地認為自己可以弄清楚,但是我遇到了一個涉及另一個課程的課程。 兩個窗口的內容雜亂無章(例如,一個窗口的bg顏色被無意地應用到另一個窗口),當我關閉其中一個窗口時,無論如何都將另一個窗口打開。 有沒有人有與班級一起上班和非班的提示? 這是沒有線程的代碼:

def conundrumClock():
    global threading, playerAnswer, playerNumber, tkinter
def clock():
    global threading, rootA
    def countdown(time): # (I copied this from a previous answer by Bryan Oakley)
        global threading
        if time == -1:
            rootA.destroy()
        else:
            if time == 0:
                label.configure(text="TIME UP!")
            else:
                label.configure(text="Time remaining: %d seconds" % time)

            rootA.after(1000, countdown, time-1)

    rootA = Tk() 
    rootA.title("COUNTDOWN CLOCK")
    label = Label(rootA, width=30)
    label.pack(padx=20, pady=20)
    countdown(15)
    rootA.mainloop() # I am aiming to get rid of this

    class AnswerEntry(tk.Tk):

        def __init__(self):
            tk.Tk.__init__(self)

            self.anagram = Label(self, text="Your anagram solution", bg="light cyan", font=(None, 15), width=18, height=2, anchor=E) 
            self.numerics = Label(self, text="Player number (1 or 2)", bg="light cyan", font=(None, 14), width=19, height=2, padx=4, anchor=E)
            self.anagram.grid(row=1, sticky=E, pady=1)
            self.numerics.grid(row=2, padx=(7,0), pady=5)

            self.solution = tk.Text(self, height=2, width=17,font=(None,15))
            self.number = tk.Text(self, height=2, width=17, font=(None, 15))
            self.solution.grid(row=1, column=1)
            self.number.grid(row=2, column=1) 

            self.button1 = tk.Button(self, text=" SUBMIT YOUR NAME ", bg="cyan", fg="black", width=20, height=1, font=(None, 11), anchor=W, command=self.answer)

            self.button2 = tk.Button(self, text="SUBMIT PLAYER NUMBER ", bg="cyan", fg="black", font=(None, 11), padx=3, command=self.the_number)
            self.button1.grid(row=100, column=1, sticky=E)
            self.button2.grid(row=100, column=0, sticky=W)

        def answer(self):
            global playerAnswer
            playerAnswer = self.solution.get('1.0', END)
        def the_number(self):
            global playerNumber
            playerNumber = self.number.get('1.0', END)

root = AnswerEntry()
root.title("REMEMBER TO PRESS THE BUTTONS!")
root.geometry("500x150")
root["bg"] = "aquamarine"
center(root) # (this is a function I got to center the window from a previous answer) 

第一個窗口顯示一個計時器(倒數),第二個窗口顯示一個框,您可以在其中輸入字謎的解答以及您的玩家編號。 下方的按鈕允許玩家“提交”這兩個東西(我在按鈕命令過程中使用了“ self。(text_entry_information).get”東西)。 我沒有做任何使這些窗口同時運行的嘗試,因為我做錯了,這會使問題困惑。

再次,任何幫助將不勝感激!

您的mainloop()不能超過1個。 即使您使用了線程也不行,因為它會引起問題。 但是您可以擁有超過1 tk.Toplevel窗口,其工作原理相同。 下面是一個示例:

import tkinter as tk

class Demo1:
    def __init__(self, master):
        self.master = master
        self.master.title('Happening at the same time')
        self.newWindow = tk.Toplevel(self.master)
        self.app = Demo2(self.newWindow)

class Demo2:
    def __init__(self, master):
        self.master = master
        self.master.title("Simultaneous Window")

def main(): 
    root = tk.Tk()
    app = Demo1(root)
    root.mainloop()

if __name__ == '__main__':
    main()

如您所見,我只有一個mainloop()

嘗試僅更頻繁地將tkinter導入為tk,因為它對名稱空間更好。 這個答案是為了解決您的編輯。

import tkinter as tk

def clock(root):
    global rootA
    def countdown(time): 
        if time == -1:
            destroyer() #invokes the destroy function 
        else:
            if time == 0:
                label.configure(text="TIME UP!")
            else:
                label.configure(text="Time remaining: %d seconds" % time)

            rootA.after(1000, countdown, time-1)

    rootA = tk.Toplevel(root) #Made it a tk.Toplevel instead of a new root
    rootA.protocol("WM_DELETE_WINDOW", destroyer) #set the window close protocol
    rootA.title("COUNTDOWN CLOCK")
    label = tk.Label(rootA, width=30)
    label.pack(padx=20, pady=20)
    countdown(15)

class AnswerEntry(tk.Tk):

    def __init__(self):
        super().__init__() #I changed tk.Tk.__init__(self) to this
        self.title("REMEMBER TO PRESS THE BUTTONS!") #I placed them here since they are the same thing
        self.geometry("500x150")
        self["bg"] = "aquamarine"
        self.protocol("WM_DELETE_WINDOW", destroyer)
        self.anagram = tk.Label(self, text="Your anagram solution", bg="light cyan", font=(None, 15), width=18, height=2, anchor=tk.E) 
        self.numerics = tk.Label(self, text="Player number (1 or 2)", bg="light cyan", font=(None, 14), width=19, height=2, padx=4, anchor=tk.E)
        self.anagram.grid(row=1, sticky=tk.E, pady=1)#Changed all your 'W' and 'E'... to 'tk.W' and 'tk.E'
        self.numerics.grid(row=2, padx=(7,0), pady=5)

        self.solution = tk.Text(self, height=2, width=17,font=(None,15))
        self.number = tk.Text(self, height=2, width=17, font=(None, 15))
        self.solution.grid(row=1, column=1)
        self.number.grid(row=2, column=1) 

        self.button1 = tk.Button(self, text=" SUBMIT YOUR NAME ", bg="cyan", fg="black", width=20, height=1, font=(None, 11), anchor=tk.W, command=self.answer)

        self.button2 = tk.Button(self, text="SUBMIT PLAYER NUMBER ", bg="cyan", fg="black", font=(None, 11), padx=3, command=self.the_number)
        self.button1.grid(row=100, column=1, sticky=tk.E)
        self.button2.grid(row=100, column=0, sticky=tk.W)

    def answer(self):
        global playerAnswer
        playerAnswer = self.solution.get('1.0', tk.END)
    def the_number(self):
        global playerNumber
        playerNumber = self.number.get('1.0', tk.END)

def destroyer():
    rootA.destroy() #When the window closes
    root.destroy()

if __name__ == '__main__':
    root = AnswerEntry()
    clock(root)
    root.mainloop()

請下次再寫一個新的問題,以便更多的人知道。 由於您的EDIT是一個完全不同的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM