我正在整理一个tkinter gui应用程序,偶尔在加载一个新框架并将其添加到笔记本时,gui将冻结更新的调用。我不确定要为代码提供什么,我有很多子类正在进行所以发布所有这些都会变得荒谬,而且我不确定它是否会有用。
def _handle_events_button(self):
ntbk = self.find_notebook()
print("1: " + str(int(time.time())))
w = EventListDetailsCombo(ntbk)
print("2: " + str(int(time.time())))
w.load()
print("3: " + str(int(time.time())))
w.add_to_notebook(ntbk)
print("4: " + str(int(time.time())))
# clipboard.root.update_idletasks()
print("5: " + str(int(time.time())))
ntbk.select(w)
print("6: " + str(int(time.time())))
印刷品的输出是这样的:
# Working correctly
1: 1555952235
2: 1555952235
3: 1555952235
4: 1555952235
5: 1555952237
6: 1555952237
# Hang / Delay
1: 1555952240
2: 1555952240
3: 1555952240
4: 1555952240
5: 1555952266
6: 1555952266
即没有update_idletasks()的update_idletasks(),所有这些输出都在1-2秒之内。挂起反而发生在mainloop update_idletasks中
一些说明:
我不知道从这里可以去哪里,关于我可以研究的事情的任何指示?
编辑:所以我经历并删除了任何更新的调用,现在它只是在这段代码后挂起,我假设在主循环更新步骤但我不确定如何检查该假设,这个_handle_events_button函数是直接从事件按钮,所以在此之后不再有我的代码了。
编辑2:如果我保留update_idletasks并在其上运行一个分析器,当它正常工作时它看起来像这样:
在挂起的运行中,一切看起来都是一样的,除了方法“呼叫”花费大约1000毫秒,它需要25000毫秒或更多,与“呼叫”的呼叫次数大致相同。
编辑3:我已经在print语句的输出中添加了。此外,我不能将任何此函数放入单独的线程,因为它只是准备小部件。
如果你有一个持久的事件循环运行,你不想调用update
/ update_idletasks
。 These functions are the alternative to a persistent event loop.
当您从事件处理程序调用它时,您实际上是在运行临时嵌套事件循环。在处理所有适用的待处理事件之前会阻塞代码 - 并且还可能产生其他不良副作用,因为当前事件处理程序应执行的操作只有一半完成,而其他代码可能会看到应用程序处于不一致状态。
所以经过大量的敲击我的脑袋后,我想我想出来了。首先,看起来tkinter加载小部件的速度很慢,不确定这是因为我有多少个小部件(不是很多小部件,可能少于100个,每个框架可能少于50个)或者由于我正在做的所有子类化(可能比我应该做的更多)。它烦人但现在可行。
似乎解决偶尔冻结的原因是停止使用tkcalender datepicker小部件。一旦我为一个基于入口和框架的自定义小部件切换出来,事情就会停止冻结,现在每次加载一个框架它需要相当多的时间,仍然有点慢,但是一致,这就是我真正需要的目前。