PyGtk 线程在 main 退出之前不会运行

发布于 2024-12-11 11:22:34 字数 1624 浏览 0 评论 0原文

我已经尝试解决这个问题几个小时了,搜索网络并阅读文档并没有帮助。我正在尝试在单独的线程中执行长时间运行的任务,并在 UI 的进度栏中显示进度。新线程已启动,但在主循环退出之前不会给出任何时间,我在 Gtk.main 之前调用了 Gdk.threads_init() ,并且我已将 UI 调用包围起来Gdk.threads_enter()Gdk.threads_leave()

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

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 有关吗?

I've been trying to sort this problem for hours now, scouring the web and reading the documentation hasn't helped. I'm trying to perform a long running task in a separate thread and display the progress in a progress bar in the UI. The new thread is started but is not given any time until the main loop quits, I have called Gdk.threads_init() before Gtk.main and I have surrounded UI calls with Gdk.threads_enter() and Gdk.threads_leave().

The following code reproduces the problem, clicking on the 'start' button has no effect, but once the window is closed and the main loop quits I see the second thread doing work (i.e I see the print statements half a second apart)

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

Could this be related to the fact that I am using Gtk3?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风轻花落早 2024-12-18 11:22:34

在发布问题之前花了几个小时试图找到答案,我在发布后几分钟就找到了解决方案。结果(来自 此处)对于 GTK3,您需要调用 GLib .threads_init(),该代码在调用之前使用初始 from gi.repository import GLibGLib.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()

And having spent hours trying to find an answer before posting a question I find the solution minutes after posting. Turns out (from here) that for GTK3 you need to call GLib.threads_init(), the code works with an initial from gi.repository import GLib and a GLib.threads_init() before the call to Gtk.main(), so a working version of the code looks like this:

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文