python - Python/tkinter:一次命令执行两次更改标签
问题描述
假设我们有三个 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
一旦完成所有要求,该命令就会影响目标小部件。因为我确实看到标签闪烁“正在执行”,但立即显示“完成”。对这种情况有什么想法吗?任何建议表示赞赏。谢谢!
解决方案
我怀疑命令 refresh_table 一旦完成所有需求就会影响目标小部件。
确实如此。每次mainloop
输入时,您的 GUI 都会更新。当您的函数refresh_table
运行时,不会处理任何事件(例如更新您的标签),因为这些事件仅在空闲时间发生(因此它们的另一个名称是“空闲任务”)。但是因为 UI 在执行期间不是空闲的refresh_table
,所以直到函数中的所有代码都完成(因为你的整个程序在同一个线程上运行)并且重绘事件处于挂起状态之前,事件循环才可访问。您可以通过调用来解决此问题update_idletasks
,这将立即处理所有待处理的事件。会这样做(假设您的主窗口被调用parent
并且您在类定义中,重要的是您update_idletasks
在更改标签文本后直接调用主窗口):
def refresh_table(self, args):
label['text'] = 'Executing'
self.parent.update_idletasks()
print_data()
label['text'] = 'Done'
还有update
, 它不仅会调用挂起的空闲任务,而且基本上会处理所有要处理的事情,这在您的情况下是不必要的。在这个问题的答案中可以找到一个很好的解释为什么update_idletasks
最可取。update
推荐阅读
- javascript - 当所选下拉选项的值大于 0 时,激活提交按钮
- sdn - 更改 Open vSwitch 的流表大小
- spring - Spring RestTemplate 交换返回 204 和邮递员 200
- sql - 存储过程工作正常,但突然停止某些值
- ios - 如何在 iOS 图表中向数据圈插入插图
- java - 有没有办法从“onResponse”函数中接收响应对象?
- jquery - 分页链接更新查询失败
- javascript - 如何在 onClick 反应中播放 mp3?
- python - 如何在 PyCharm 项目视图中隐藏 venv
- sqlplus - 在 sqlplus 中添加特殊字符