2011-10-21 2 views
2

Я пытался решить эту проблему часами, очистка веб-страниц и чтение документации не помогли. Я пытаюсь выполнить многолетнюю задачу в отдельном потоке и отображать прогресс в индикаторе выполнения в пользовательском интерфейсе. Новый поток запускается, но не предоставляется какое-либо время, пока основной цикл не завершится, я позвонил Gdk.threads_init() до Gtk.main, и я окружил вызовы пользовательского интерфейса Gdk.threads_enter() и Gdk.threads_leave().Поток PyGtk не работает до основных завершений

Следующий код воспроизводит проблему, нажатие на кнопку «Пуск» не имеет никакого эффекта, но как только окно закрывается, а основной цикл завершается, я вижу, что второй поток выполняет работу (т. Е. Я вижу операторы печати полсекунды)

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?

+0

ли вам думаете, что этот код будет работать с GTK 2.x? Я очень хочу проверить это, когда вы получите решение ... – heltonbiker

+0

Хорошо, должен был проверить, что раньше, да, он работает с gtk 2.28. Но я бы предпочел использовать Gtk3, поэтому любые предложения приветствуются. –

+2

Проведя много разочаровывавших часов на этом, я нахожу ответ почти сразу, как только я отправляю вопрос, ну ладно. Проблема в том, что вам нужно вызвать 'GLib.thread_init()', а не 'Gdk.threads_init()'. У меня нет ответа, чтобы ответить на мой вопрос еще на 7 часов, сделаю это, когда смогу. –

ответ

4

И потратив часы, пытаясь найти ответ, прежде чем отправлять вопрос. Я нахожу решение через несколько минут после публикации. Оказывается (от here), что для GTK3 вам нужно позвонить GLib.threads_init(), код работает с начальным 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() 
+0

Это тоже моя проблема. Пока я делал вызов thread_init(), ключ должен сделать это * перед * вызовом main(). – esarjeant

Смежные вопросы