【问题标题】:PyQt5 Python on Raspberry Pi Threaded RFIDRaspberry Pi 线程 RFID 上的 PyQt5 Python
【发布时间】:2019-03-21 11:10:45
【问题描述】:

我有一个 Raspberry Pi 3 b+ 时间打卡应用程序,我正在尝试与 Mifare RC522 RFID 阅读器一起使用。

我在一个单独的线程上安装了 RFID 阅读器,该线程在激活时会启动一个时间打卡窗口。 RFID 线程发出一个信号,该信号由 打孔窗口内的定义。这个 def 打印出来自 RFID 信号的数据,但不会填充文本框。请参阅下面的代码。在编程方面,我非常喜欢,但一直无法弄清楚这一点

import SimpleMFRC522
import sys
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5 import QtCore
import time
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication, QLabel
import RPi.GPIO as GPIO
import threading
from threading import Timer
#Turn Off GPIO Warnings
GPIO.setmode(GPIO.BCM) # Specifies referring to GPIO pins by Broadcom SOC channel
GPIO.setwarnings(False) #Disables the Warning

###################################################################################################
#RFID Thread Class
class ThreadRFID(QThread):
    signal = pyqtSignal(str, str, int)

    def __init__(self):
        QThread.__init__(self)
        self.PunchDialog = PunchWindow()

    def __del__(self):
        self.wait()

    def run(self):

        #Initialize RFID Reader
        reader = SimpleMFRC522.SimpleMFRC522()
        try:
            id, text = reader.read()
            print(id)
            print("Text from RFID scan = " + text)

            if(id == 955738786217):  #Validate card is company ID 
                print(" scan card success")

                self.PunchDialog.show() # Launches Punch Window  

                #Send sgnal to onPunch Class in PunchWindow
                otherClass = PunchWindow()
                self.signal.connect(otherClass.onPunch)
                self.signal.emit("Data From RFID ", text, 10) 


        finally:
            GPIO.cleanup()

        time.sleep(1)        
        self.myThread = ThreadRFID()
        self.myThread.start()
########################################################################################################    

class PunchWindow(QMainWindow):    
    def __init__(self):
        super(PunchWindow, self).__init__()  
        self.move(550,200)
        self.resize(480,320)
        self.title = 'Punch Window'
        self.left = 900
        self.top = 106
        self.lbl = QLabel('Punch Times', self)
        self.txtDataField = QLineEdit(self)
        self.txtDataField.move(10, 100)
        self.txtDataField.resize(321,41)
        self.txtDataField.setText("")
        self.lbl.setText("Company ")

        #btnUpdate -- test button to validate function of update
        self.btnUpdate = QPushButton("Update", self)
        self.btnUpdate.move(230, 140)
        self.btnUpdate.clicked.connect(self.Update)
        self.btnUpdate.resize(141,91)

    @pyqtSlot(str, str, int)   
    def onPunch(self, strA, strB, int1):
        print(strA, strB, int1)
        self.txtDataField.setText(strA)
##        self.Update() 
##          
    def Update(self):
        print("In def Update")
        self.txtDataField.setText("Works to Update with btnUpdate")


#Main Window
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.title = ' '
        self.left = 420
        self.top = 106
        self.width = 800
        self.height = 600
        self.setMinimumSize(800,600)
        self.setMaximumSize(800,600)
        self.setWindowFlags( QtCore.Qt.CustomizeWindowHint ) #Turns off Min/Max/Close buttons

        self.lbl = QLabel('Company Spash Screen', self)
        self.lbl.move(10, 100)
        self.lbl.resize(321,41)

        self.initUI()

        pass1 = 1
        self.myThread = ThreadRFID()
        self.myThread.start()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    MW = MainWindow()
    MW.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python pyqt pyqt5


    【解决方案1】:

    在 Qt 中,无法从另一个线程更新 GUI,从而产生了这个问题。如果您希望在线程中发生某些事情时有一个窗口,您必须通过如下所示的信号来执行此操作,另一方面,id 请求和文本必须在循环中执行。

    import SimpleMFRC522
    from PyQt5 import QtCore, QtGui, QtWidgets 
    import RPi.GPIO as GPIO
    
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    
    
    class ThreadRFID(QtCore.QThread):
        signal = QtCore.pyqtSignal(str, str, int)
        successSignal = QtCore.pyqtSignal()
    
        def __del__(self):
            self.wait()
    
        def run(self):
            #Initialize RFID Reader
            reader = SimpleMFRC522.SimpleMFRC522()
            while True:
                _id, text = reader.read()
                if _id == 955738786217:  #Validate card is company ID 
                    print(" scan card success")
                    self.successSignal.emit()
                    self.signal.emit("Data From RFID ", text, 10) 
    
    
    class PunchWindow(QtWidgets.QMainWindow):    
        def __init__(self):
            super(PunchWindow, self).__init__()  
            self.move(550,200)
            self.resize(480,320)
            self.title = 'Punch Window'
            self.left = 900
            self.top = 106
            self.lbl = QtWidgets.QLabel('Punch Times', self)
            self.txtDataField = QtWidgets.QLineEdit(self)
            self.txtDataField.setGeometry(10, 100, 321,41)
            self.lbl.setText("Company ")
    
            #btnUpdate -- test button to validate function of update
            self.btnUpdate = QtWidgets.QPushButton("Update", self)
            self.btnUpdate.move(230, 140)
            self.btnUpdate.clicked.connect(self.Update)
            self.btnUpdate.resize(141,91)
    
        @QtCore.pyqtSlot(str, str, int)   
        def onPunch(self, strA, strB, int1):
            self.txtDataField.setText(strA) 
    
        def Update(self):
            print("In def Update")
            self.txtDataField.setText("Works to Update with btnUpdate")
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
    
            self.title = ' '
            self.left = 420
            self.top = 106
            self.width = 800
            self.height = 600
            self.setFixedSize(800,600)
            self.setWindowFlags( QtCore.Qt.CustomizeWindowHint ) #Turns off Min/Max/Close buttons
    
            self.lbl = QtWidgets.QLabel('Company Spash Screen', self)
            self.lbl.setGeometry(10, 100, 321,41)
    
            self.initUI()
    
            self.PunchDialog = PunchWindow()
    
            self.myThread = ThreadRFID(self)
            self.myThread.start()
            self.myThread.successSignal.connect(self.PunchDialog.show)
            self.myThread.signal.connect(self.PunchDialog.onPunch)
    
        def initUI(self):
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
    
        def closeEvent(self, event):
            GPIO.cleanup() 
            super(MainWindow, self).closeEvent(event)
    
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        MW = MainWindow()
        MW.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 提供的答案为使用线程提供了新的思路 - 谢谢
    • Eyllanesc 在使用提供的解决方案时 - RFID 线程始终运行时遇到一些问题。从 RFID 扫描中获得多次点击会导致误刷,其中仅读取 RFID 卡数据的一部分。还考虑设置另一个用于对 RFID 卡进行编程的模块。我在想我需要在卡验证后立即关闭 RFID 阅读器/线程。然后在 PunchWindow 关闭后重新启动。您能否就如何最好地优雅地关闭 RFID 阅读器/线程并在 PunchWindow 关闭时重新启动提供建议。谢谢——丹
    • 当从 GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback) 调用回调时,我可以向 qt ui 发出信号吗?
    猜你喜欢
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 2021-03-31
    • 2017-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多