【问题标题】:How to stop thread using QPushButton(Python)?如何使用 QPushButton(Python) 停止线程?
【发布时间】:2021-02-07 05:02:09
【问题描述】:

我目前正在开发一个应用程序,该应用程序需要不断地将我的屏幕流发送到其中的窗口。但是,我想要一种能够停止并使用停止和启动按钮重新启动它的方法,我也使用 layout.addWidget(QtWidgets.QPushButton('Start'),0,0 添加了网格), layout.addWidget(QtWidgets.QPushButton('Stop'),0,1)。但是,我不知道如何正确地将这些按钮连接到使用这两个按钮分别启动和停止线程的非活动/活动线程。

这是我的代码:

from PyQt5 import QtCore, QtGui, QtWidgets 
import cv2
import numpy as np
from mss import mss


class Thread(QtCore.QThread):
   changePixmap = QtCore.pyqtSignal(QtGui.QImage)
   scaled_size = QtCore.QSize(1500, 1000)
   


   def run(self):
       mon = {'top': 0, 'left': 0, 'width': 1920, 'height': 1080}
       with mss() as sct:

        while True:
           ret = True
           if ret:
               img = sct.grab(mon)
            #    cv2.imshow('test', np.array(img))
               rgbImage = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
               convertToQtFormat = QtGui.QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QtGui.QImage.Format_RGB888)
               p = convertToQtFormat.scaled(self.scaled_size, QtCore.Qt.KeepAspectRatio)
               self.changePixmap.emit(p)
def scaled(self, scaled_size):
        self.scaled_size = scaled_size


class PlayStreaming(QtWidgets.QWidget):
    def __init__(self):
        super(PlayStreaming,self).__init__()
        self.initUI()

    @QtCore.pyqtSlot(QtGui.QImage)
    def setImage(self, image):
        self.label.setPixmap(QtGui.QPixmap.fromImage(image))

    def initUI(self):
        self.setWindowTitle("Image")
        # create a label
        self.label = QtWidgets.QLabel(self)
        th = Thread(self)
        th.changePixmap.connect(self.setImage)
        th.start()
        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.label, alignment=QtCore.Qt.AlignCenter)


class UIWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(UIWidget, self).__init__(parent)
        # Initialize tab screen
        self.tabs = QtWidgets.QTabWidget()
        self.tab1 = QtWidgets.QWidget()   
        self.tab2 = QtWidgets.QWidget()
        self.tab3 = QtWidgets.QWidget()


        # Add tabs
        self.tabs.addTab(self.tab1,"Face")

        # Create first tab
        self.createGridLayout()
        self.tab1.layout = QtWidgets.QVBoxLayout()
        self.display = PlayStreaming()
        self.tab1.layout.addWidget(self.display, stretch=1)
        self.tab1.layout.addWidget(self.horizontalGroupBox)
        self.tab1.setLayout(self.tab1.layout)

        # Add tabs to widget        
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.tabs)

    def createGridLayout(self):
        self.horizontalGroupBox = QtWidgets.QGroupBox("Control")
        self.horizontalGroupBox.setStyleSheet("QGroupBox { background-color: red}");
        layout = QtWidgets.QGridLayout()
        layout.addWidget(QtWidgets.QPushButton('Start'),0,0) 
        layout.addWidget(QtWidgets.QPushButton('Stop'),0,1) 
        self.horizontalGroupBox.setLayout(layout)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = UIWidget()
    w.resize(1000, 800)
    w.show()
    sys.exit(app.exec_())

提前致谢

请注意,我在以下位置使用了代码: How to change display size changing with window size in PyQT5?Screen Capture with OpenCV and Python-2.7 作为我的代码模板。

【问题讨论】:

    标签: python user-interface pyqt5 qthread


    【解决方案1】:

    您需要一种方法来中断线程的 run 方法中的 while True 循环,以停止线程。您可以改为保留一个布尔变量,在调用 Thread.stop() 时将其设置为 False。

    def run(self):
        self._go = True
        
        mon = {'top': 0, 'left': 0, 'width': 1920, 'height': 1080}
        with mss() as sct:
    
            while self._go:
                ret = True
                if ret:
                    img = sct.grab(mon)
                    #    cv2.imshow('test', np.array(img))
                    rgbImage = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
                    convertToQtFormat = QtGui.QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QtGui.QImage.Format_RGB888)
                    p = convertToQtFormat.scaled(self.scaled_size, QtCore.Qt.KeepAspectRatio)
                    self.changePixmap.emit(p)
            
    def stop(self):
        self._go = False

    我建议在 UIWidget 类中构建线程并从那里连接它的信号。

    class UIWidget(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(UIWidget, self).__init__(parent)
            # Initialize tab screen
            self.tabs = QtWidgets.QTabWidget()
            self.tab1 = QtWidgets.QWidget()   
            self.tab2 = QtWidgets.QWidget()
            self.tab3 = QtWidgets.QWidget()
    
            # Add tabs
            self.tabs.addTab(self.tab1,"Face")
    
            self.display = PlayStreaming()
            self.th = Thread(self)
            self.th.changePixmap.connect(self.display.setImage)
    
            # Create first tab
            self.createGridLayout()
            self.tab1.layout = QtWidgets.QVBoxLayout()
            self.tab1.layout.addWidget(self.display, stretch=1)
            self.tab1.layout.addWidget(self.horizontalGroupBox)
            self.tab1.setLayout(self.tab1.layout)
    
            # Add tabs to widget        
            layout = QtWidgets.QVBoxLayout(self)
            layout.addWidget(self.tabs)
    
        def createGridLayout(self):
            self.horizontalGroupBox = QtWidgets.QGroupBox("Control")
            self.horizontalGroupBox.setStyleSheet("QGroupBox { background-color: red}");
            layout = QtWidgets.QGridLayout()
            layout.addWidget(QtWidgets.QPushButton('Start', clicked=self.th.start), 0, 0) 
            layout.addWidget(QtWidgets.QPushButton('Stop', clicked=self.th.stop), 0, 1)
            self.horizontalGroupBox.setLayout(layout)

    现在,当您单击停止按钮时,当前迭代将完成,然后它将跳出循环并停止。如果您希望线程在循环中的任何位置都立即停止,则包含self.th.setTerminationEnabled(True) 并将停止按钮信号连接到self.th.terminate。但请注意文档警告不要使用QThread.terminate

    【讨论】:

    • 感谢您的回复。我尝试了代码,但线程继续运行。出于某种原因,即使停止函数将 self._go = False 的值设置为,while 也不会中断。
    • @MauriceBekambo 您是否删除了 PlayStreaming 类中与 QThread 相关的所有行?
    • 非常感谢它现在停止运行。你知道我怎样才能让它删除静止帧,当我按下停止时只有一个空窗口吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-29
    • 1970-01-01
    • 2015-10-31
    • 2013-08-03
    相关资源
    最近更新 更多