当我调用update_idletasks()

时间:2019-04-22 15:27:49

标签: python tkinter

我正在组装一个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终止应用程序,则框架会在应用程序终止之前加载一秒钟。

我不确定从这里去哪里,是否有任何我可以研究的内容的指针?

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

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

enter image description here

在挂起的运行中,所有内容看起来都一样,除了方法“ call”花费约1000ms而不是花费25000ms或更长时间,并且“ call”的调用次数大致相同。

编辑3:我在打印语句的输出中添加了内容。同样,我不能将任何此函数放入单独的线程中,因为它们都只是在准备小部件。

2 个答案:

答案 0 :(得分:0)

如果您正在运行持久性事件循环,则不要要调用update / update_idletasksThese functions are the alternative to a persistent event loop.

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

答案 1 :(得分:0)

因此,在将我的头撞到桌子上很多次之后,我想我明白了。首先,似乎tkinter加载小部件的速度很慢,不确定这是否是因为我有多少个小部件(加载的每一帧不是全部,可能少于100个,也许少于50个)或由于我正在做的所有子类化(可能比我应该做的还要多)。它很烦人,但目前仍然可行。

似乎可以解决偶发冻结的问题是停止使用tkcalender datepicker小部件。一旦我将其切换为基于条目和基于框架的自定义小部件,事情就停止了冻结,现在每次加载框架所需的时间几乎相同,虽然仍然很慢,但始终如一,这是我真正需要的现在。