0

関数 updateTelemetry() を介して定期的に更新されるテキスト表示を備えたpyqt guiがあります

これが私のコードの仕組みです。ユーザーがボタンをクリックすると、buttonHandler が呼び出されます。そして updateTelemetry は 10 秒ごとに繰り返し呼び出されます。

def buttonHandler(self):
    self.monitor=true
    self.updateTelemetry()

def updateTelemetry(self):
   try:
        #update values on gui
   finally:
       if self.monitor:
          QtCore.QTimer.singleShot(10000, self.updateTelemetry)

このアプローチは機能し、約 10 秒ごとに更新を取得できます。ただし、10 秒ごとに、GUI 全体が数秒間フリーズしてから更新されます。私がやっていることは、ブロックしているようです。それがどのように起こっているのかわかりません。qtimer.singleshot は別のスレッドを作成すると思いましたか?

私がやっていることを行うためのより良い方法はありますか?

4

1 に答える 1

1

AQTimerは別のスレッドを作成しません。QTimer特定のタイムアウト後にメインスレッドでシグナルを送信するだけです。そのため、すべて (デバイス読み取りコードを含む) は引き続きメイン スレッドで実行されます。

デバイスから読み取るコードを に移動し、からGUI を更新できるメイン スレッドにQThreadシグナルを送信する必要があります。GUI の更新は、メイン スレッドからのみ行う必要があります。シグナルの発行のみがスレッドセーフです!QThread

以下は、 a の大まかな実装ですQThread

class MyThread(QObject):
    send_data_to_gui = pyqtSignal(str)

    def __init__(self,*args,**kwargs):
        QObject.__init__(self,*args,**kwargs)

    @pyqtSlot()
    def run(self):
        while True: 
            # get data from device
            self.send_data_to_gui.emit(data_from_device)
            time.sleep(10) 

...

thread = QThread()
my_thread = MyThread()
my_thread.send_data_to_gui.connect(my_slot)
my_thread.moveToThread(thread)
thread.started.connect(my_thread.run)
thread.start()

現在の形式では、 はQThread実際には独自のイベント ループを持っているため、あらゆる種類の複雑なことを行うことができます (ただしwhile True、現時点では がイベント ループをブロックしています)。スレッドには独立したイベント ループがあるため、 を に置き換えて、10 秒ごとに起動するように構成することができますwhile True(QTimerただし、QTimerが実際にスレッドで作成されていることを確認してください。MyThread.__init__引き続きメイン スレッドで実行されますが、 の内容はMyThread.run新しいイベントで実行されます)。スレッド)。また、スレッドをシャットダウンする機能を追加したり、私が知らない他の機能を追加したりすることもできます!

実装に問題がある場合は、スタック オーバーフローに関するフォローアップの質問を投稿してください。

于 2015-08-10T23:28:14.013 に答える