這篇文章主要介紹了Python之PyQT多線程串口程式碼分析,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧
這篇部落格主要記錄PyQT多執行緒串口的主要程式碼分析,文末會有工程的原始碼檔案
首先,從PyCharm啟動QtDesigner
之前給客戶做的上位機,保密起見,刪減了大部分的框圖構件,但不影響本篇串列教學
QtDesigner介面如下:
#忽略新增資料以及表格資料顯示,這裡用不到
著重講一下類別的構成
新建一個串口類別SerialThread,繼承自QtCore.QThread,實作全部的串口收發功能
class SerialThread(QtCore.QThread): dataReadoutSignal = pyqtSignal(str) def __init__(self, parent = None, portName = 'COM3', baudrate = 9600, parity = 'N', bytesize = 8, stopbits = 1, timeout = None): super(SerialThread, self).__init__(parent) self.m_serialPort = serial.Serial() self.m_serialPort.port = portName self.m_serialPort.baudrate = baudrate self.m_serialPort.parity = parity self.m_serialPort.bytesize = bytesize self.m_serialPort.stopbits = stopbits self.m_serialPort.timeout = timeout self.OpenScom() def OpenScom(self): try: self.m_serialPort.open() self.m_serialPort.setRTS(True) self.m_serialPort.setDTR(True) except Exception as ex: print(ex) return ex def ScomSendOneData(self,datain): if isinstance(datain,int): listTemp = [] listTemp.append(datain) d = bytes(listTemp) self.m_serialPort.write(d) else: if isinstance(datain,str): d = datain.encode('utf-8') self.m_serialPort.write(d) def ScomGetintData(self): n = self.m_serialPort.inWaiting() if n: data = self.m_serialPort.read(n).hex() #writefile print(data) def ScomGetstrData(self): if self.m_serialPort.is_open: n = self.m_serialPort.inWaiting() if n > 0: data = self.m_serialPort.read(n).decode('GB2312',errors='ignore') return data def run(self): cnt = 50 while cnt <= 3000: sendstr = str(cnt) if len(sendstr) == 2: sendstr = '00' + sendstr else: if len(sendstr) == 3: sendstr = '0' + sendstr self.ScomSendOneData('SET' + sendstr + 'V') cnt = cnt + 5 print('此时设置电压为:' + sendstr + 'V') time.sleep(2)
函數功能見名知意,此處不表。這裡主要講一下run函數,run函數實作了一次循環,50到3000步進取5,發送內容是SET0050V到SET3000V,當然,我這樣做是業務需求,如果並不需要這個功能,run函數可以寫成
def run(self): while true: time.sleep(2)
介面我們用QtDesigner製作的ui檔案透過pyUIC產生py檔
產生的程式碼如下(太長,只留前幾行)
# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'CashUpdateUI11v.ui'## Created by: PyQt5 UI code generator 5.6## WARNING! All changes made in this file will be lost!from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_cash(object): def setupUi(self, cash): ** ** **
此時,新建一個類別MyWindow,繼承QMainWindow和Ui_cash,並在類別內部,建立SerialThread成員
整體程式碼如下:
class MyWindow(QMainWindow,Ui_cash): def __init__(self): super(MyWindow,self).__init__() self.scomList = [] self.threadList = [] self.setupUi(self) self.actionOpen.triggered.connect(self.openMsg) self.actionSave.triggered.connect(self.saveMsg) self.pushButton.clicked.connect(self.ScomAutoFind) self.addDataButton.clicked.connect(self.getRHandT) self.tableWidget.setColumnCount(5) self.tableWidget.setRowCount(1) self.tableWidget.setHorizontalHeaderLabels(['11', '22', '33', '44', '55']) self.tableRowCnt = 0 self.tableColumnCnt = 0 self.ThreadComID = 0 self.addDatasignal = pyqtSignal(str) self.datadict = {'RHldy':0,'Tldy':0,'meaRT':0,'voltport':0} def getMCUdata(self): if self.ThreadComID == 0: self.showMsgbox('请先连接串口') else: self.ThreadComID.ScomSendOneData(' 5501AA') time.sleep(0.1) strt = self.ThreadComID.ScomGetstrData() if strt is None: self.showMsgbox('请将串口线连接到电路板') return None print(strt) self.datadict['voltport'] = strt[4:-3] + '.' + strt[-3:-2] self.ThreadComID.ScomSendOneData(' 5502AA') time.sleep(0.1) strt = self.ThreadComID.ScomGetstrData() if strt is None: self.showMsgbox('请将串口线连接到电路板') return None print(strt) self.datadict['meaRT'] = strt[4:-4] + '.' + strt[-4:-2] return 1 def insertTableNewLine(self): self.tableWidget.setItem(self.tableRowCnt, 0, QTableWidgetItem(self.datadict['RHldy'])) self.tableWidget.setItem(self.tableRowCnt, 1, QTableWidgetItem(self.datadict['Tldy'])) self.tableWidget.setItem(self.tableRowCnt, 2, QTableWidgetItem(self.datadict['meaRT'])) self.tableWidget.setItem(self.tableRowCnt, 3, QTableWidgetItem(self.datadict['voltport'])) self.tableWidget.setItem(self.tableRowCnt, 4, QTableWidgetItem(str(datetime.date.today())+' '+str(datetime.datetime.today().hour)+':'+str(datetime.datetime.today().minute))) self.tableRowCnt += 1 self.tableWidget.insertRow(self.tableRowCnt) def openMsg(self): file,ok = QFileDialog.getOpenFileName(self,"打开记录表","C:/",".txt") def getRHandT(self): if self.ThreadComID == 0: self.showMsgbox('请先连接串口') else: data,ok = QInputDialog.getText(self, "露点仪数据", "按如下格式记录:\n RH空格T\n示例:\n RH(0~100):66.6\n T(0~200):9.8\n 输入:66.6 9.8", QLineEdit.Normal, "66.6 9.8" ) if ok == True: data = re.findall('^[0-9]+\.[0-9]+\s+[0-9]+\.[0-9]+$', data.rstrip()) if len(data) == 0: self.showMsgbox('数据格式有误,重新录入') else: data = data[0].split() print(data) self.datadict['RHldy'] = data[0] self.datadict['Tldy'] = data[1] if self.getMCUdata() is None: return None print(self.datadict) self.insertTableNewLine() else: self.showMsgbox('请重新录入数据') def showMsgbox(self,strtoshow): QMessageBox.warning(self,'提示',strtoshow,QMessageBox.Ok) def saveMsg(self): file,ok = QFileDialog.getSaveFileName(self,"保存记录表","C:/",".txt") def ScomAutoFind(self): self.pushButton.setDisabled(True) self.scomList = list(serial.tools.list_ports.comports()) if len(self.scomList) <= 0: self.showMsgbox('未发现串口,请检查线缆连接') self.pushButton.setDisabled(False) else: comNum = len(self.scomList) print(str(comNum) + 'Scom is found') while comNum: comNum = comNum - 1 if "USB" in str(self.scomList[comNum]): self.ThreadComID = SerialThread(portName=self.scomList[comNum][0]) self.ThreadComID.start() self.graphicsView.setStyleSheet("background-color: rgb(0, 255, 0);") print(str(self.scomList[comNum]) + ' is added')
由於我用的是RS232轉USB接入電腦,設備名稱是USB-SERIAL CH340,當然還有其他RS232轉USB晶片,如PL2303等。我這裡就單獨檢查USB是否在設備名稱中,沒有檢查全名,這裡要根據實際需求變動
最後就是main了,沒什麼特別
if __name__ == "__main__": app = QApplication(sys.argv) myshow = MyWindow() myshow.show() print('程序终止') sys.exit(app.exec_())
看一下實際運行效果:
實際運行,(忽略新增資料與資料記錄表….)
點選 connect後,
當然點選新增資料也是沒問題的哈
奉上全部工程文件,連結如下:
https://download.csdn.net/download/ysgjiangsu/10324162
以上是Python之PyQT多執行緒串列程式碼分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!