2

我想在更改其内容后查询小部件的大小。这是一个演示:

import tkinter as tk

win = tk.Tk()

label = tk.Label(win)
label.pack()

def callback1():
    label['text'] = 'hello world'
    win.after_idle(callback2)

def callback2():
    print('label width:', label.winfo_width())

win.after(0, callback1)    
win.mainloop()

根据文档after_idle,只有在无事可做时才应执行排队的回调:

注册一个在系统空闲时调用的回调。回调将被调用,主循环中不再有要处理的事件。

然而,callback2显然是在调整标签大小之前执行的,因为程序的输出是这样的:

label width: 1

即使添加调用update_idletasks()也不会更改此输出。仅当在和中win.update_idletasks()调用时,才会打印正确的尺寸。我真的不明白为什么有必要调用它两次。 callback1 callback2

问题

为什么callback2在调整标签大小之前执行?如何确保label.winfo_width()返回正确的尺寸?

限制

这个问题的主要目标是了解 tkinter 如何/何时执行(空闲)任务。我想了解如何正确地对任务进行排队,以便仅在 GUI 自行更新后才执行它们。我对诸如以下的解决方法并不感兴趣:

  • 我宁愿避免使用update(),因为我不明白它如何导致竞争条件或何时可以安全使用。(在我的真实代码中,所有这些都将在事件处理程序中执行,文档明确指出应该避免这种情况。)
  • 我也想避免使用<Configure>event。这是因为可能有任意数量的小部件在改变大小,并且不能合理地期望我将事件处理程序绑定到它们的所有<Configure>事件。在所有调整大小发生后,我真的只需要一种方法来执行回调函数。
4

0 回答 0