0

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

目前,我有它,以便每次输入新输入时,它都会检查它们是否都已满。但是,这会变得低效,因为如果输入一个长字符串,它将检查每个字母(因为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

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

4

2 回答 2

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) # <---
于 2013-06-19T00:56:36.520 回答
1

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

对于 3000 个条目小部件,在我的 Mac 上,我可以在每次击键时在大约 3 毫秒内检查所有小部件的长度。假设我有一个要检查的小部件列表。如果您遍历所有小部件及其子级,这将花费更长的时间,这 a) 毫无意义,并且 b) 可能仍然非常快。

于 2013-06-19T01:08:54.577 回答