问题描述
我一直试图将这个问题排序几个小时,淘到网页并阅读文档没有帮助。我试图在单独的线程中执行长时间运行的任务,并在UI中的进度条中显示进度。新线程已经启动,但是在主循环退出之前没有给出任何时间,我在之前调用了 Gdk.threads_init() code>,我用 Gdk.threads_enter()和 Gdk.threads_leave()包围了UI调用。
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()
可以这与我正在使用Gtk3的事实有关?
Could this be related to the fact that I am using Gtk3?
推荐答案
在发布问题之前花了几个小时试图找到答案发布后我会找到解决方案的几分钟。原来(从),对于GTK3你需要调用 GLib.threads_init(),代码适用于gi.repository import GLib 和 GLib的初始。在调用 Gtk.main()之前调用threads_init(),因此代码的工作版本如下所示:
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()
这篇关于在主要退出之前,PyGtk线程不运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!