bugfix> python > 投稿

Pythonバックエンドで、PyQt GUIが(多くの)ものを描画するのを待つ必要がないようにします。以下のコード例のようにPyQtでこれを行うより良い/正しい方法はありますか?スレッドインポートを使用する必要がありますか、それともPyQtにはそれを行う独自のより良い方法がありますか?

import time
from threading import Thread
class Backend(Thread):
    def __init__(self):
        super().__init__()
    def run(self):
        for i in range(20):
            print("Backend heavy work")
            time.sleep(4)

class GUI(Thread):
    def __init__(self):
        super().__init__()
    def run(self):
        for i in range(20):
            print("GUI drawing stuff")
            time.sleep(0.5)
if __name__ == '__main__':
    thread_backend = Backend()
    thread_gui = GUI()
    thread_backend.start()
    thread_gui.start()

Qtimerで試しましたが、動作しませんでした。ありがとうございました!

回答 1 件
  • Qtループの外側からUIを更新することはできません。できることは、qtシグナルを使用してメソッドに接続し、ジョブを実行することです。例として

    class GUI(QtCore.QObject): # must be a class that inherits QObject to use signals, I believe
        drawSignal = QtCore.pyqtSignal(int)
        def __init__(self):
            super().__init__()
            self.drawSignal.connect(self._drawStuff) # The underscore thing is a little hacky, but sort of pythonic I think, and makes the API clean.
            self.drawStuff = self.drawSignal.emit
        def _drawStuff(self, i):
            # do whatever you want to the gui here
            pass
    
    class GUILoop(Thread):
        def __init__(self, gui):
            super().__init__()
            self.gui = gui
        def run(self):
            for i in range(20):
                self.gui.drawStuff(i)
                time.sleep(0.5)
    if __name__ == '__main__':
        gui = GUI()
        thread_backend = Backend()
        thread_gui = GUILoop(gui)
        thread_backend.start()
        thread_gui.start()
    
    

    少し奇妙に見えるかもしれませんが、QtとPythonの両方の長所にうまく適合しています。おそらく、あなたの QMainWindow に信号を追加することも理にかなっています  既に QObject であるクラス 。

あなたの答え