解决Python Socket Udp通讯子线程更新UI窗口显示时卡顿、奔溃问题

406 阅读2分钟

Python使用PyQt5做UI界面,开启子线程侦听UDP端口,端口接收到网络读卡器的读卡数据后刷新UI界面显示接收数据,解析数据包信息并向读卡器发送显示文字、驱动读卡器播报语音、蜂鸣响声提示、开启继电器开关等操作。

ic-14w8.png

本示例使用设备介绍:ID 网络读卡器 云读卡器 WIFI无线 RFID读卡器 POE供电 中文语音-淘宝网 (taobao.com) 电话:18002295132 QQ:95448673

   在接收数据的子线程内如果直接更改UI窗口控件来显示信息,会产生显示信息刷新不及时、造成显示卡顿、卡死或软件直接奔溃等问题,产生原因是PyQt5中,数据接收处理子线程内是不能刷新UI显示线程的,必须使用创建信号,触发时将显示信号传送给槽函数来刷新UI的方式,代码如下:

UDP端口侦听线程接收数据:

class SockListenThread(QThread):      #Socket端口侦听线程
    Sock_data = pyqtSignal(int,str)   # 创建一个信号,触发时传递显示信息给槽函数

    def run(self):
        global LastBuf
        global CardNuff

        while listen==1:
            try:
                data, addr = s.recvfrom(1024)
                RemortIPort = '%s:%s' % addr
                self.Sock_data.emit(1,RemortIPort)

                GetData = 'FromIP:%s:%s' % addr + '    Data:'
                for num in range(0, len(data)):
                    GetData = GetData + '%02X ' % (data[num])
                self.Sock_data.emit(2,GetData)
          except:
                self.Sock_data.emit(2, 'Socket端口侦听线程正在重启...')

在UI界面初始化内绑定槽函数:

    self.subSockListenThread=SockListenThread()
    self.subSockListenThread.Sock_data.connect(self.SockGetData)
    self.subSockListenThread.start()

槽函数更新UI

def SockGetData(self,dispcode,Getdata):
    if(dispcode==1):
        self.textEdit_7.setText(Getdata)
    elif(dispcode==2):
        self.ListAddItem(Getdata)
    elif (dispcode == 3):
        FieldsList = Getdata.split(',')
        rowPosition = self.tableWidget.rowCount()
        self.tableWidget.insertRow(rowPosition)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[0])
        self.tableWidget.setItem(rowPosition, 0, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[1])
        self.tableWidget.setItem(rowPosition, 1, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[2])
        self.tableWidget.setItem(rowPosition, 2, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[3])
        self.tableWidget.setItem(rowPosition, 3, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[4])
        self.tableWidget.setItem(rowPosition, 4, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[5])
        self.tableWidget.setItem(rowPosition, 5, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[6])
        self.tableWidget.setItem(rowPosition, 6, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[7])
        self.tableWidget.setItem(rowPosition, 7, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[8])
        self.tableWidget.setItem(rowPosition, 8, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[9])
        self.tableWidget.setItem(rowPosition, 9, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[10])
        self.tableWidget.setItem(rowPosition, 10, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[11])
        self.tableWidget.setItem(rowPosition, 11, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[12])
        self.tableWidget.setItem(rowPosition, 12, NewItem)
        NewItem = QtWidgets.QTableWidgetItem(FieldsList[13])
        self.tableWidget.setItem(rowPosition, 13, NewItem)
        self.tableWidget.resizeColumnsToContents()
    elif (dispcode == 4):  #显示卡号
        self.textEdit_8.setText(Getdata)
    elif (dispcode == 5): #显示读卡数据
        self.textEdit_5.setText(Getdata)