Я собираюсь процитировать PyGTK FAQ :
Вы создали индикатор выполнения внутри окна, затем запускаете цикл, который выполняет некоторую работу:
while work_left:
...do something...
progressbar.set_fraction(...)
Вы заметите, что окно даже не отображается, или если оно это делает, индикатор выполнения остается замороженным до конца задачи. Объяснение простое: gtk управляется событиями, и вы отбираете управление у основного цикла gtk, тем самым не позволяя ему обрабатывать обычные события обновления графического интерфейса.
Самое простое решение состоит в том, чтобы временно возвращать контроль gtk каждый раз, когда изменяется ход:
while work_left:
...do something...
progressbar.set_fraction(...)
while gtk.events_pending():
gtk.main_iteration()
Обратите внимание, что с этим решением пользователь не может выйти из приложения (gtk.main_quit не будет работать из-за нового цикла [gtk.main_iteration ()]), пока ваша тяжелая работа не будет завершена.
Другое решение состоит в использовании функций простоя gtk, которые вызываются главным циклом gtk всякий раз, когда ему нечего делать. Таким образом, gtk находится под контролем, и функция простоя должна сделать немного работы. Он должен вернуть True, если есть еще работа, в противном случае False.
Лучшее решение (у него нет недостатков) было указано Джеймсом Хенстриджем. Генераторы python используют функции простоя, чтобы Python автоматически сохранял для нас состояние. Это выглядит так:
def my_task(data):
...some work...
while heavy_work_needed:
...do heavy work here...
progress_label.set_text(data) # here we update parts of UI
# there's more work, return True
yield True
# no more work, return False
yield False
def on_start_my_task_button_click(data):
task = my_task(data)
gobject.idle_add(task.next)
Выше 'while' - просто пример. Единственные правила заключаются в том, что он должен выдавать True после выполнения небольшой работы, и есть еще много работы, и он должен давать False, когда задача выполнена.