控制6个继电器的切换试验(行为)

2024-04-28 20:36:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我的GUI应该能够管理继电器的测试。继电器(假设为6)连接到具有适当负载的测试设备上,并一直打开和关闭,直到一个或多个继电器出现故障。程序应停止测试,并显示在缺陷出现之前已执行的切换次数

控制器块的屏幕截图如下所示

enter image description here

开始测试后,等待1秒打开继电器,查看触点是否闭合,等待9秒关闭继电器,查看触点是否再次打开

我尝试在PyQt5中使用线程,因为在运行测试过程时没有冻结GUI。 在得到一些提示后,我尝试在不使用线程的情况下重写代码。 下面是我想要的功能非常好的代码

但是,有人告诉我,我们需要一个QThread来运行测试,因为启动测试(打开/关闭继电器并向硬件的GPIO发送信号)和等待答案(从硬件的GPIO获得响应),如果它们切换良好,则需要大约1个resp的时间。9秒,当我在与GUI线程相同的线程中运行测试时,会冻结GUI

我不太熟悉线程,不知道如何处理这个问题,无论是否使用线程

使用下面提供的代码,由于我的任务描述,我不知道在没有线程的情况下GUI是否冻结。这是因为我们的硬件还没有准备好运行以查看是否冻结

#!/usr/bin/env python
# Filename: test_pyqt_signals_with_timer.py
###########################################
# coding: utf-8
import sys
import time

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

ACTIVE_WIDTH = 106
ACTIVE_HEIGHT = 32

