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

时间:2018-03-10 14:19:02

标签: python python-3.x pyqt5 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传递到接口(信号)的例子..但不是相反。 在这种情况下,信号让我感到困惑..

1 个答案:

答案 0 :(得分:1)

我想建议下一步:

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_())

enter image description here