Python/tkinter:一次命令执行两次更改标签
Posted
技术标签:
【中文标题】Python/tkinter:一次命令执行两次更改标签【英文标题】:Python/tkinter: Change label twice with one command execution 【发布时间】:2019-06-04 00:16:55 【问题描述】:假设我们有三个 tkinter 小部件:一个标签、一个树视图和一个选项菜单(以下简称为“菜单”)。一旦选择了一个选项,我就成功地使菜单执行了一个功能。简要函数如下所示:
def data_process():
# do something takes time
def print_data()
data_process() # do something takes time too
# print stuff to treeview
def refresh_table(self, args):
label['text'] = 'Executing' # change label text to Executing
print_data() # a func. which takes time to run
label['text'] = 'Done' # change text to Done
label = tk.Label(parent, text = 'ready')
label.pack()
menu = tk.OptionMenu(parent, var, *list, command = lambda _:refresh_table(self, args))
menu.pack()
table = tk.Treeview(parent)
table.pack()
函数print_data
将打印一些内容到树视图小部件(表格)。标签小部件就像一个状态栏,告诉用户现在发生了什么。所以我尝试做的工作流程是:
在菜单中选择一个选项并致电refresh_table
。
将标签文本更改为“正在执行”。
执行print_data
并在树形视图中打印内容。
print_data
完成后,将标签更改为“完成”。
事情就是这样。当我选择该选项时,程序会(如预期的那样)做一些事情。但是,标签在开始时并未更改为“正在执行”。相反,当print_data
完成执行(几乎同时)时,它变为“完成”。我怀疑命令refresh_table
会在所有需求完成后影响目标小部件。因为我确实看到标签闪烁“正在执行”,但立即显示“完成”。对这种情况有什么想法吗?任何建议表示赞赏。谢谢!
【问题讨论】:
将标签更改为“正在执行”后尝试调用root.update()
。
@Kamal 先生,谢谢它有效!但我可以进一步问为什么吗?它与线程有关吗?不过只是猜测。再次感谢您。
如果不查看完整代码,我不能肯定地说,但我猜想当refresh_table
函数被调用时,root.mainloop()
没有在执行中,所以对root.update()
的调用就可以完成这项工作.
原来.update
和.update_idletasks
都可以完成这项工作,但有不同的方面。再次感谢您的快速回复!
@Kamal 我只是注意到它可能会让人觉得好像我想直接在我的回答中处理你的评论,在我说update_idletasks
在我看来比@987654335 更好的部分@,但我想明确表示这不是我的意图——我在写答案时没有阅读你的评论。希望我没有冒犯你:-)
【参考方案1】:
我怀疑命令 refresh_table 会在所有要求完成后影响目标小部件。
确实如此。每次输入 mainloop
时,您的 GUI 都会更新。当您的函数 refresh_table
正在运行时,不会处理任何事件(例如更新您的标签),因为这些事件仅在空闲时间发生(因此它们的另一个名称是“空闲任务”)。但是因为在refresh_table
的执行过程中UI 不是空闲的,所以直到函数中的所有代码都完成(因为你的整个程序在同一个线程上运行)并且重绘事件处于挂起状态之前,事件循环是不可访问的。您可以通过调用update_idletasks
来解决此问题,它将立即处理所有未决事件。会这样做(假设您的主窗口称为parent
并且您在类定义中,重要的是您在更改标签文本后直接在主窗口上调用update_idletasks
):
def refresh_table(self, args):
label['text'] = 'Executing'
self.parent.update_idletasks()
print_data()
label['text'] = 'Done'
还有update
,它不仅会调用挂起的空闲任务,而且基本上会处理所有要处理的事情,这在你的情况下是不必要的。 in the answer to this question 可以很好地解释为什么 update_idletasks
比 update
更可取。
【讨论】:
感谢先生清晰而精彩的回答。你的解释和建议对我帮助很大。再次感谢您! 很高兴我能帮上忙 :) 有美好的一天以上是关于Python/tkinter:一次命令执行两次更改标签的主要内容,如果未能解决你的问题,请参考以下文章
[小菜随笔]python tkinter实现简单的ping命令
在 Python(tkinter)中从类的外部更改类的私有属性(标签)
按下按钮后可以更改菜单栏文本吗? (Python,tkinter)