class MainWindow(QWidget):
    def __init__( self ):
        super().__init__()

        self.setFixedWidth(400)
        self.setFixedHeight(200)
        self.move(100, 100)
        self.setWindowTitle("Test PYQT Signals")

        # self.labels[0].setText('10')
        # self.labels[1].setText('100')
        # self.labels[2].setText('1000')

        self.startCounting = False

        self.createMainWindow()

    ###################################################################

    def createMainWindow(self):

        # Create Vertival layout for three Horizontal laouts
        self.layout = QVBoxLayout(self)         # Create Vertical Layout
        self.h_layout_1 = QHBoxLayout(self)     # Create Horizontal Layout for Top Row

        self.btnStartAll = QPushButton()
        self.btnStartAll.setText("Start All")
        self.btnStartAll.setObjectName("btnStartAll")
        self.btnStartAll.setFixedSize(ACTIVE_WIDTH, ACTIVE_HEIGHT)
        self.btnStartAll.clicked.connect(self.start_all)
        self.btnStartAll.setStyleSheet(
            'font-family: Arial; '
            'font-size: 13pt; '
            'color: blue; '
            'font-weight: bold; '
            'border: 1px solid black; '
            'background-color:lightcyan;'
            )

        self.btnStopAll = QPushButton()
        self.btnStopAll.setText("Stop All")
        self.btnStopAll.setObjectName("btnStopAll")
        self.btnStopAll.setFixedSize(ACTIVE_WIDTH, ACTIVE_HEIGHT)
        self.btnStopAll.clicked.connect(self.stop_counting)
        self.btnStopAll.setStyleSheet(
            'font-family: Arial; '
            'font-size: 13pt; '
            'color: blue; '
            'font-weight: bold; '
            'border: 1px solid black; '
            'background-color:lightcyan;'
            )

        self.btnResetAll = QPushButton()
        self.btnResetAll.setText("Reset All")
        self.btnResetAll.setObjectName("btnResetAll")
        self.btnResetAll.setFixedSize(ACTIVE_WIDTH, ACTIVE_HEIGHT)
        self.btnResetAll.clicked.connect(self.resetAll)
        self.btnResetAll.setStyleSheet(
            'font-family: Arial; '
            'font-size: 13pt; '
            'color: blue; '
            'font-weight: bold; '
            'border: 1px solid black; '
            'background-color:lightcyan;'
            )

        self.h_layout_1.addWidget(self.btnStartAll)
        self.h_layout_1.addWidget(self.btnStopAll)
        self.h_layout_1.addWidget(self.btnResetAll)

        self.layout.addLayout(self.h_layout_1)
        self.h_layout_2 = QHBoxLayout(self)     # Create Horizontal Layout for Middle Row

        # Creating Counter Labels
        #####################################
        self.counter_values = ['0', '1', '2']
        self.labels = {}
        for i in range(3):
            text = self.counter_values[i]

            self.labels[i] = QLabel(text)
            self.labels[i].setAlignment(Qt.AlignCenter)
            self.labels[i].setObjectName(text)
            self.labels[i].setStyleSheet(
                'font-family: Arial; font-size: 13pt; '
                'color: blue; background-color:lightgreen; '
                'font-weight: bold; border: 3px solid black;'
                )

            self.h_layout_2.addWidget(self.labels[i])

        self.layout.addLayout(self.h_layout_2)

        self.h_layout_3 = QHBoxLayout(self)     # Create Horizontal Layout for Bottom Row

        self.button_names_active = ['btnActive0', 'btnActive1', 'btnActive2']
        self.command_names_active = ('setActive0', 'setActive1', 'setActive2')

        self.buttons_active = {}

        for i, command_name_active in enumerate(self.command_names_active):
            self.buttons_active[i] = QPushButton()
            self.buttons_active[i].setText("Inactive")
            self.buttons_active[i].setObjectName(self.button_names_active[i])
            self.buttons_active[i].setFixedSize(ACTIVE_WIDTH, ACTIVE_HEIGHT)
            self.buttons_active[i].setCheckable(True)
            self.buttons_active[i].setStyleSheet(
                'font-family: Arial; '
                'font-size: 12pt; '
                'color: blue; '
                'background-color:lightcyan; '
                'font-weight: bold;'
                )

            self.buttons_active[i].clicked.connect(self.call_button_active_fun(i, command_name_active))
            self.h_layout_3.addWidget(self.buttons_active[i])

        self.layout.addLayout(self.h_layout_3)

        self.setLayout(self.layout)

        # Create timer object
        timer = QTimer(self)

        # Add a method with the timer
        timer.timeout.connect(self.start_counting)

        # Call start() method to modify the timer value
        timer.start(1000)

    def start_all(self):
        self.startCounting = True
        self.btnResetAll.setEnabled(False)

    def start_counting(self):
        if self.startCounting:
            for i in range(3):
                state = self.buttons_active[i].text()
                val_int = int(self.labels[i].text())

                if state == 'Active':
                    val_int += 1

                self.labels[i].setText(str(val_int))

    def stop_counting(self):
        self.startCounting = False
        self.btnResetAll.setEnabled(True)
        print('Counting stopped')

    def resetAll(self):
        for i in range(3):
            state = self.buttons_active[i].text()

            if state == 'Active':
                self.labels[i].setText('0')
    def call_button_active_fun(self, i, command_name):

        def button_active_fun():
            print(command_name)
            if command_name == self.command_names_active[i]:
                if self.buttons_active[i].clicked:
                    if self.buttons_active[i].text() == 'Inactive':
                        self.buttons_active[i].setText('Active')
                        self.buttons_active[i].setStyleSheet(
                            'font-family: Arial; '
                            'font-size: 12pt; '
                            'font-weight: bold; '
                            'color: blue; '
                            'background-color:lightgreen;')

                        self.labels[i].setStyleSheet(
                            'font-family: Arial; font-size: 13pt; '
                            'color: blue; background-color:orange; '
                            'font-weight: bold; border: 3px solid black;'
                            )

                    else:
                        self.buttons_active[i].setText('Inactive')
                        self.buttons_active[i].setStyleSheet(
                            'font-family: Arial; '
                            'font-size: 12pt; '
                            'font-weight: bold; '
                            'color: blue; '
                            'background-color:lightcyan;')

                        self.labels[i].setStyleSheet(
                            'font-family: Arial; font-size: 13pt; '
                            'color: blue; background-color:lightgreen; '
                            'font-weight: bold; border: 3px solid black;'
                            )

        return button_active_fun

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()

    # Intercept Exception, when they are not processed
    sys._excepthook = sys.excepthook

    def exception_hook(exctype, value, traceback):
        print(exctype, value, traceback)
        sys._excepthook(exctype, value, traceback)
        sys.exit(1)

    sys.excepthook = exception_hook

    exit(app.exec_())

Tags: selfsizelabelsdeffamilycoloractivefont
1条回答
网友
1楼 · 发布于 2024-04-28 20:36:58

我使用线程成功地解决了我的问题。
我希望和我有同样问题的人能使用我的解决方案

我的GUI说明:
有三个标签显示三个计数器的内容。
按下StartAll按钮可启动这些计数器,按下StopAll按钮可停止这些计数器。
可以使用StartAll重新启动它们

只有在按下每个(所需)标签的非活动按钮并将其更改为活动后,计数器才能启动。
在计数过程中,ResetAll按钮被禁用。
由于要重置计数器的内容,必须停止计数器。
它们也必须处于非活动状态才能重置。
因此,必须按下标签下方的按钮才能更改为非活动

下面是我的工作GUI的完整代码

#!/usr/bin/env python
# Filename: 3_counter_Lastdauertester_using_tread.py
####################################################
# coding: utf-8
import sys
import time

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

ACTIVE_WIDTH = 106
ACTIVE_HEIGHT = 32

