当所有条目都满时,Python Tkinter会做一些事情

时间:2013-06-19 00:18:40

标签: python graphics tkinter

我希望在tk.Toplevel实例中的每个输入框都已满时运行命令。

目前,我有这样一来,每次输入新输入时,都会检查是否所有输入都已满。但是,这会变得效率低下,因为如果输入一个长字符串,它将检查每个字母(因为每次更改Entry时都会执行一个Entry command)。此外,我将使用多个Entry框(总共约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

基本上命令应该做的是激活一个按钮(我希望它只在每个条目被填满时使用)。或者,我可以检查Button按下时的Entry框(并因此一直保持激活状态),只有当它们已满时,执行按钮的命令,但我只想在它们满时激活它。 有没有更好的方法来实现这一目标?谢谢!

2 个答案:

答案 0 :(得分: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) # <---

答案 1 :(得分:1)

它并不像你想象的那么低效。尝试测量检查30个(甚至300个或3000个)条目小部件的内容所需的时间。你可能会感到惊讶。在发现延迟之前,您可能需要每分钟输入几百个单词。

对于3000个入口小部件,在我的Mac上,我可以在每次击键时在大约3ms内检查所有这些小部件的长度。这个,假设我有一个要检查的小部件列表。如果你遍历所有小部件和他们的孩子,这将是需要更长的时间,这是a)毫无意义,并且b)可能仍然非常快。