【问题标题】:PyQt5 multi threadPyQt5 多线程
【发布时间】:2017-12-08 03:51:52
【问题描述】:

为什么代码不起作用?视频工作文件,当我尝试在第二个标签中显示文本时,它也会显示出来。但是如果我想像 setText() 中的当前时间一样连续更改值,我该怎么办?我是多线程新手。

import sys
import cv2
from PyQt5.QtCore import QThread, pyqtSignal, Qt
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
import datetime


class App(QWidget):
    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 Video'
        self.left = 100
        self.top = 100
        self.width = 640
        self.height = 480
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.resize(1800, 1200)
        # create a label
        label = QLabel(self)
        label.move(280, 120)
        label.resize(640, 480)
        label1 = QLabel(self)
        label1.move(680, 820)
        th = Thread(self)
        th.changePixmap.connect(lambda p: label.setPixmap(p))
        th.changeLabel.connect(lambda n:label1.setText("A"))
        th.start()

class Thread(QThread):
    changePixmap = pyqtSignal(QPixmap)
    changeLabel = pyqtSignal(QLabel)

    def __init__(self, parent=None):
        QThread.__init__(self, parent=parent)

    def run(self):
        cap = cv2.VideoCapture(0)
        n=QLabel()
        while True:
            ret, frame = cap.read()
            rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            convertToQtFormat = QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QImage.Format_RGB888)
            convertToQtFormat = QPixmap.fromImage(convertToQtFormat)
            p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
            self.changePixmap.emit(p)
            now = datetime.datetime.now()
            sec = now.second
            try:
                self.changeLabel.emit(n)
            except Exception as e:
                print(str(e))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    ex.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 qthread


    【解决方案1】:

    您不应将新的小部件 (QLabel) 发送到主视图,因为这将是一个新标签,而不是原始标签,您应该发送 str 类型的文本。

    class Thread(QThread):
        changePixmap = pyqtSignal(QPixmap)
        changeLabel = pyqtSignal(str)
    
        def run(self):
            [...]
            now = datetime.datetime.now()
            sec = now.second
            self.changeLabel.emit(str(sec))
    

    然后连接到setText函数:

    th.changeLabel.connect(label1.setText)
    

    完整代码:

    import sys
    import cv2
    from PyQt5.QtCore import QThread, pyqtSignal, Qt
    from PyQt5.QtGui import QPixmap, QImage
    from PyQt5.QtWidgets import QApplication, QWidget, QLabel
    import datetime
    
    
    class App(QWidget):
        def __init__(self):
            super().__init__()
            self.title = 'PyQt5 Video'
            self.left = 100
            self.top = 100
            self.width = 640
            self.height = 480
            self.initUI()
    
        def initUI(self):
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
            self.resize(1800, 1200)
            # create a label
            # create a label
            label = QLabel(self)
            label.move(280, 120)
            label.resize(640, 480)
            label1 = QLabel(self)
            label1.move(580, 620)
            self.th = Thread(self)
            self.th.changePixmap.connect(label.setPixmap)
            self.th.changeLabel.connect(label1.setText)
            self.th.start()
    
        def closeEvent(self, event):
            self.th.stop()
            QWidget.closeEvent(self, event)
    
    class Thread(QThread):
        changePixmap = pyqtSignal(QPixmap)
        changeLabel = pyqtSignal(str)
    
        def __init__(self, parent=None):
            QThread.__init__(self, parent=parent)
            self.isRunning = True
    
        def run(self):
            cap = cv2.VideoCapture(0)
            while self.isRunning:
                ret, frame = cap.read()
                rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                convertToQtFormat = QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QImage.Format_RGB888)
                convertToQtFormat = QPixmap.fromImage(convertToQtFormat)
                p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
                self.changePixmap.emit(p)
                now = datetime.datetime.now()
                sec = now.second
                self.changeLabel.emit(str(sec))
    
        def stop(self):
            self.isRunning = False
            self.quit()
            self.wait()
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ex = App()
        ex.show()
        sys.exit(app.exec_())
    

    注意:我添加了 stop 方法来停止线程并正确关闭,为此我还覆盖了 closeEvent 方法。另一个变化,我移动了 label1,因为我的屏幕不是那么大。

    【讨论】:

    • 如果我想在不阻塞视频流的情况下同时执行一些与任何 QtWidgets 无关的其他进程,例如某些 .exe 文件或其他文件,我该怎么做?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    • 2021-07-29
    • 2017-03-25
    • 1970-01-01
    • 2023-03-17
    相关资源
    最近更新 更多