1. 程式人生 > >PyQT多執行緒串列埠 QtDesigner

PyQT多執行緒串列埠 QtDesigner

這篇部落格主要記錄一下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, QtWidgets

class 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

時間原因寫的比較粗糙,各位多包涵,以後業務多偏向C++QT,後續會多出相關文章