これは@mhallが提案したことを行うための複雑な方法であることに注意する必要があると思います。
基本的に、これを実行してから、async_callの関数を実行します。
動作を確認したい場合は、スリープタイマーで遊んで、ボタンをクリックし続けることができます。サンプルコードがある以外は、@ mhallの答えと本質的に同じです。
これに基づき、私の仕事ではないとします。
import threading
import time
from gi.repository import Gtk, GObject
# calls f on another thread
def async_call(f, on_done):
if not on_done:
on_done = lambda r, e: None
def do_call():
result = None
error = None
try:
result = f()
except Exception, err:
error = err
GObject.idle_add(lambda: on_done(result, error))
thread = threading.Thread(target = do_call)
thread.start()
class SlowLoad(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Hello World")
GObject.threads_init()
self.connect("delete-event", Gtk.main_quit)
self.button = Gtk.Button(label="Click Here")
self.button.connect("clicked", self.on_button_clicked)
self.add(self.button)
self.file_contents = 'Slow load pending'
async_call(self.slow_load, self.slow_complete)
def on_button_clicked(self, widget):
print self.file_contents
def slow_complete(self, results, errors):
'''
'''
self.file_contents = results
self.button.set_label(self.file_contents)
self.button.show_all()
def slow_load(self):
'''
'''
time.sleep(5)
self.file_contents = "Slow load in progress..."
time.sleep(5)
return 'Slow load complete'
if __name__ == '__main__':
win = SlowLoad()
win.show_all()
#time.sleep(10)
Gtk.main()
追加の注意として、適切に終了する前に他のスレッドを終了させるか、子スレッドでfile.lockを確認する必要があります。
コメントに対処するための編集:
最初は忘れていましたGObject.threads_init()
。明らかに、ボタンが発動すると、スレッドが初期化されました。これは私にとって間違いを隠してくれました。
通常、フローはメモリ内にウィンドウを作成し、スレッドがボタンを更新するのを完了するとすぐに他のスレッドを起動します。Gtk.mainを呼び出す前にスリープを追加して、ウィンドウが描画される前に完全な更新が実行されることを確認しました。また、スレッドの起動がウィンドウの描画をまったく妨げないことを確認するためにコメントアウトしました。