python - 事件期间GUI没有变化吗? (Python3.6、PyQt5)

标签 python user-interface events pyqt5

我正在尝试在操作过程中更改按钮的样式。

当按下按钮时,我想让它们变成蓝色,然后读取 rfid 卡,然后通过 ID 将按钮的颜色更改为绿色或红色(在代码中只是红色以使其更容易)。

问题是,将按钮样式更改为蓝色没有任何作用(绿色和红色效果很好)。 它正在等待完成“clicked()”方法吗? 如何告诉 PyQt5“现在就做!” ?

编辑:我将伪代码修改为可重现的示例。

#!/usr/bin/python3
import sys
import time
from PyQt5.QtWidgets import *

class MainScreen(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.button = QPushButton("TEXT")
        self.button.clicked.connect(self.clicked)
        self.changeButtonColor("black")  # set default style
        self.grid = QGridLayout(self)
        self.grid.addWidget(self.button)
        self.show()

    def changeButtonColor(self, color):
        self.button.setStyleSheet("QPushButton{ \
                color: "+color+"; font: bold 18px;}")

    def clicked(self):
        self.changeButtonColor("blue")  # nothing happening (this is my problem!)
        uid = self.readCard()  # reading ID from rfid card
        self.changeButtonColor("red")

    def readCard(self):
        #return rfid.read() # in real case
        time.sleep(2)
        return "12345678"

def main():
    app = QApplication(sys.argv)
    window = MainScreen()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

最佳答案

void QTimer::singleShot(int msec, const QObject *receiver, const char *member)

This static function calls a slot after a given time interval.

It is very convenient to use this function because you do not need to bother with a timerEvent or create a local QTimer object.

import sys
import time
from PyQt5.QtWidgets import *
from PyQt5 import QtCore

class MainScreen(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.button = QPushButton("TEXT")
        self.button.clicked.connect(self.clicked)
        self.changeButtonColor("black")             
        self.grid = QGridLayout(self)
        self.grid.addWidget(self.button)
        self.show()

    def changeButtonColor(self, color):
        self.button.setStyleSheet("QPushButton{ \
                color: "+color+"; font: bold 18px;}")

    def clicked(self):
        self.changeButtonColor("blue")  # nothing happening (this is my problem!)
#        time.sleep(2)                  # reading ID from rfid card
#        self.changeButtonColor("red")
        QtCore.QTimer.singleShot(2000, lambda: self.changeButtonColor("red"))             # <---

def main():
    app = QApplication(sys.argv)
    window = MainScreen()
    sys.exit(app.exec_())

enter image description here

<小时/>

更新

import sys
import time
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *

class Worker(QtCore.QObject):                              # +++

    started  = QtCore.pyqtSignal()
    finished = QtCore.pyqtSignal()
    data     = QtCore.pyqtSignal(str)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.running = False
        self.stop = 5

    @QtCore.pyqtSlot()
    def read_data_from_sensor(self):
        self.started.emit()
        time.sleep(1)                                  # We simulate the blocking process
        while self.running and self.stop:
            dt  = time.strftime("%Y-%m-%d %H:%M:%S")
            self.data.emit(dt)
            time.sleep(1)                              # We simulate the blocking process
            self.stop -= 1
            
        self.finished.emit()


class MainScreen(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.button = QPushButton("TEXT Start")
        self.button.clicked.connect(self.clicked)
        self.changeButtonColor("black") 
        
        self.label_data = QtWidgets.QLabel(self, alignment=QtCore.Qt.AlignCenter)
        self.label_data.setText('Pending')
        
        self.grid = QGridLayout(self)
        self.grid.addWidget(self.label_data)
        self.grid.addWidget(self.button)
        self.show()
### vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv       
        self._worker = Worker()
        self._worker.started.connect(self.on_started)
        self._worker.finished.connect(self.on_finished)
        self._worker.data.connect(self.update_label)

        self._thread = QtCore.QThread(self)
        self._thread.start()
        self._worker.moveToThread(self._thread)      

    @QtCore.pyqtSlot()
    def on_started(self):
        self.label_data.setText("Start to read")
        self.button.setText("TEXT Stop")
        self.button.setEnabled(True) 
        self._worker.stop = 5
        
    @QtCore.pyqtSlot()
    def on_finished(self):
        self.label_data.setText("Pending")
        self.button.setText("TEXT Start")
        self.button.setEnabled(True)
        self.changeButtonColor("red")                      # <---
        self._worker.running = False
        self._worker.stop = 5
        
    @QtCore.pyqtSlot(str)
    def update_label(self, data):
        self.label_data.setText(data)
### ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        

    def changeButtonColor(self, color):
        self.button.setStyleSheet("QPushButton{ \
                color: "+color+"; font: bold 18px;}")

    def clicked(self):
        self.changeButtonColor("blue")  # nothing happening (this is my problem!)
#        time.sleep(2)                  # reading ID from rfid card
#        self.changeButtonColor("red")
#        QtCore.QTimer.singleShot(2000, lambda: self.changeButtonColor("red"))             # <---

### vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv       
        if self._worker.running:
            self._worker.running = False
        else:
            self._worker.running = True
            QtCore.QTimer.singleShot(0, self._worker.read_data_from_sensor)
        self.button.setEnabled(False)        
### ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^       
        

def main():
    app = QApplication(sys.argv)
    window = MainScreen()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

enter image description here

关于python - 事件期间GUI没有变化吗? (Python3.6、PyQt5),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57852863/

相关文章:

python - 如何对 View Qweb 中的字段求和?

python - 根据 py.test 中的参数跳过测试

python - 默认文本以及列表 textvariable Entry widget Tkinter

javascript - 在 Javascript 中转发事件

python - 避免 python 中的多个嵌套 for 循环

python - 如何使用 Python 锁定 Azure 资源组中的所有资源

user-interface - wxpython 角落中的 UI

android - Eclipse 中的某些布局文件不会出现图形布局选项卡

javascript - 如何将事件监听器附加到打开的颜色框?

Android 处理所有输入键一个触摸事件