使用PyGtk时,GUI未从其他线程更新

时间:2010-01-14 19:04:40

标签: python multithreading pygtk

我正在使用PyGTK来构建GUI应用程序。我想从另一个线程更新textview小部件,但每次尝试更新时小部件都不会更新。我该怎么做才能获得可靠的GUI更新?

4 个答案:

答案 0 :(得分:12)

GTK +不是线程安全的,因此您不应该简单地从其他线程调用GUI更新方法。 glib.idle_add(或旧的PyGTK版本中的gobject.idle_add)可用于此目的。

而不是写作:

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;否则它会再次排队。

编辑:正如Daniel指出的那样,您需要先在程序中的任何位置拨打gtk.gdk.threads_init()

答案 1 :(得分:2)

如前面的答案中所述,GTK不是“线程安全的”,但它是“线程感知的” - 请参阅线程上的此页面:https://developer.gnome.org/gdk2/stable/gdk2-Threads.html

为了从另一个线程修改GTK小部件,您必须使用GTK的锁定。导入gtk模块后立即调用gtk.threads_init(),然后您可以像这样更新:

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

请注意,上述内容在Windows上无效(请参阅上面的链接)。在Windows上,您必须使用gobject.idle_add(),如上所述,但不要忘记在代码中导入gobject后直接放置gobject.threads_init()! idle_add()函数将在主线程(运行gtk.main()的线程)中执行更新。

答案 2 :(得分:-1)

使用gobject.idle_add方法可以实现同样的方法,其语法与上面相同,你必须导入模块gobject

答案 3 :(得分:-1)

Johannes所说的是正确的,但是由于GTK是glib和gobject事物的包装器,你实际上想要使用gtk.idle_add()。不需要不必要的进口。