PyGtk线程在主要退出之前没有运行

时间:2011-10-21 13:32:05

标签: python gtk

我一直试图将此问题排序数小时,在网上搜索并阅读文档并没有帮助。我正在尝试在单独的线程中执行长时间运行的任务,并在UI中的进度条中显示进度。新线程已启动,但在主循环退出之前没有给出任何时间,我在Gdk.threads_init()之前调用Gtk.main并且我已使用Gdk.threads_enter()Gdk.threads_leave()包围了UI调用。

下面的代码重现了这个问题,单击“开始”按钮没有任何效果,但是一旦窗口关闭并且主循环退出,我看到第二个线程正在工作(即我看到打印语句相隔半秒)

class App(Gtk.Window):

    def __init__(self):
        super(App, self).__init__()
        self.connect("destroy", self.on_destroy)

        self.layout = Gtk.VBox()
        self.progress = Gtk.ProgressBar()
        self.layout.pack_start(self.progress, False, False, 0)

        self.set_size_request(100,100)

        self.go_button = Gtk.Button("Start")
        self.go_button.connect("clicked", self.do_work_subclass)
        self.layout.pack_start(self.go_button, False, False, 0)

        self.add(self.layout)
        self.show_all()



    def on_destroy(widget, event):
        Gtk.main_quit()

    def do_work(self, widget):
        def worker_thread():
            so_far = 0
            while so_far < 10:
                time.sleep(0.5)
                print("work so far: %s" % so_far)
                Gdk.threads_enter()
                try:
                    if so_far > 0:
                        self.progress.set_fraction(so_far / 10.0)
                finally:
                    Gdk.threads_leave()
                so_far += 1
        threading.Thread(target=worker_thread).start()


if __name__ == "__main__":
    app = App()
    Gdk.threads_init()
    Gdk.threads_enter()
    Gtk.main()
    Gdk.threads_leave() 

这可能与我使用Gtk3的事实有关吗?

1 个答案:

答案 0 :(得分:4)

在发布问题之前花了好几个小时试图找到答案,我在发布后的几分钟内找到了答案。事实证明(从here)您需要致电GLib.threads_init()的GTK3,代码在调用from gi.repository import GLib之前使用初始GLib.threads_init()Gtk.main() ,所以代码的工作版本如下所示:

from gi.repository import Gtk,Gdk, GLib
import threading 
import time

class App(Gtk.Window):

    def __init__(self):
        super(App, self).__init__()
        self.connect("destroy", self.on_destroy)

        self.layout = Gtk.VBox()
        self.progress = Gtk.ProgressBar()
        self.layout.pack_start(self.progress, False, False, 0)

        self.set_size_request(100,100)

        self.go_button = Gtk.Button("Start")
        self.go_button.connect("clicked", self.do_work)
        self.layout.pack_start(self.go_button, False, False, 0)

        self.add(self.layout)
        self.show_all()



    def on_destroy(widget, event):
        Gtk.main_quit()

    def do_work(self, widget):
        def worker_thread():
            so_far = 0
            while so_far < 10:
                time.sleep(0.5)
                print("work so far: %s" % so_far)
                Gdk.threads_enter()
                try:
                    if so_far > 0:
                        self.progress.set_fraction(so_far / 10.0)
                finally:
                    Gdk.threads_leave()
                so_far += 1
        threading.Thread(target=worker_thread).start()



if __name__ == "__main__":
    app = App()
    GLib.threads_init()
    Gdk.threads_init()
    Gdk.threads_enter()
    Gtk.main()
    Gdk.threads_leave()