我希望在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框(并因此一直保持激活状态),只有当它们已满时,执行按钮的命令,但我只想在它们满时激活它。 有没有更好的方法来实现这一目标?谢谢!
答案 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)可能仍然非常快。