プログレスバーは、動作中に更新されません
-
20-08-2019 - |
質問
私のPythonプログラムでのアップロードの進行状況を表示するにはGTKのプログレスバーを使用して、インターネットにIMをファイルをアップロードします。しかし、直面イム問題は、アップロードが完了するまでプログレスバーは任意の活性を示さない、そしてそれが突然、完全なアップロードを示しているということです。イム...私の質問は、http要求であることを確認するためにpycurlを使って - 私は、ファイルをアップロードし、同時に、GUIを更新するために、マルチスレッドアプリケーションを持っている必要がありますか?または作るイム他のいくつかの間違いがありますか?
事前に感謝します!
解決
私は PyGTKのよくある質問:
あなたは、いくつかの作業を行うループの実行を開始、その後、ウィンドウ内のプログレスバーを作成しています:
while work_left:
...do something...
progressbar.set_fraction(...)
あなたは、ウィンドウも表示されない、またはそれがない場合は、プログレスバーがタスクの終了まで凍結とどまることがわかります。説明は簡単です:GTKはイベント駆動型で、あなたはこのように、通常のGUI更新イベントを処理することを妨げる、離れgtkのメインループからの制御を盗んでいる。
。最も簡単な解決策は、一時的にGTKに戻って進展が変更されるたびに制御を与えるに構成されてい
while work_left:
...do something...
progressbar.set_fraction(...)
while gtk.events_pending():
gtk.main_iteration()
あなたのheavy_workが完了するまで、この溶液を用いて、ユーザは、(gtk.main_quitがあるため、新たなループ[gtk.main_iteration()]で動作しない)アプリケーションを終了することができないということです。お知らせ
別の解決策は、それが何の関係もありませんたびgtkのメインループによって呼び出され、GTKアイドル機能を使用して構成されています。したがって、GTKが制御されている、アイドル機能は、仕事のビットを行う必要があります。やるべき多くの仕事があります場合にはTRUE、そうでなければFALSEを返す必要があります。
最善の解決策は、(それは欠点を持っていない)ジェームズ・ヘンストリッジによって指摘されました。 Pythonは自動的に私たちのために状態を維持するために、アイドル状態の関数としてのpythonの発電機の利点を取っています。それはこのように書きます:
def my_task(data):
...some work...
while heavy_work_needed:
...do heavy work here...
progress_label.set_text(data) # here we update parts of UI
# there's more work, return True
yield True
# no more work, return False
yield False
def on_start_my_task_button_click(data):
task = my_task(data)
gobject.idle_add(task.next)
「ながら」は上記の一例です。唯一のルールは、それが仕事のビットをやった後、真の得なければならないと行うにはより多くの仕事がありますし、タスクが完了したときに、それは偽得なければならないということです。
他のヒント
もっと可能性が高い問題は、私はあなたがプログレスバーを更新していると推定ところで、あなたの進捗コールバック、中には、手動でディスプレイすなわちGUIのイベントループを介して実行を更新するための呼び出しを行っていないということです。これは、あなたがより多くのコードを提供することができれば、さらにそれを絞ることが容易であるかもしれない、しかし単なる憶測です。
あなたのメインスレッドでも、それがブロックしていますどこでアップロードを、実行しているので、あなたが手動で表示を更新する必要がある理由があります。
のPython 2.xの整数オペランドでは、整数除算をもたらします。これを試してください:
#Callback function invoked when download/upload has progress
def progress(download_t, download_d, upload_t, upload_d):
print 'in fileupload progress'
mainwin.mainw.prog_bar.set_fraction(float(upload_d) / upload_t)
はい、あなたはおそらく並行処理を必要とし、そうスレッドが一つの方法ですが、あなたがスレッドを使用しない場合は、このいずれかのようなメソッドを使用してください:<のhref = "http://unpythonic.blogspot.com/2007/08 /using-threads-in-pygtk.html」のrel = "nofollowをnoreferrer"> http://unpythonic.blogspot.com/2007/08/using-threads-in-pygtk.html のどの意志抽象離れて痛みは、あなたが重要な側面に焦点を当てることができます。
(私は、怠惰を通じてので、コミュニティのwikiをそのブログの記事内のすべてを繰り返されていない)。
1つのオプションは、GObjectののIOウォッチャーを使用することです。
http://pygtk.org/ pygtk2reference / GObjectの-functions.html#関数-GObjectの - のIO-アドオン見る
あなたは、通常のPyGTKのイベントループでファイルのアップロードをインターリーブ、さらにはあなたのIOの時計のコールバックでset_progress通話を行うことができ、これを使用します。あなたはpycurl上にアップロードするすべての作業負荷を軽減している場合、これは本当に現実的ではありませんが、あなただけのHTTP経由でファイルをアップロードしている場合、io_add_watchはあまり痛みを伴うだけでなく、このためのソケットを使用して行います。