0

QTextEdit フィールドを持つ Gui を表示するコードがあります。print 関数がコンソールに出力するのと同じように、このフィールドにリアルタイムで出力したいと思います。

追加機能の複数のインスタンスを使用してみました。元:

self.textEdit.append(_translate("MainWindow", ">>> Text", None))

問題は、コード内のどこにいても、プログラムが実行された後にのみ表示されるように見えることです。私の目標は、印刷機能がコンソールで行うように、それらを並べて表示することです。

これは簡単な答えだと思いますが、うまく検索できませんでした..私はPythonにかなり慣れていないので、助けやガイダンスをいただければ幸いです。

前もって感謝します!

4

2 に答える 2

2

確かに、mata が述べたように、フリーズは、UI の更新も処理する同じ (メイン) スレッドですべての作業を行うことから発生します。応答性の問題を解決する 1 つの方法は、ブロッキング コードで QApplication.processEvents() を頻繁に使用することです。十分な頻度があれば、応答性の高い GUI の印象をユーザーに与えることができます。

ただし、Python でのスレッドの使用 (ネイティブまたは QThread) は、常に機能するとは限りません。これは、Global Interpreter Lock (GIL、ウィキには短いイントロがあります) が存在するためです。つまり、Python では複数のスレッドが同時にコードを実行することはできません。

バックグラウンド タスクが軽い場合、または IO に基づいている場合は、Python のほとんどの IO ヘビー モジュールがジョブを実行中に GIL をリリースするため、これを回避できます。ただし、Python で大量の計算を実行している場合、GIL はプロセスによってロックされるため、UI は依然として応答しません。

PySide を使用して構築された次の例を考えてみましょう。

import sys, random
from threading import Thread
from time import sleep
from urllib import urlopen
from PySide import QtCore, QtGui

class Window(QtGui.QMainWindow):
    update_signal = QtCore.Signal(int)
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.progress_bar = QtGui.QProgressBar(self)
        self.progress_bar.setRange(0, 10)
        self.setCentralWidget(self.progress_bar)
        self.update_signal[int].connect(self.progress_bar.setValue)
        self.show()
        self.t = Thread(target=self.worker)
        self.t.start()

    def worker(self):
        while self.progress_bar.value() < 10:
            self.update_signal.emit(self.progress_bar.value()+1)
            print "Starting Sleep"
            sleep(5)
            print "End of Sleep"

if __name__ == '__main__':
    qapp = QtGui.QApplication(sys.argv)
    win = Window()
    sys.exit(qapp.exec_())

次に、ワーカー関数を次のように置き換えてみてください。

def worker(self):
    while self.progress_bar.value() < 10:
        self.update_signal.emit(self.progress_bar.value()+1)
        v = 0
        print "Starting Add"
        for i in xrange(5000000):
            v = v+random.uniform(0, 100)
        print "End of Add"

最初のケースでは、sleep() の呼び出しによって GIL が解放されるため、レスポンシブ UI が維持されます。しかし、計算量の多いアルゴリズムがロックを保持するため、2 番目の例はそうではありません。

解決策の 1 つは、マルチプロセッシングパッケージを使用することです。ドキュメントから:

multiprocessing は、threading モジュールと同様の API を使用してプロセスの生成をサポートするパッケージです。マルチプロセッシング パッケージは、ローカルとリモートの両方の同時実行性を提供し、スレッドの代わりにサブプロセスを使用してグローバル インタープリター ロックを効果的に回避します。このため、マルチプロセッシング モジュールを使用すると、プログラマは特定のマシンで複数のプロセッサを完全に活用できます。

Python のマルチポセッシングを使用した簡単な例です。

また、さらに興味がある場合は、マルチプロセッシング手法に関するこのブログ投稿が興味深いかもしれません。

于 2013-04-23T21:53:39.423 に答える
2

これは、おそらくすべての作業を GUI スレッドで行っていることを意味します。これはよくある間違いで、別の処理を行っているときに GUI がフリーズして応答しなくなることを意味します。

QApplication.processEvents()のテキストを変更した後に GUI を更新できるようにするための呼び出しを追加できますQTextEditが、それでは問題が部分的にしか解決されず、GUI はこれらの呼び出しの間にフリーズします。

解決策は簡単です。別のスレッドで作業を行います。Qt のドキュメントからThreading Basicsを読む必要があります。

于 2013-04-23T20:14:55.790 に答える