代码之家  ›  专栏  ›  技术社区  ›  appusajeev

使用pygtk时,没有从其他线程更新GUI

  •  6
  • appusajeev  · 技术社区  · 15 年前

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

    4 回复  |  直到 10 年前
        1
  •  12
  •   Community CDub    13 年前

    GTK+不是线程安全的,因此您不应该简单地从其他线程调用GUI更新方法。 glib.idle_add (或gobject.idle_外接程序旧的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() 在你的程序中的任何地方。

        2
  •  2
  •   SiHa Yousef_Shamshoum    10 年前

    如前面的答案所述,GTK不是“线程安全的”,但它是“线程感知的”-请参阅线程上的本页: https://developer.gnome.org/gdk2/stable/gdk2-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()的线程)中执行更新本身。

        3
  •  -1
  •   saintah    15 年前

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

        4
  •  -1
  •   excid3    14 年前

    Johannes说的是正确的,但是由于GTK是glib和gobject的包装器,所以您实际上需要使用gtk.idle-add()。不需要不必要的进口。