2012-03-25 16 views
3

まず、PythonとPysideの新機能です。自己改良のために、私はPyTideプログラムの子スレッドで1秒ごとにQTimerを実行させようとしています(現時点では、 "hi!"メインウィンドウをフリーズすることなく)。PySideの子スレッドのタイマー

私はexample I found on the Qt WikiをC++からPython/PySideに変換しようとしましたが、実際にはC++が分からないため、正しく変換しなかったと思われます。

現時点でdoWork()関数は1回だけ実行され、その後は実行されないようです。私は間違って何をしていますか?メインウィンドウを凍らせずにPySideで1秒ごとに関数を実行するより良い方法はありますか? 、updateGuiWithStatsクラスの

from PySide import QtGui 
from PySide import QtCore 
from client_gui import Ui_MainWindow 

statsThread = QtCore.QThread() 

class MainWindow(QtGui.QMainWindow, Ui_MainWindow): 
    def __init__(self, parent=None): 
     super(MainWindow, self).__init__(parent) 
     #setup GUI 
     self.setupUi(self) 
     #start thread to update GUI 
     self.statsThread = updateStatsThread() 
     self.statsThread.start(QtCore.QThread.TimeCriticalPriority) 

class updateGuiWithStats(QtCore.QObject): 
    def Worker(self): 
     timer = QtCore.QTimer() 
     timer.timeout.connect(self.doWork()) 
     timer.start(1000) 

    def doWork(self): 
     print "hi!" 

class updateStatsThread (QtCore.QThread): 
    def run(self): 
     updater = updateGuiWithStats() 
     updater.Worker() 
     self.exec_() 

if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    frame = MainWindow() 
    frame.show() 
    sys.exit(app.exec_()) 

答えて

4

@Masciは既にあなたのtimer.timeout.connectに必要な修正を指摘しましたが、それ以上の問題があります。

使用されることはありませんグローバルQThreadを作成する必要はありません:

statsThread = QtCore.QThread() 

あなたQTimerはゴミがすぐにそのため作成した親なしで収集されている、とあなたはクラス内に保存されていませんが。

また
class UpdateGuiWithStats(QtCore.QObject): 

    def startWorker(self): 
     self.timer = QtCore.QTimer() 
     self.timer.timeout.connect(self.doWork) 
     self.timer.start(1000) 

、最初のクラスの文字、およびメソッドのキャメルケースには、大文字を使用する:あなたは、タイマーの接続を修正した後でも、それはまだ試してみてください...動作しません理由です。あなたは両方の方法の混合をしています。

あなたが提供したリンク、あなたの例、そしてここにある他のコメントをもとにしたいくつかのノート... doWork()が非常に軽く、あなたのメインイベントループをブロックしないなら、QTimerをソリューションとして使うことができますデータの集まり、寝る時間などがあります。もしそうであれば、doWork()は例のようにQThreadに移動する必要があります。しかし、その時点では、イベントループとQTimerを別々のクラスで使用して独自の作業を呼び出すことは多少不要です。これはすべて次のような単一のクラスに統合できます。

class UpdateStatsThread(QtCore.QThread): 

    def __init__(self, parent=None): 
     super(UpdateStatsThread, self).__init__(parent) 
     self._running = False 

    def run(self): 
     self._running = True 
     while self._running: 
      self.doWork() 
      self.msleep(1000) 

    def stop(self, wait=False): 
     self._running = False 
     if wait: 
      self.wait() 

    def doWork(self): 
     print "hi!" 
+0

'doWork()'で 'print" foo "'などを呼び出すよりももっとやりたいと思うのは正しいです。それを念頭に置いて、あなたが書いた改訂された 'UpdateStatsThread()'クラスを実装しました。しかし、スレッドを終了するときに、実行中にスレッドが破棄されたというメッセージが表示されます。私は、 'time.sleep(1)'がまだ動いている間にスレッドを終了したためだと思います。スレッドを終了してそのメッセージを避ける良い方法はありますか? –

+0

まあまあです。 Pythonは実際に終了する前にオブジェクトを破壊しているからです。私は、stop()メソッドにオプションのwaitを追加するように答えを更新しました。私はまた、QThread.msleep() – jdi

+1

を使用するように睡眠を更新しました。 ;) – Kasramvd

1

Worker方法:ここで

コード(私は明瞭性を高めるために、いくつかのメインウィンドウのコードを削除した)だ

timer.timeout.connect(self.doWork()) 

timer.timeout.connect(self.doWork) 

する必要がありますタイムアウト信号をNoneに接続しています(戻り値doWork()メソッドの)、私はこれが1回だけ実行される理由だと思う:doWorkが接続とnomore中に呼び出されます。接続を行うときは、関数呼び出しではなく、関数名(Pythonの言葉では呼び出し可能なオブジェクト)を接続してください。

ところで、上記の問題が解決したとしても、QTimerは既にそれ自体で必要とするスレッドを使用しないでください。 docs you linkedでは、最初の答えはスレッドは使用しないでください。質問は:タイマー。

+0

QTimerはスレッドを使用しません。 – jdi

+0

また、QThreadの代わりにQTimerを使用するソリューションは、修正されたすべての解決策ではありません。'doWork()'が高速でメインイベントループをブロックしないで実行できる場合にのみ動作します。その重い呼び出しの場合、呼び出されるたびにイベントループをブロックします。したがって、その機能をスレッドに移す必要があります。 – jdi

+0

同意するが、OPの必要性のためにスレッディングが過剰だと思う。 – Masci

関連する問題