Мигающие индикаторы PyQt5

Рейтинг: 3Ответов: 2Опубликовано: 07.02.2023

Я написал небольшой интерфейс с использованием библиотеки PyQt5. В нем есть таблица, куда поступают данные с прибора, а внизу статус панель.

При приеме или передаче каждого пакета данных с прибора, на статус панели должны мигать индикаторы Tx и Rx типа светодиода на плате. Сейчас это просто статичный текст.

Как мне реализовать это мигание зеленым и красным цветом на 30-50 мс при передаче данных?
Вопрос касается только стороны GUI, откуда брать сигнал, мне понятно. Какой виджет PyQt5 лучше использовать и каким образом?

Код статус GUI:

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # конфигурация главного окна и центрального виджета
        self.central_widget = QWidget(self)
        self.setGeometry(50, 50, 1500, 800)
        self.setWindowTitle('Чтение БКУ')
        self.setCentralWidget(self.central_widget)
        self.layout_main_window = QVBoxLayout()
        self.central_widget.setLayout(self.layout_main_window)
        
        # конфигурация верхней панели инструментов
        self.btn_start_reading = QPushButton("Считать")
        self.btn_start_reading.clicked.connect(self.start_read)
        self.btn_save_to_file = QPushButton("Экспорт")
        self.btn_save_to_file.clicked.connect(self.save_to_file)
        self.layout_toolbar = QHBoxLayout()
        self.layout_toolbar.addStretch(1)
        self.layout_toolbar.addWidget(self.btn_start_reading)
        self.layout_toolbar.addWidget(self.btn_save_to_file)
        self.layout_main_window.addLayout(self.layout_toolbar)

        # конфигурация таблицы
        self.layout_table = QHBoxLayout()
        self.table = QTableWidget()
        self.table.setColumnCount(9)
        self.table.setRowCount(13500)
        self.table.setHorizontalHeaderLabels(['№', 'Дата и время', 'БКУ', 'КЛ', 'АУ', 'Канал', 'Код события', 'Доп. параметр', 'Описание'])
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.horizontalHeader().setVisible(True)
        self.layout_table.addWidget(self.table)
        self.layout_main_window.addLayout(self.layout_table)

        # конфигурация статус панели
        self.layout_status_bar = QHBoxLayout()
        self.layout_status_bar.addStretch(0)
        self.layout_status_bar.setDirection(QBoxLayout.RightToLeft)
        self.btn_select_port = QPushButton('Выбрать порт')
        self.label_tx = QLabel('Tx:   ')
        self.label_rx = QLabel('Rx:   ')
        self.label_trans_packets = QLabel('Передано: 0  ')
        self.label_rec_packets = QLabel('Принято: 0  ')
        self.label_count_of_log_entries = QLabel('Количество записей: 0  ')
        self.label_session_time = QLabel('00:00:00')
        self.layout_status_bar.addWidget(self.label_session_time)
        self.layout_status_bar.addWidget(self.label_count_of_log_entries)
        self.layout_status_bar.addWidget(self.label_rec_packets)
        self.layout_status_bar.addWidget(self.label_trans_packets)
        self.layout_status_bar.addWidget(self.label_rx)
        self.layout_status_bar.addWidget(self.label_tx)
        self.layout_status_bar.addWidget(self.btn_select_port)
        self.layout_main_window.addLayout(self.layout_status_bar)

Так выглядит приложение. Индикаторы Tx и Rx в левом нижнем углу.введите сюда описание изображения

Ответы

▲ 1Принят

Как вариант, примерно так:

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


# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
class Thread(QtCore.QThread):
    dateSignal = QtCore.pyqtSignal(str)
    
    def __init__(self):    
        super().__init__()
        
    def run(self):        
        while True:
            # тут вы получаете какие-то данные с прибора
            text = random.choice(['Tx', 'Rx'])
            # тут вы испускаете сигнал и передаете какие-то данные
            self.dateSignal.emit(text)
            #           40 мс
            self.msleep(40)                             
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # конфигурация главного окна и центрального виджета
        self.central_widget = QWidget(self)
        self.setWindowTitle('Чтение БКУ')
        self.setCentralWidget(self.central_widget)
        self.layout_main_window = QVBoxLayout()
        self.central_widget.setLayout(self.layout_main_window)
        
        # конфигурация верхней панели инструментов
        self.btn_start_reading = QPushButton("Считать")
        self.btn_start_reading.clicked.connect(self.start_read)
        self.btn_save_to_file = QPushButton("Экспорт")
        self.btn_save_to_file.clicked.connect(self.save_to_file)
        self.layout_toolbar = QHBoxLayout()
        self.layout_toolbar.addStretch(1)
        self.layout_toolbar.addWidget(self.btn_start_reading)
        self.layout_toolbar.addWidget(self.btn_save_to_file)
        self.layout_main_window.addLayout(self.layout_toolbar)

        # конфигурация таблицы
        self.layout_table = QHBoxLayout()
        self.table = QTableWidget()
        self.table.setColumnCount(9)
        self.table.setRowCount(13500)
        self.table.setHorizontalHeaderLabels(['№', 'Дата и время', 'БКУ', 'КЛ', 'АУ', 'Канал', 'Код события', 'Доп. параметр', 'Описание'])
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.horizontalHeader().setVisible(True)
        self.layout_table.addWidget(self.table)
        self.layout_main_window.addLayout(self.layout_table)

        # конфигурация статус панели
        self.layout_status_bar = QHBoxLayout()
        self.layout_status_bar.addStretch(0)
        self.layout_status_bar.setDirection(QBoxLayout.RightToLeft)
        self.btn_select_port = QPushButton('Выбрать порт')
# +++        
        self.label_tx = QLabel('Tx:')
        self.rb_tx = QRadioButton()                                 # +++
        self.rb_tx.setObjectName('rb_tx')                           # +++
        self.label_rx = QLabel('Rx:')
        self.rb_rx = QRadioButton()                                 # +++
        self.rb_rx.setObjectName('rb_rx')                           # +++
        
        self.label_trans_packets = QLabel('Передано: 0  ')
        self.label_rec_packets = QLabel('Принято: 0  ')
        self.label_count_of_log_entries = QLabel('Количество записей: 0  ')
        self.label_session_time = QLabel('00:00:00')
        self.layout_status_bar.addWidget(self.label_session_time)
        self.layout_status_bar.addWidget(self.label_count_of_log_entries)
        self.layout_status_bar.addWidget(self.label_rec_packets)
        self.layout_status_bar.addWidget(self.label_trans_packets)
# +++   
        self.layout_status_bar.addWidget(self.rb_rx)                # +++
        self.layout_status_bar.addWidget(self.label_rx)
        self.layout_status_bar.addWidget(self.rb_tx)                # +++
        self.layout_status_bar.addWidget(self.label_tx)
        
        self.layout_status_bar.addWidget(self.btn_select_port)
        self.layout_main_window.addLayout(self.layout_status_bar)

        self.thread = Thread()                                     # +++
        self.thread.dateSignal.connect(self.update_data)           # +++
        
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv        
        size = 20
        border = 2
        self.setStyleSheet('''
            #rb_rx::indicator, #rb_tx::indicator {{
            
                border: {border}px solid #a35709; 
                height: {size}px;
                width: {size}px;
                border-radius: {radius}px;
                
                background: qradialgradient(
                    cx:.5, cy:.5, radius: {innerRatio},
                    fx:.5, fy:.5,
                    stop:0 {color}, 
                    stop:0.45 {color},
                    stop:0.5 transparent,
                    stop:1 transparent
                    );
            }}
            #rb_rx::indicator:checked, #rb_tx::indicator:checked {{
                background: qradialgradient(
                    cx:.5, cy:.5, radius: {innerRatio},
                    fx:.5, fy:.5,
                    stop:0 {checkColor}, 
                    stop:0.45 {checkColor},
                    stop:0.5 transparent,
                    stop:1 transparent
                    );
            }}
        '''.format(
            size=size - border * 2, 
            border=border, 
            radius=size // 2, 
            innerRatio=1 - (border * 2 + 1) / size, 
            color='#ff0000',
            checkColor='#bbff00',
        )) 
        

    def start_read(self):
        self.thread.start()
        
    def save_to_file(self):
        pass

    def update_data (self, text):
        #print(f'{text}')
        if text == 'Tx':
            self.rb_tx.click()
        elif text == 'Rx':
            self.rb_rx.click()
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.resize(700, 500)
    window.show()
    sys.exit(app.exec())

введите сюда описание изображения

▲ 0

Можно использовать QLabel

if signal:
    QLabel().setStyleSheet("background-color : red;")
else:
    QLabel().setStyleSheet("background-color : white;")