python-2.7 - 如果在程序的其他地方调用了 after_idle,则单击时 tkinter 选项菜单会挂起
问题描述
我有一个 GUI,可以在消息到达时串行处理消息并由多个 websocket 排队。该函数使用 after_idle 为自身设置一个回调以使该过程永久化,如下所示:
def process_queue(self, flush=False):
'''
Check for new messages in the queue periodically.
Sets up callback to itself to perpetuate the process.
'''
if flush:
while not self.queue.empty():
self.get_msg()
else:
self.get_msg()
self.master.after_idle(self.process_queue)
我OptionMenu
在 GUI 上有一个小部件,它挂起并导致程序在单击时崩溃:
self.plotind = tk.StringVar()
self.plotind.set('MACD')
options = ['MACD']
self.indopts = tk.OptionMenu(self.analysis_frame, self.plotind, *[option for option in options])
self.indopts.grid(row=1, column=1)
如果我将 更改after_idle()
为 just after()
,它可以正常工作。
我认为这是因为单击 anOptionMenu
实际上会设置它自己的after_idle()
调用来打开菜单,然后它会与我在process_queue()
.
如果需要,我当然可以after()
在我的函数中使用 - 它在处理队列时可能不是最佳速度,但这不是世界末日。但是有没有更优雅的方法来处理这个问题?当然,大多数 GUI 应该能够处理在存在after_idle()
时调用某处的情况吗?OptionMenu
解决方案
一般来说,您不应该after_idle
从名为 via 的函数中调用after_idle
。
原因如下:
一旦 tkinter 开始处理空闲队列,它不会停止,直到队列为空。如果队列中有一个项目,tkinter 会拉出该项目并调用该函数。如果该函数将某些内容添加到队列中,则队列不再为空,因此 tkinter 会处理新项目。如果这个新项目将某些东西放在空闲队列中,那么 tkinter 将处理它,依此类推。队列永远不会变空,并且 tkinter 永远不会有机会做任何事情,除了服务这个队列。
一个常见的解决方案是使用after
两次,以便队列有机会变空,从而允许 tkinter 处理其他非空闲事件。
例如,而不是这个:
self.master.after_idle(self.process_queue)
... 做这个:
self.master.after_idle(self.master.after, 1, self.process_queue)
这会为队列创建一个小窗口,使其变为空,从而允许 tkinter 处理其他“非空闲”事件,例如在self.process_queue
再次调用之前重绘屏幕的请求。
推荐阅读
- java - 查找迭代次数
- python - 如何使用 tf.identity 制作张量列表的副本(而不仅仅是单个张量)?
- python - Python Selenium --user-data-dir 选项错误:无法删除旧的 devtools 端口文件
- sql-server - 在同一个查询中使用 JOIN 和 OFFSET
- python-3.x - Windows上的HDF5充气错误
- gmail-api - 创建发布者主题时“用户无权执行此操作”
- android - 谷歌登录在华为的“Mate 9”中无法使用,但在任何其他设备上都可以正常使用
- json - 如何在 Go 中构建递归的结构切片?
- python - 对两个子查询的总和进行排序
- .net - Visual Studio 中缺少 package.appxmanifest