GUI не обновляется из другого потока при использовании PyGtk

Я использую PyGTK для создания приложения с графическим интерфейсом. Я хочу обновить виджет textview из другого потока, но виджет не обновляется каждый раз, когда я пытаюсь обновить. Что я должен сделать, чтобы получить надежное обновление графического интерфейса?

4 ответа

Решение

GTK+ не является потокобезопасным, поэтому вам не следует просто вызывать методы обновления GUI из других потоков. Для этой цели можно использовать glib.idle_add (или gobject.idle_add в более старых версиях PyGTK).

Вместо того чтобы писать:

label.set_text("foo")

вы бы написали:

glib.idle_add(label.set_text, "foo")

что вызывает вызов функции в очереди в GTK+.

Если вам нужно запустить несколько операторов, часто проще заключить их в функцию:

def idle():
    label1.set_text("foo")
    label2.set_text("bar")
glib.idle_add(idle)

Убедитесь, что функция передана idle_add не возвращается True; в противном случае он снова будет поставлен в очередь.

Редактировать: как Дэниел указал, вам нужно позвонить gtk.gdk.threads_init() сначала в любом месте вашей программы.

Как указывалось в предыдущих ответах, GTK не является "потокобезопасным", но он "поддерживает потоки" - см. Эту страницу в разделе "Потоки": http://library.gnome.org/devel/gdk/unstable/gdk-Threads.html.

Чтобы изменить виджеты GTK из другого потока, вы должны использовать блокировку GTK. Вызов gtk.threads_init() сразу после импорта модуля gtk, а затем вы можете обновить его так:

gtk.threads_enter()
# make changes...
gtk.threads_leave()

Обратите внимание, что вышеописанное не будет работать в Windows (см. Ссылку выше). В Windows вы должны использовать gobject.idle_add() как объяснено выше, но не забудьте поставить gobject.threads_init() непосредственно после импорта gobject в ваш код! Функция idle_add() выполнит само обновление в основном потоке (потоке, выполняющем gtk.main()).

То же самое может быть достигнуто с помощью метода gobject.idle_add, синтаксис которого такой же, как и выше, вы должны импортировать модуль gobject

То, что сказал Йоханнес, верно, однако, поскольку GTK является оберткой для вещей glib и gobject, вы на самом деле захотите использовать gtk.idle_add(). Нет необходимости в ненужном импорте.

Другие вопросы по тегам