Я хочу запросить размер виджета после изменения его содержимого. Вот демонстрация:
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
должны выполняться только тогда, когда больше нечего делать:
Регистрирует обратный вызов, который вызывается, когда система простаивает. Обратный вызов будет вызван, больше нет событий для обработки в mainl oop.
И все же callback2
явно выполняется перед размер метки изменяется, потому что вывод программы следующий:
label width: 1
Даже добавление вызова к update_idletasks()
не меняет этот вывод. Только если win.update_idletasks()
вызывается в как callback1
, так и callback2
, печатается правильный размер. Я действительно не понимаю, почему нужно вызывать его дважды.
Вопрос
Почему callback2
выполняется до изменения размера метки? Как я могу гарантировать, что label.winfo_width()
возвращает правильный размер?
Ограничения
Основная цель этого вопроса - понять, как / когда tkinter выполняет (простаивающие) задачи. Я хочу узнать, как правильно ставить задачи в очередь, чтобы они выполнялись только после обновления GUI. Меня не очень интересуют обходные пути, такие как:
- Я бы предпочел избегать использования
update()
, потому что я не понимаю, как это вызывает условия гонки или когда безопасно использовать. (В моем реальном коде все это будет выполняться внутри обработчика событий, чего следует избегать в документации.) - Я также хочу избежать использования события
<Configure>
. Это связано с тем, что может быть произвольное количество виджетов, меняющих размер, и я не могу разумно ожидать, что я привяжу обработчики событий ко всем их <Configure>
событиям. Мне действительно просто нужен способ выполнить функцию обратного вызова после того, как все изменение размера было выполнено.