当我调用update_idletasks()时,Tkinter有时会冻结

问题描述 投票:1回答:2

我正在整理一个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中

一些说明:

  • 它不会持续冻结,看起来很随意,但似乎确实每4到5次尝试就会发生。
  • 冻结的长度似乎也是随机的,有时是30秒,有时是几分钟。
  • 如果我在冻结时单击其他按钮,它将在冻结停止后执行这些操作
  • 通常如果我从pycharm终止应用程序,框架将在应用程序终止之前加载一秒钟。

我不知道从这里可以去哪里,关于我可以研究的事情的任何指示?

编辑:所以我经历并删除了任何更新的调用,现在它只是在这段代码后挂起,我假设在主循环更新步骤但我不确定如何检查该假设,这个_handle_events_button函数是直接从事件按钮,所以在此之后不再有我的代码了。

编辑2:如果我保留update_idletasks并在其上运行一个分析器,当它正常工作时它看起来像这样:

enter image description here

在挂起的运行中,一切看起来都是一样的,除了方法“呼叫”花费大约1000毫秒,它需要25000毫秒或更多,与“呼叫”的呼叫次数大致相同。

编辑3:我已经在print语句的输出中添加了。此外,我不能将任何此函数放入单独的线程,因为它只是准备小部件。

python tkinter
2个回答
0
投票

如果你有一个持久的事件循环运行,你不想调用update / update_idletasksThese functions are the alternative to a persistent event loop.

当您从事件处理程序调用它时,您实际上是在运行临时嵌套事件循环。在处理所有适用的待处理事件之前会阻塞代码 - 并且还可能产生其他不良副作用,因为当前事件处理程序应执行的操作只有一半完成,而其他代码可能会看到应用程序处于不一致状态。


0
投票

所以经过大量的敲击我的脑袋后,我想我想出来了。首先,看起来tkinter加载小部件的速度很慢,不确定这是因为我有多少个小部件(不是很多小部件,可能少于100个,每个框架可能少于50个)或者由于我正在做的所有子类化(可能比我应该做的更多)。它烦人但现在可行。

似乎解决偶尔冻结的原因是停止使用tkcalender datepicker小部件。一旦我为一个基于入口和框架的自定义小部件切换出来,事情就会停止冻结,现在每次加载一个框架它需要相当多的时间,仍然有点慢,但是一致,这就是我真正需要的目前。

© www.soinside.com 2019 - 2024. All rights reserved.