繁体   English   中英

如果在程序的其他位置调用after_idle,则单击tkinter选项菜单时将挂起

[英]tkinter optionmenu hangs when clicked if after_idle is called elsewhere in the program

我有一个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)

我在GUI上有一个OptionMenu小部件,该小部件挂起并导致单击该程序时崩溃:

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()更改为after() ,则可以正常工作。

我认为这是因为单击OptionMenu实际上会设置它自己的after_idle()调用来打开菜单,然后该菜单与process_queue()的菜单竞争。

如果需要的话,我当然可以after()函数中使用after() -处理队列可能不是最佳速度,但这不是世界末日。 但是,有没有更优雅的方式来处理此问题? 当然,当存在OptionMenu时,大多数GUI都应该能够处理在某处调用after_idle()

一般来说,你应该不叫after_idle从通过调用函数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之前重self.process_queue屏幕的请求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM