2013-06-19 46 views
0

我想在每個條目框在tk.Toplevel實例中已滿時運行命令。Python Tkinter做所有條目滿時的東西

目前,我擁有它,所以每次輸入新的輸入時,它都會檢查它們是否全部已滿。但是,這會變得效率低下,因爲如果輸入一個長字符串,它將檢查每個字母(因爲每次更改條目時都會執行一個條目的command)。另外,我還有大量的輸入框(總共大約30個)將被使用,所以這將變得非常低效。

are_EntriesFull = lambda master: all(bool(widget.get()) for widget in filter(lambda s: isinstance(s, tk.Entry), findAllWidgets(master))) 

_packingWidgets = (tk.Tk, tk.Toplevel, tk.Frame) 

def findAllWidgets(master, widgetsFound = None): 
    '''Returns all of the widgets in a packing instance''' 
    if widgetsFound is None: 
     widgetsFound = [] 
    subWidgets = master.grid_slaves() 
    for widget in subWidgets: 
     widgetsFound.append(widget) 
     if isinstance(widget, _packingWidgets): 
      widgetsFound.extend(findAllWidgets(widget, widgetsFound)) 
    return widgetsFound 

class GetWord: 

    '''Window to get input from the user and create an entry for the word''' 
     def __init__(self, master, current, total): 
      self.master, self.current, self.total, self.mainFrame = master, current, total, tk.Frame(master) 
      self.master.title(STANDARD_TITLE) 
      self.wordFrame, self.typeFrame, self.infoFrame, self.buttonFrame = tk.Frame(self.mainFrame), tk.Frame(self.mainFrame), tk.Frame(self.mainFrame), tk.Frame(self.mainFrame) 
      self.word = tk.StringVar(self.wordFrame) 
      self.wordLabel = tk.Label(self.wordFrame, text = "{}/{}) Word:".format(self.current, self.total), justify = tk.CENTER) 
      self.activateButton = lambda: self.okButton.configure(state = tk.ACTIVE) if are_EntriesFull(self.master) else None 
      self.wordEntry = tk.Entry(self.wordFrame, width = 50, justify = tk.CENTER, textvariable = self.word, command = self.activateButton) 
        # bunch of other code 

基本上什麼命令應該做的是激活按鈕(我想這隻有當每個條目被填充使用)。或者,我可以檢查按鈕被按下時的輸入框(並且始終保持激活狀態),並且只有當它們已滿時才執行按鈕的命令,但是我只想在滿足時激活它。 有沒有更好的方法來完成這個?謝謝!

回答

1

這並不像您認爲的那樣低效。嘗試測量需要多長時間檢查30個(甚至300個或3000個)條目窗口小部件的內容。你可能會感到驚訝。在您注意到延遲之前,您可能必須每分鐘輸入幾百個字。

對於3000個條目小部件,在我的Mac上,我可以在每個按鍵上約3毫秒檢查它們的全部長度。這,假設我有一個小部件列表來檢查。如果你遍歷所有小部件和他們的孩子,這將花費更長的時間,這是a)毫無意義的,b)可能仍然非常快。

+0

事實證明,我沒有看到正確的信息......而不是'tk.Entry(...,command = self.activateButton)',我不得不使用'self.master.bind(「 「,lambda事件:self.activateButton())',但仍然是相同的想法。不過謝謝! –

1

保存findAllWidgets的結果並重新使用該結果,而不是每次調用findAllWidgets

#are_EntriesFull = lambda master: all(bool(widget.get()) for widget in filter(lambda s: isinstance(s, tk.Entry), findAllWidgets(master))) 
are_EntriesFull = lambda entries: all(bool(widget.get()) for widget in entries) # <--- 

_packingWidgets = (tk.Tk, tk.Toplevel, tk.Frame) 

def findAllWidgets(master, widgetsFound = None): 
    '''Returns all of the widgets in a packing instance''' 
    if widgetsFound is None: 
     widgetsFound = [] 
    subWidgets = master.grid_slaves() 
    for widget in subWidgets: 
     widgetsFound.append(widget) 
     if isinstance(widget, _packingWidgets): 
      widgetsFound.extend(findAllWidgets(widget, widgetsFound)) 
    return widgetsFound 

class GetWord: 

    '''Window to get input from the user and create an entry for the word''' 
     def __init__(self, master, current, total): 
      self.master, self.current, self.total, self.mainFrame = master, current, total, tk.Frame(master) 
      self.master.title(STANDARD_TITLE) 
      self.wordFrame, self.typeFrame, self.infoFrame, self.buttonFrame = tk.Frame(self.mainFrame), tk.Frame(self.mainFrame), tk.Frame(self.mainFrame), tk.Frame(self.mainFrame) 
      self.word = tk.StringVar(self.wordFrame) 
      self.wordLabel = tk.Label(self.wordFrame, text = "{}/{}) Word:".format(self.current, self.total), justify = tk.CENTER) 
      self.activateButton = lambda: self.okButton.configure(state = tk.ACTIVE if are_EntriesFull(all_entries) else tk.DISABLED) # <--- 
      self.wordEntry = tk.Entry(self.wordFrame, width = 50, justify = tk.CENTER, textvariable = self.word, command = self.activateButton) 
        # bunch of other code 

      ... 

      all_entries = findAllWidgets(self.master) # <---