Как поставить задачу в очередь ПОСЛЕ всех операций по изменению размера виджета? - PullRequest
2 голосов
/ 08 мая 2020

Я хочу запросить размер виджета после изменения его содержимого. Вот демонстрация:

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> событиям. Мне действительно просто нужен способ выполнить функцию обратного вызова после того, как все изменение размера было выполнено.
...