class countingWorker(QObject):
    
    #explicit signal sent in the startCounting function
    signal_set_Label = pyqtSignal(dict, dict)

    #explicit slot that takes input from the signal_start_counting
    @pyqtSlot(dict, dict)
    def startCounting(self, value, state):
        
        value_emitted = {}
        for i in range(3):
            value_emitted[i] = int(value[i])

        while True:
            for j in range(3):
                if state[j] == 'Active':
                    value_emitted[j] += 1

            self.signal_set_Label.emit(value_emitted, state)
            time.sleep(1)

class MainWindow(QWidget):
    
    #explicit signals from the start_counting_emitter function
    signal_start_counting = pyqtSignal(dict, dict)

    def __init__( self ):
        super().__init__()

        self.worker = countingWorker()
        self.thread = QThread()
        self.worker.moveToThread(self.thread)
        
        self.setFixedWidth(400)
        self.setFixedHeight(200)
        self.move(1100, 10)
        self.setWindowTitle("Test PYQT Signals")

        # Create the real GUI (MainWindow)
        ###############################################################
        self.createMainWindow()
    ###################################################################
    def createMainWindow(self):
    ###################################################################
        # Create Vertival layout for three Horizontal layouts
        self.layout = QVBoxLayout(self)
        
        # Create Horizontal Layout for Top Row
        self.h_layout_1 = QHBoxLayout(self)

        self.btnStartAll = QPushButton()
        self.btnStartAll.setText("Start All")
        self.btnStartAll.setObjectName("btnStartAll")
        self.btnStartAll.setFixedSize(ACTIVE_WIDTH, ACTIVE_HEIGHT)
        self.btnStartAll.setStyleSheet(
            'font-family: Arial; font-size: 13pt; '
            'color: blue; font-weight: bold; '
            'background-color:lightcyan;')

        self.btnStopAll = QPushButton()
        self.btnStopAll.setText("Stop All")
        self.btnStopAll.setObjectName("btnStopAll")
        self.btnStopAll.setFixedSize(ACTIVE_WIDTH, ACTIVE_HEIGHT)
        self.btnStopAll.setStyleSheet(
            'font-family: Arial; font-size: 13pt; '
            'color: blue; font-weight: bold; '
            'background-color:lightcyan;')

        self.btnResetAll = QPushButton()
        self.btnResetAll.setText("Reset All")
        self.btnResetAll.setObjectName("btnResetAll")
        self.btnResetAll.setFixedSize(ACTIVE_WIDTH, ACTIVE_HEIGHT)
        self.btnResetAll.setCheckable(True)
        self.btnResetAll.setStyleSheet(
            'font-family: Arial; font-size: 13pt; '
            'color: blue; font-weight: bold; '
            'background-color:lightcyan;')

        self.h_layout_1.addWidget(self.btnStartAll)
        self.h_layout_1.addWidget(self.btnStopAll)
        self.h_layout_1.addWidget(self.btnResetAll)

        # Add the Top Layout to the vertival layout
        self.layout.addLayout(self.h_layout_1)

        # Create Horizontal Layout for Middle Row
        self.h_layout_2 = QHBoxLayout(self)

        # Creating Counter Labels
        #####################################
        self.counter_values = ['0', '1', '2']
        self.labels = {}
        for i in range(3):
            text = self.counter_values[i]

            self.labels[i] = QLabel(text)
            self.labels[i].setAlignment(Qt.AlignCenter)
            self.labels[i].setObjectName(text)
            self.labels[i].setStyleSheet(
                'font-family: Arial; font-size: 13pt; '
                'color: blue; background-color:lightgreen; '
                'font-weight: bold; border: 3px solid black;')

            self.h_layout_2.addWidget(self.labels[i])

        # Add the Middle Layout to the vertival layout
        self.layout.addLayout(self.h_layout_2)

        # Create Horizontal Layout for Bottom Row
        self.h_layout_3 = QHBoxLayout(self)

        self.button_names_active = ['btnActive0', 'btnActive1', 'btnActive2']
        self.command_names_active = ('setActive0', 'setActive1', 'setActive2')

        self.buttons_active = {}

        for i, command_name_active in enumerate(self.command_names_active):
            self.buttons_active[i] = QPushButton()
            self.buttons_active[i].setText("Inactive")
            self.buttons_active[i].setObjectName(self.button_names_active[i])
            self.buttons_active[i].setFixedSize(ACTIVE_WIDTH, ACTIVE_HEIGHT)
            self.buttons_active[i].setCheckable(True)
            self.buttons_active[i].setStyleSheet(
                'font-family: Arial; font-size: 12pt; '
                'color: blue; background-color:lightcyan; '
                'font-weight: bold;')

            self.buttons_active[i].clicked.connect(self.call_button_active_fun(i, command_name_active))
            self.h_layout_3.addWidget(self.buttons_active[i])

        # Add the Bottom Layout to the vertival layout
        self.layout.addLayout(self.h_layout_3)

        # Set the whole Layout
        self.setLayout(self.layout)

        # making all of the connections
        self.btnStartAll.clicked.connect(self.start_counting_emitter)
        self.btnStopAll.clicked.connect(self.stop_counting)
        self.btnResetAll.clicked.connect(self.reset_all)
        self.worker.signal_set_Label.connect(self.set_Label_text)

    def start_counting_emitter(self):       
        self.signal_start_counting.connect(self.worker.startCounting)
        
        state = {}
        value = {}
        for i in range(3):
            state[i] = self.buttons_active[i].text()
            value[i] = self.labels[i].text()

        if not self.thread.isRunning():
            activity = []
            for j in range(3):
                activity.append(self.buttons_active[j].text())

            activities = (activity[0] == 'Inactive') and \
                         (activity[1] == 'Inactive') and \
                         (activity[2] == 'Inactive')

            if activities == False:
                self.btnStartAll.setCheckable(True)
                self.thread.start()
                print('thread started')

                self.btnStartAll.setEnabled(False)
                self.btnStartAll.setChecked(True)        
                self.btnStartAll.setStyleSheet(
                    'font-family: Arial; font-size: 13pt; '
                    'color: blue; font-weight: bold; '
                    'background-color:lightgreen;')

                self.btnStopAll.setEnabled(True)
                
                self.btnResetAll.setEnabled(False)
                self.btnResetAll.setChecked(True)
                self.btnResetAll.setStyleSheet(
                    'font-family: Arial; font-size: 13pt; '
                    'color: blue; font-weight: bold; '
                    'background-color:lightgreen;')
            
                self.signal_start_counting.emit(value, state)
        self.signal_start_counting.disconnect(self.worker.startCounting)

    # implicit slot of the stop buttons
    def stop_counting(self):       
        if self.thread.isRunning():
            self.thread.terminate()
            print('thread terminated')
            self.btnStartAll.setEnabled(True)
            self.btnStartAll.setChecked(False)
            self.btnStartAll.setStyleSheet(
                'font-family: Arial; font-size: 13pt; '
                'color: blue; font-weight: bold; '
                'background-color:lightcyan;')

            self.btnStopAll.setEnabled(False)
            
            self.btnResetAll.setEnabled(True)
            self.btnResetAll.setChecked(False)
            self.btnResetAll.setStyleSheet(
                'font-family: Arial; font-size: 13pt; '
                'color: blue; font-weight: bold; '
                'background-color:lightcyan;')

    def reset_all(self):
        for i in range(3):
            state = self.buttons_active[i].text()
            
            self.btnResetAll.setChecked(False)

            if state == 'Inactive':
                self.labels[i].setText('0')

    # explicit slot that takes input from the countingWorker
    # and sets the text of the provided box
    @pyqtSlot(dict, dict)
    def set_Label_text(self, labelText):
        for i in range(3):
            self.labels[i].setText(str(labelText[i]))

    def call_button_active_fun(self, i, command_name):
        def button_active_fun():
            print(command_name)
            if command_name == self.command_names_active[i]:
                if self.buttons_active[i].clicked:
                    if self.buttons_active[i].text() == 'Inactive':
                        self.buttons_active[i].setText('Active')
                        self.buttons_active[i].setStyleSheet(
                            'font-family: Arial; font-size: 12pt; '
                            'font-weight: bold; color: blue; '
                            'background-color:lightgreen;')

                        self.labels[i].setStyleSheet(
                            'font-family: Arial; font-size: 13pt; '
                            'color: blue; background-color:orange; '
                            'font-weight: bold; border: 3px solid black;')

                    else:
                        self.buttons_active[i].setText('Inactive')
                        self.buttons_active[i].setStyleSheet(
                            'font-family: Arial; font-size: 12pt; '
                            'font-weight: bold; color: blue; '
                            'background-color:lightcyan;')

                        self.labels[i].setStyleSheet(
                            'font-family: Arial; font-size: 13pt; '
                            'color: blue; background-color:lightgreen; '
                            'font-weight: bold; border: 3px solid black;')

        return button_active_fun

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()

    # Intercept Exception, when they are not processed
    sys._excepthook = sys.excepthook

    def exception_hook(exctype, value, traceback):
        print(exctype, value, traceback)
        sys._excepthook(exctype, value, traceback)
        sys.exit(1)

    sys.excepthook = exception_hook

    exit(app.exec_())

相关问题 更多 >