使用PyGtk时,从另一个线程中未更新GUI。

8

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

4个回答

15

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()


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()的线程)中执行更新。

不错的观点。关于这两种方法,另一篇好的写作可以在PyGTK FAQ条目中看到:http://faq.pygtk.org/index.py?file=faq20.006.htp&req=show - Johannes Sasongko

-1

使用gobject.idle_add方法也可以实现相同的效果,其语法与上述相同,您需要导入gobject模块。


-1

Johannes所说的是正确的,但由于GTK是glib和gobject的包装器,您实际上应该使用gtk.idle_add()。不需要进行不必要的导入。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接