从CSDN 中的一位博主的分享做了一些修改
QtSerial 的配和更稳定些
信号和槽 … … 更不容易崩
# This Python file uses the following encoding: utf-8
import sys
import time
from PySide6.QtGui import QIcon, QTextCursor
from PySide6.QtWidgets import QApplication, QWidget, QMainWindow, QMessageBox
from PySide6.QtCore import QTimer, QThread
# Important:
# You need to run the following command to generate the ui_form.py file
# pyside6-uic form.ui -o ui_form.py, or
# pyside2-uic form.ui -o ui_form.py
from ui_form import Ui_MainWindow
import PySide6.QtSerialPort as serial
import PySide6.QtCore as QtCore
class MainWindow(QMainWindow, Ui_MainWindow):
_recvThread = None
portSelect = None
bitSize = serial.QSerialPort.DataBits.Data8
def __init__(self, parent=None):
super().__init__(parent)
self.portDict = None
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.setWindowTitle('串口小工具')
self.mSerial = serial.QSerialPort()
self.ScanComPort() # 扫描一次串口端口
self.OnPortChanged()
self.ui.comboBox_Baudrate.setCurrentText("115200") # 设置默认波特率
self.ui.comboBox_ByteSize.setCurrentText("8") # 设置默认数据位
self.ui.BtnScanPort.clicked.connect(self.ScanComPort)
self.ui.BtnOpenPort.clicked.connect(self.OpenComPort)
self.ui.BtnClosePort.clicked.connect(self.CloseComPort)
self.ui.BtnSendData.clicked.connect(self.SendData)
self.ui.BtnClearRecv.clicked.connect(self.ClearRecvText)
self.ui.BtnClearSend.clicked.connect(self.ClearSendText)
self.ui.comboBox_ComPort.currentIndexChanged.connect(self.OnPortChanged)
def ClearRecvText(self):
self.ui.textBrowserRecvArea.clear()
def ClearSendText(self):
self.ui.lineEdit_SendData.clear()
def OnPortChanged(self):
if len(self.portDict) > 0:
self.ui.label_CurrentPortName.setText(self.portDict[self.ui.comboBox_ComPort.currentText()])
def ScanComPort(self):
self.portDict = {}
self.portSelect = {}
self.ui.comboBox_ComPort.clear()
portList = serial.QSerialPortInfo.availablePorts()
for port in portList:
self.portDict["%s" % port.portName()] = "%s" % port.description()
self.portSelect["%s" % port.portName()] = port
self.ui.comboBox_ComPort.addItem(port.portName())
if len(self.portDict) == 0:
QMessageBox.critical(self, "警告", "未找到串口", QMessageBox.StandardButton.Cancel,
QMessageBox.StandardButton.Cancel)
pass
def OpenComPort(self):
port = self.ui.comboBox_ComPort.currentText()
self.mSerial.setPort(self.portSelect[port])
baudrate = int(self.ui.comboBox_Baudrate.currentText())
self.mSerial.setBaudRate(baudrate)
# 数据位设置
bytesize = self.ui.comboBox_ByteSize.currentText()
if "5" == bytesize:
bitSize = serial.QSerialPort.DataBits.Data5
elif "6" == bytesize:
bitSize = serial.QSerialPort.DataBits.Data6
elif "7" == bytesize:
bitSize = serial.QSerialPort.DataBits.Data7
elif "8" == bytesize:
bitSize = serial.QSerialPort.DataBits.Data8
self.mSerial.setDataBits(bitSize)
stopbitsItems = [serial.QSerialPort.StopBits.OneStop, serial.QSerialPort.StopBits.OneAndHalfStop,
serial.QSerialPort.StopBits.TwoStop]
stopbits = stopbitsItems[self.ui.comboBox_Stopbits.currentIndex()]
self.mSerial.setStopBits(stopbits)
parityItmes = [serial.QSerialPort.Parity.NoParity,
serial.QSerialPort.Parity.OddParity,
serial.QSerialPort.Parity.EvenParity,
serial.QSerialPort.Parity.MarkParity,
serial.QSerialPort.Parity.SpaceParity,
serial.QSerialPort.Parity.NoParity]
self.mSerial.setParity(parityItmes[self.ui.comboBox_Parity.currentIndex()])
flowctrl = self.ui.comboBox_FlowCtrl.currentText()
if 'None' == flowctrl:
self.mSerial.setFlowControl(serial.QSerialPort.FlowControl.NoFlowControl)
elif 'XON/XOFF' == flowctrl:
self.mSerial.setFlowControl(serial.QSerialPort.FlowControl.SoftwareControl)
elif 'RTS/CTS' == flowctrl:
self.mSerial.setFlowControl(serial.QSerialPort.FlowControl.HardwareControl)
self.mSerial.timeout = 100
if self.mSerial.isOpen():
QMessageBox.warning(self, "警告", "串口已打开", QMessageBox.StandardButton.Cancel,
QMessageBox.StandardButton.Cancel)
else:
try:
self.ui.BtnOpenPort.setEnabled(False)
self.mSerial.open(QtCore.QIODeviceBase.OpenModeFlag.ReadWrite)
self.mSerial.flush()
self._recvThread = QThread(self)
self._recvThread.run = self.RecvData
self._recvThread.start()
except SerialException as error:
QMessageBox.critical(self, "警告", "串口打开失败:%s" % error.strerror,
QMessageBox.StandardButton.Cancel,
QMessageBox.StandardButton.Cancel)
self.ui.BtnOpenPort.setEnabled(True)
self.mSerial.readyRead.connect(self.RecvData)
def CloseComPort(self):
if self._recvThread is not None:
if self._recvThread.isRunning():
self._recvThread.exit(1)
if self.mSerial.isOpen():
self.ui.BtnOpenPort.setEnabled(True)
self.mSerial.flush()
self.mSerial.close()
pass
def SendData(self):
if self.mSerial.isOpen():
if self.mSerial.isWritable():
sendtext = self.ui.lineEdit_SendData.text() + "\r"
self.mSerial.write(sendtext.encode("utf-8"))
else:
QMessageBox.warning(self, "警告", "串口未打开,请先打开串口", QMessageBox.StandardButton.Cancel,
QMessageBox.StandardButton.Cancel)
def refreshConsole(self):
self.ui.textBrowserRecvArea.moveCursor(QTextCursor.MoveOperation.End)
def RecvData(self):
rdata = self.mSerial.readAll()
self.ui.textBrowserRecvArea.append(rdata.data().decode("utf-8").strip("\n"))
self.refreshConsole()
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec())
ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1439</width>
<height>713</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QGroupBox" name="groupBox_ComSettings">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>221</width>
<height>471</height>
</rect>
</property>
<property name="title">
<string>串口设置</string>
</property>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>400</y>
<width>201</width>
<height>51</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="BtnOpenPort">
<property name="text">
<string>打开串口</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="BtnClosePort">
<property name="text">
<string>关闭串口</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget_2">
<property name="geometry">
<rect>
<x>10</x>
<y>350</y>
<width>201</width>
<height>51</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QPushButton" name="BtnScanPort">
<property name="text">
<string>扫描端口</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QLabel" name="label_CurrentPortName">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>201</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>201</width>
<height>281</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_ComPort">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>串 口</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_ComPort">
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_Baudrate">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>波特率</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_Baudrate">
<property name="editable">
<bool>true</bool>
</property>
<property name="currentText">
<string>115200</string>
</property>
<property name="currentIndex">
<number>8</number>
</property>
<item>
<property name="text">
<string>2400</string>
</property>
</item>
<item>
<property name="text">
<string>4800</string>
</property>
</item>
<item>
<property name="text">
<string>9600</string>
</property>
</item>
<item>
<property name="text">
<string>14400</string>
</property>
</item>
<item>
<property name="text">
<string>19200</string>
</property>
</item>
<item>
<property name="text">
<string>38400</string>
</property>
</item>
<item>
<property name="text">
<string>56000</string>
</property>
</item>
<item>
<property name="text">
<string>57600</string>
</property>
</item>
<item>
<property name="text">
<string>115200</string>
</property>
</item>
<item>
<property name="text">
<string>128000</string>
</property>
</item>
<item>
<property name="text">
<string>256000</string>
</property>
</item>
<item>
<property name="text">
<string>230400</string>
</property>
</item>
<item>
<property name="text">
<string>1000000</string>
</property>
</item>
<item>
<property name="text">
<string>2000000</string>
</property>
</item>
<item>
<property name="text">
<string>3000000</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_ByteSize">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>数据位</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_ByteSize">
<property name="editable">
<bool>false</bool>
</property>
<property name="currentText">
<string>8</string>
</property>
<property name="currentIndex">
<number>3</number>
</property>
<item>
<property name="text">
<string>5</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>7</string>
</property>
</item>
<item>
<property name="text">
<string>8</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label_Stopbits">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>停止位</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_Stopbits">
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>1.5</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label_Parity">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>校验位</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_Parity">
<item>
<property name="text">
<string>None</string>
</property>
</item>
<item>
<property name="text">
<string>Odd</string>
</property>
</item>
<item>
<property name="text">
<string>Even</string>
</property>
</item>
<item>
<property name="text">
<string>Mark</string>
</property>
</item>
<item>
<property name="text">
<string>Space</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="label_CTS">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>流 控</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_FlowCtrl">
<item>
<property name="text">
<string>None</string>
</property>
</item>
<item>
<property name="text">
<string>RTS/CTS</string>
</property>
</item>
<item>
<property name="text">
<string>XON/XOFF</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>250</x>
<y>20</y>
<width>1181</width>
<height>471</height>
</rect>
</property>
<property name="title">
<string>接收区</string>
</property>
<widget class="QTextBrowser" name="textBrowserRecvArea">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>1161</width>
<height>441</height>
</rect>
</property>
</widget>
</widget>
<widget class="QGroupBox" name="groupBox_2">
<property name="geometry">
<rect>
<x>250</x>
<y>500</y>
<width>1181</width>
<height>151</height>
</rect>
</property>
<property name="title">
<string>发送区</string>
</property>
<widget class="QLineEdit" name="lineEdit_SendData">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>561</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="BtnSendData">
<property name="geometry">
<rect>
<x>580</x>
<y>20</y>
<width>181</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>发送数据</string>
</property>
</widget>
<widget class="QPushButton" name="BtnClearRecv">
<property name="geometry">
<rect>
<x>760</x>
<y>20</y>
<width>171</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>清空接收区</string>
</property>
</widget>
<widget class="QPushButton" name="BtnClearSend">
<property name="geometry">
<rect>
<x>930</x>
<y>20</y>
<width>171</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>清空发送区</string>
</property>
</widget>
<widget class="QPushButton" name="BtnSendData_2">
<property name="geometry">
<rect>
<x>930</x>
<y>60</y>
<width>171</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>循环执行脚本</string>
</property>
</widget>
<widget class="QPushButton" name="BtnSendData_3">
<property name="geometry">
<rect>
<x>760</x>
<y>60</y>
<width>171</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>导入命令脚本</string>
</property>
</widget>
<widget class="QPushButton" name="BtnSendData_4">
<property name="geometry">
<rect>
<x>580</x>
<y>60</y>
<width>181</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>执行命令脚本</string>
</property>
</widget>
<widget class="QComboBox" name="comboBox">
<property name="geometry">
<rect>
<x>10</x>
<y>100</y>
<width>561</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="BtnSendData_5">
<property name="geometry">
<rect>
<x>580</x>
<y>100</y>
<width>181</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>变更输出解析类型</string>
</property>
</widget>
<widget class="QPushButton" name="BtnSendData_6">
<property name="geometry">
<rect>
<x>760</x>
<y>100</y>
<width>171</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>导入输出解析类型</string>
</property>
</widget>
<widget class="QPushButton" name="BtnSendData_7">
<property name="geometry">
<rect>
<x>930</x>
<y>100</y>
<width>171</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>冻结/解冻</string>
</property>
</widget>
<widget class="QComboBox" name="comboBox_2">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>561</width>
<height>31</height>
</rect>
</property>
</widget>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1439</width>
<height>17</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
> 添加键盘监听事件