2017-02-26 41 views
1

我正在爲學校做一個倒計時(如電視節目)項目,其中涉及一小段時間,用戶在tkinter Text()條目(在時間限制下)輸入響應。感謝此網站上的以前的回答,我知道如何製作屏幕上的tkinter計時器,並且我使用了一個非常基本的線程設備,將它與用戶的Text()輸入窗口同時放置。爲什麼銷燬tkinter上的兩個不同的主循環窗口會凍結程序?

它工作正常,如果我不打擾關閉時鐘,當用戶儘早關閉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 

我也搞不清楚爲什麼第二個窗口沒有出現中間無看似隨機的打印語句。我嘗試了谷歌搜索這一切,但沒有成功;這是一個很小的問題。

EDIT(我感到很困惑):

我知道有人已經回答了這個問題,我把它的偉大工程 - 無論是關閉其中的一個時,窗口自動關閉 - 但我無法得到它一起工作我的倒計時程序,因爲我對類的知識是朦朧的,我用一個窗口的類(這是我設法讓網格方法工作的唯一方法)。

原理是一樣的,所以我錯誤地認爲我可以弄明白,但關於運行涉及另一個班級的課程讓我難倒了。兩個窗口的內容混亂了(例如,一個窗口的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'thingy)。 我沒有試圖讓這些窗口同時運行,因爲我做錯了,它會混淆問題。

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

+0

因爲在應用程序中有多個'mainloop()'會導致問題。 – TigerhawkT3

回答

1

更多的時候,因爲它是爲更好的命名空間嘗試僅僅導入Tkinter的傳統知識。這個答案是爲了解決你的編輯。

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

請下次再寫一個新的問題,讓更多的人可以到它。由於你的編輯是一個完全不同的問題。

+0

Thanks @abcd;將確保下次單獨提問! –

+0

感謝您的理解 – abccd

3

您不能有超過1 mainloop()。即使您使用線程,也不會造成問題。但是您可以有多個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()

+0

謝謝!我不認爲你對我如何通過編輯過的代碼實現相同的目標有所瞭解(即當涉及到另一個類時)? –

+0

@LauraCookson我只需要一些信息:你的第一個函數'conundrumClock'什麼都不做,你的名字空間有點亂,你的代碼的某些部分使用'tk.Tk'和'tk.Button',你可以得到通過'import tkinter as tk',而你的代碼的一部分使用'Label'和'W',你只能通過'tkinter import *'來完成這兩個操作通常不是一個好主意,因爲它與命名空間混淆。還有一件事是'中心(根)'做什麼?它既不是一個功能也不是一個命令 – abccd

+0

看到我的新答案 – abccd

相關問題