将数据从一个 QThread 传递到另一个 QThread

Passing data from a QThread to another QThread

我有一个 Gui 处于活动状态和一个 QThread 的情况。 QThread 一直在后台获取和保存数据,它不应该停止这样做。 现在我想在不中断 QThread 或冻结 Gui 的情况下处理来自 QThread 的最新数据。

所以我想我需要另一个线程来做这个?! 我怎样才能将它的数据传递给另一个线程并对其进行处理?

import sys, random, time
from PyQt5 import QtWidgets
from PyQt5.QtCore import  *


class Ui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui, self).__init__()
        self.setWindowTitle('Window')

        #getData
        self.myGetData = getData()
        self.myGetData.start()

        self.show()

class getData(QThread):
    #This Thread should run all the time
    def run(self):
        while True:
            myNumber = random.randint(0, 100)
            #He 'processData Thread'!! Do Something with mynumber!!
            time.sleep(1)

class processData(QThread):
    def processNumber(self, myNumber):
        #Extremly complex code will execute while 'getData' is doing its thing.
        newNumber = myNumber * 10
        return newNumber

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = Ui()
    sys.exit(app.exec_())

找到了很多关于如何将数据从 QThread 传递到接口(信号)的示例。但反之则不然。 在这种情况下,信号让我有点困惑..

我想建议下一步做什么:

import sys, random, time
from PyQt5 import QtWidgets
from PyQt5.QtCore import  *

from PyQt5 import Qt          #+

class getData(QThread):
    #This Thread should run all the time

    threadSignalGetData = pyqtSignal(int)
    def __init__(self, myNumber):
        super().__init__()
        self.myNumber = myNumber

    def run(self):
        #myNumber = 0
        while True:
            #He 'processData Thread'!! Do Something with mynumber!!
            Qt.QThread.msleep(1000)
            self.myNumber += 1
            self.threadSignalGetData.emit(self.myNumber)

class MsgBoxGetData(Qt.QDialog):
    def __init__(self):
        super().__init__()

        layout     = Qt.QVBoxLayout(self)
        self.label = Qt.QLabel("")
        layout.addWidget(self.label)

        close_btn  = Qt.QPushButton("Close window GetData")
        layout.addWidget(close_btn)

        close_btn.clicked.connect(self.close) 

        self.setGeometry(900, 65, 400, 80)
        self.setWindowTitle('MsgBox GetData')
        self.setStyleSheet("""QLabel{
          font-family:'Consolas'; 
          color: green; 
          font-size: 16px;}""")


class processData(QThread):

    threadSignalProcessData = pyqtSignal(int, int)
    def __init__(self, myNumber):
        super().__init__()
        self.newNumber = myNumber

    def run(self):
        flagProcessData = True
        while flagProcessData:
            #Extremly complex code will execute while 'getData' is doing its thing.
            newNumber = self.newNumber * 10
            self.threadSignalProcessData.emit(self.newNumber, newNumber)
            flagProcessData = False

class MsgBoxProcessData(Qt.QDialog):
    def __init__(self):
        super().__init__()

        layout     = Qt.QVBoxLayout(self)
        self.label = Qt.QLabel("")
        layout.addWidget(self.label)

        close_btn  = Qt.QPushButton("Close window ProcessData")
        layout.addWidget(close_btn)

        close_btn.clicked.connect(self.close) 

        self.setGeometry(900, 200, 400, 80)
        self.setWindowTitle('MsgBox ProcessData')            
        self.setStyleSheet("""QLabel{
          font-family:'Consolas'; 
          color: red; 
          font-size: 24px;}""")            


class Ui(Qt.QWidget):
    def __init__(self, parent=None):
        super(Ui, self).__init__(parent)

        layout   = Qt.QVBoxLayout(self)
        self.lbl = Qt.QLabel("process GUI")
        layout.addWidget(self.lbl)
        self.btnA = Qt.QPushButton("Start getData")
        layout.addWidget(self.btnA)
        self.btnB = Qt.QPushButton("Start processData")
        layout.addWidget(self.btnB)        

        self.setGeometry(550, 65, 300, 300)
        self.setWindowTitle('Window')


        self.btnA.clicked.connect(self.usingGetData)
        self.btnB.clicked.connect(self.usingProcessData)

        self.myNumber  = 0
        self.newNumber = None
        self.msgGetData    = MsgBoxGetData()  
        self.threadGetData = None
        self.msgProcessData    = MsgBoxProcessData()
        self.threadProcessData = None


        self.counter = 0
        self.timer = Qt.QTimer()
        self.timer.setInterval(1000)
        # -------- timeout -------> def recurring_timer(self):
        self.timer.timeout.connect(self.recurring_timer)   
        self.timer.start()

        self.setStyleSheet("""QLabel{
          font-family:'Consolas'; 
          color: blue; 
          font-size: 20px;}""")


        self.show()

    def recurring_timer(self):
        self.counter += 1
        self.lbl.setText("process GUI: %d" % self.counter)         

    # ---- getData(QThread) -----------------------------------------------------#    
    def usingGetData(self):
        if self.threadGetData is None:
            self.threadGetData = getData(self.myNumber) 
            self.threadGetData.threadSignalGetData.connect(self.on_threadSignalGetData)
            self.threadGetData.finished.connect(self.finishedGetData)
            self.threadGetData.start()
            self.btnA.setText("Stop getData(QThread)")
        else:
            self.threadGetData.terminate()         
            self.threadGetData = None
            self.btnA.setText("Start getData(QThread)")    

    def finishedGetData(self):
        self.threadGetData = None
        self.btnA.setText("Start getData(QThread)")

    def on_threadSignalGetData(self, value):
        self.myNumber = value
        self.msgGetData.label.setText(str(self.myNumber))
        if not self.msgGetData.isVisible():        
            self.msgGetData.show() 
    # --END-- getData(QThread) -------------------# 

    # ---- processData(QThread) -----------------------------------------------------#    
    def usingProcessData(self):
        if self.threadProcessData is None:
            self.threadProcessData = processData(self.myNumber) 
            self.threadProcessData.threadSignalProcessData.connect(self.on_threadSignalProcessData)
            self.threadProcessData.finished.connect(self.finishedProcessData)
            self.threadProcessData.start()
            self.btnB.setText("Stop processData(QThread)")
        else:
            self.threadProcessData.terminate()         
            self.threadProcessData = None
            self.btnB.setText("Start processData(QThread)")    

    def finishedProcessData(self):
        self.threadProcessData = None
        self.btnB.setText("Start processData(QThread)")

    def on_threadSignalProcessData(self, value1, value2):
        self.newNumber = value2                                                         
        self.msgProcessData.label.setText(str(value1)+" * 10 = "+str(self.newNumber))   
        if not self.msgProcessData.isVisible():        
            self.msgProcessData.show() 
    # --END-- processData(QThread) -------------------#     


    # --------------------  closeEvent  --------------------------------------- #  
    def closeEvent(self, event):
        reply = Qt.QMessageBox.question\
        (self, 'Question',
            "QUIT ?",
             Qt.QMessageBox.Yes,
             Qt.QMessageBox.No)
        if reply == Qt.QMessageBox.Yes:

            # close getData(QThread)
            if self.threadGetData:
                self.threadGetData.terminate()
            self.msgGetData.close()

            # close processData(QThread)
            if self.threadProcessData:
                self.threadProcessData.terminate()
            self.msgProcessData.close()            

            #event.accept()
            super().closeEvent(event)
        else:
            event.ignore()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = Ui()
    sys.exit(app.exec_())