2013-02-23 411 views
1

我正在創建一個「定義測試」類型的程序(用戶爲每個單詞輸入單詞,詞性和同義詞,然後程序測驗用戶在所述信息上)。 在最後的窗口(quizzing窗口),我有一個窗口的佈局是這樣的:Tkinter:打開另一個窗口的按鈕(並關閉當前窗口)

1/25 What is the definition of _word_? # number out of total + prompt 
Definition: _entry_ # entry fields for information 
Part of Speech: _entry_ 
Next Help Quit # buttons; 'Next' checks the info and goes to the next word 
# 'Help' shows the info and goes to the next word 
# 'Quit' force-quits the program 
Tries Left: 5 # how many tries before the info is shown 

我的問題是「幫助」按鈕。通常,只需輸入5次錯誤信息,它將成功創建「幫助」窗口;然而,它仍然保留原來的詞(無法回答的那個詞),開放。當這個新窗口關閉時,新的單詞將顯示出來,但會有兩個窗口:新單詞+舊單詞。此外,「幫助」按鈕本身引發錯誤:

>>> 

Traceback (most recent call last): 
    File _filepath_, line 455, in <module> 
    main() 
    File _filepath_, line 68, in main 
    test(screenDim, test_dict) 
    File _filepath_, line 451, in test 
    root.destroy() 
    File "C:\Python2.7.3\lib\lib-tk\Tkinter.py", line 1728, in destroy 
    self.tk.call('destroy', self._w) 
TclError: can't invoke "destroy" command: application has been destroyed 

這裏是我的test功能(我修剪了一下代碼,因此它更容易發現問題):

def test(screenDim, test_dict): 
    class TestWords: 
     def __init__(self, master): 
      w, h = screenDim[0], screenDim[1] 
      rootW, rootH, xPos, yPos = int(float(w)/3), int(float(h)/4), w/2 - (w/6), h/2 - (h/8) 
      self.frame = Frame(master) 
      self.frameB = Frame(self.frame) 
      self.frameE = Frame(self.frame) 
      self.posE = Entry(self.frameE, width = 50, justify = CENTER) 
      self.defE = Entry(self.frameE, width = 50, justify = CENTER) 
      self.posE.grid(row = 1, column = 2, pady = 5) 
      self.defE.grid(row = 2, column = 2, pady = 5) 
      # there are a few other widgets/frames that don't pertain to this problem 
      self.goButton = Button(self.frameB, text = 'Next', command = self.getInfo, width = 10) 
      self.helpButton = Button(self.frameB, text = 'Help', command = self.getHelp, width = 10) 
      self.quitButton = Button(self.frameB, text = 'Quit', command = self.quitBox, width = 10, fg = 'red') 
      self.goButton.grid(row = 1, column = 1, padx = 10) 
      self.helpButton.grid(row = 1, column = 2, padx = 10) 
      self.quitButton.grid(row = 1, column = 3, padx = 10) 
      master.geometry("%sx%s+%s+%s" % (rootW, rootH, xPos, yPos)) 
      self.frameE.grid(row = 3, pady = 5) 
      self.frameB.grid(row = 4, padx = rootW/4 - 60, pady = 5) 
      self.frame.grid() 
     def quitBox(self): 
      import sys 
      sys.exit('Program Terminated.') 
     def getHelp(self): 
      triesLeft = 0 
      self.frame.quit() 
      root.destroy() 
     def getInfo(self): 
      info = (self.posE.get(), self.defE.get()) 
      self.frame.quit() 
      return info 
    class GetHelp: 
     def __init__(self, master): 
      w, h = screenDim[0], screenDim[1] 
      rootW, rootH, xPos, yPos = int(float(w)/4), int(float(h)/4), w/2 - (w/8), h/2 - (h/8) 
      self.frame = Frame(master) 
      self.frameB = Frame(self.frame) 
      self.goButton = Button(self.frameB, text = 'Next', command = self.frame.quit, width = 10) 
      self.quitButton = Button(self.frameB, text = 'Quit', command = self.quitBox, fg = 'red', width = 10) 
      self.goButton.grid(row = 1, column = 1, padx = 5) 
      self.quitButton.grid(row = 1, column = 2, padx = 5) 
      self.frameB.grid(row = 2, padx = rootW/4 - 20, pady = 5) 
      master.geometry("%sx%s+%s+%s" % (rootW, rootH, xPos, yPos)) 
      self.frame.grid() 
      # again, a few widgets were removed for brevity 
     def quitBox(self): 
      import sys 
      sys.exit('Program Terminated.') 
    n, words, reviewWords = len(test_dict.keys()), test_dict.keys(), [] 
    shuffle(words) 
    for i in range(n): 
     word, triesLeft = words[i], 4 
     while triesLeft >= 0: 
      root = Tk(className = ' Definition Tester') 
      root.columnconfigure(0, weight=1) 
      root.rowconfigure(0, weight=1) 
      app = TestWords(root) 
      root.mainloop() 
      try: 
       info = app.getInfo() 
      except TclError: 
       info = ('', '') 
      if info[0] == test_dict[word][0] and info[1] in test_dict[word][1]: 
       del words[i] 
       root.destroy() 
       break 
      elif triesLeft == 0: 
       reviewWords.append(word) 
       root = Tk(className = ' Definition Tester') 
       root.columnconfigure(0, weight=1) 
       root.rowconfigure(0, weight=1) 
       app = GetHelp(root) 
       root.mainloop() 
       break 
      else: 
       triesLeft -= 1 
       root.destroy() 

的在剩下0次嘗試後,程序會自動顯示幫助窗口。因此,「幫助」按鈕將triesLeft設置爲0.但是,這似乎並未打開窗口。謝謝!

+0

你是怎麼調用'test'函數的? I.E.有什麼論點? – 2013-02-23 16:34:51

+0

@SamMussmann'test'有兩個參數:'screenDim'和'test_dict'。 'screenDim'是一個元組,屏幕尺寸爲:'(width,height)'; 'test_dict'是一個格式如下的字典:'{_word_:[_part of speech_,[_synonyms_]],...}'。它由函數'main'調用(這可以在回溯中看到)。我相信這個問題不在於函數調用/參數傳遞,因爲如果我刪除了「幫助」功能,它將完美運行。此外,該功能本身完美運行,直到使用「幫助」功能。 – 2013-02-23 16:37:54

回答

2

您需要重新構建您的解決方案,以便您只創建一個根窗口,並且只運行單個實例mainloop。不要一遍又一遍地創建和銷燬根窗口,而是創建並銷燬Toplevel的實例。 Tkinter根本不是爲了創建和銷燬多個根窗口而設計的。

+0

我該怎麼做?我從來沒有使用'Toplevel'小部件。 – 2013-02-23 16:49:38

+0

另外,做'root = Tk()','app = Toplevel(root)',最後'app.mainloop()'打開兩個窗口......我只想打開一個窗口。在我的「幫助」功能中,我希望它關閉當前窗口和一個新窗口,而不是打開兩個窗口。 – 2013-02-23 17:03:15