一、图形界面的设计
1、使用QtDesigner设计基本的图形界面,如下图
将文件命名为"ui_mainwindow.ui",保存到本地文件夹
设计配置文件界面,如下图所示,
将文件命名为“ui_settingdialog.ui”,保存到本地文件夹
2、使用PyUic将xx.ui文件转换为xx.py文件
二、图形界面的显示
1、新建一个settingdialog.py文件,在文件中创建一个基于QDialog的SettingDialog类
from PyQt5.QtWidgets import QDialog
from ui_settingdialog import Ui_Dialog
class SettingDialog(QDialog):
def __init__(self,parent=None):
super().__init__(parent)
self.dialog = Ui_Dialog()
self.dialog.setupUi(self)
2、新建一个mainwindow.py文件,在文件中创建一个基于QMainWindow的MainWindow类
from PyQt5.QtWidgets import QMainWindow
from ui_mainwindow import Ui_MainWindow
from settingdialog import SettingDialog
class MainWindow(QMainWindow):
def __init__(self,parent=None):
super().__init__(parent)
self.m_ui = Ui_MainWindow()
self.m_ui.setupUi(self)
self.m_setting = SettingDialog(self)#创建一个SettingDialog实例
self.m_ui.actionConfigure.triggered.connect(self.m_setting.show)
3、新建一个main.py文件
import sys
from PyQt5.QtWidgets import QApplication
from mainwindow import MainWindow
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec())
运行main.py文件:
点击configure按键,显示Dialog界面
三、串口的操作
1、串口参数设置
class SettingDialog(QDialog):
def __init__(self,parent=None):
super().__init__(parent)
self.m_ui = Ui_Dialog()
self.m_ui.setupUi(self)
self.fill_ports_parameters()
def fill_ports_parameters(self):
self.m_ui.baudRateBox.addItem("9600", QSerialPort.Baud9600)
self.m_ui.baudRateBox.addItem("19200", QSerialPort.Baud19200)
self.m_ui.baudRateBox.addItem("38400", QSerialPort.Baud38400)
self.m_ui.baudRateBox.addItem("115200", QSerialPort.Baud115200)
self.m_ui.baudRateBox.addItem("Custom")
self.m_ui.baudRateBox.setCurrentIndex(3)
self.m_ui.dataBitsBox.addItem("5", QSerialPort.Data5)
self.m_ui.dataBitsBox.addItem("6", QSerialPort.Data6)
self.m_ui.dataBitsBox.addItem("7", QSerialPort.Data7)
self.m_ui.dataBitsBox.addItem("8", QSerialPort.Data8)
self.m_ui.dataBitsBox.setCurrentIndex(3)
self.m_ui.parityBox.addItem("None", QSerialPort.NoParity)
self.m_ui.parityBox.addItem("Even", QSerialPort.EvenParity)
self.m_ui.parityBox.addItem("Odd", QSerialPort.OddParity)
self.m_ui.parityBox.addItem("Mark", QSerialPort.MarkParity)
self.m_ui.parityBox.addItem("Space", QSerialPort.SpaceParity)
self.m_ui.stopBitsBox.addItem("1", QSerialPort.OneStop)
if sys.platform == "win32":
self.m_ui.stopBitsBox.addItem("1.5", QSerialPort.OneAndHalfStop)
self.m_ui.stopBitsBox.addItem("2", QSerialPort.TwoStop)
self.m_ui.flowControlBox.addItem("None", QSerialPort.NoFlowControl)
self.m_ui.flowControlBox.addItem("RTS/CTS", QSerialPort.HardwareControl)
self.m_ui.flowControlBox.addItem("XON/XOFF", QSerialPort.SoftwareControl)
运行效果:
2、串口号扫描
class SettingDialog(QDialog):
def __init__(self,parent=None):
super().__init__(parent)
self.m_ui = Ui_Dialog()
self.m_ui.setupUi(self)
self.fill_ports_parameters()
self.full_port_info()
def full_port_info(self):
self.m_ui.serialPortInfoListBox.clear()
for info in QSerialPortInfo.availablePorts():
self.m_ui.serialPortInfoListBox.addItem(info.portName())
def fill_ports_parameters(self):
self.m_ui.baudRateBox.addItem("9600", QSerialPort.Baud9600)
self.m_ui.baudRateBox.addItem("19200", QSerialPort.Baud19200)
运行效果:
3、点击Apply更新串口参数
创建一个Settings类初始化m_currentSettings值
class Settings():
def __init__(self):
self.name = ""
self.baud_rate = 0
self.string_baud_rate = ""
self.data_bits = QSerialPort.Data8
self.string_data_bits = ""
self.parity = QSerialPort.NoParity
self.string_parity = ""
self.stop_bits = QSerialPort.OneStop
self.string_stop_bits = ""
self.flow_control = QSerialPort.SoftwareControl
self.string_flow_control = ""
self.local_echo_enabled = False
class SettingDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.m_ui = Ui_Dialog()
self.m_ui.setupUi(self)
self.m_currentSettings = Settings() #m_currentSettings初始化
定义update_setting函数,将当前选择的参数传递给m_currentSettings
def update_settings(self):
self.m_currentSettings.name = self.m_ui.serialPortInfoListBox.currentText()
self.m_currentSettings.baud_rate = self.m_ui.baudRateBox.currentData()
self.m_currentSettings.string_baud_rate = f"{self.m_currentSettings.baud_rate}"
self.m_currentSettings.data_bits = self.m_ui.dataBitsBox.currentData()
self.m_currentSettings.string_data_bits = self.m_ui.dataBitsBox.currentText()
self.m_currentSettings.parity = self.m_ui.parityBox.currentData()
self.m_currentSettings.string_parity = self.m_ui.parityBox.currentText()
self.m_currentSettings.stop_bits = self.m_ui.stopBitsBox.currentData()
self.m_currentSettings.string_stop_bits = self.m_ui.stopBitsBox.currentText()
self.m_currentSettings.flow_control = self.m_ui.flowControlBox.currentData()
self.m_currentSettings.string_flow_control = self.m_ui.flowControlBox.currentText()
点击按键Apply调用update_settings()函数更新m_currentSettings值
class SettingDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.m_ui = Ui_Dialog()
self.m_ui.setupUi(self)
self.m_currentSettings = Settings() #m_currentSettings初始化
self.m_ui.applyButton.clicked.connect(self.apply)
self.fill_ports_parameters()
self.full_port_info()
def apply(self):
self.update_settings() #更新m_currentSettings值
self.hide() #隐藏Dialog
4、使用当前参数打开/关闭串口
from PyQt5.QtWidgets import QMainWindow, QMessageBox
from ui_mainwindow import Ui_MainWindow
from settingdialog import SettingDialog
from PyQt5.QtSerialPort import QSerialPort
from PyQt5.QtCore import QIODevice,Qt
class MainWindow(QMainWindow):
def __init__(self,parent=None):
super().__init__(parent)
self.m_ui = Ui_MainWindow()
self.m_ui.setupUi(self)
self.m_serial = QSerialPort(self)
self.m_settings = SettingDialog(self)#创建一个SettingDialog实例
self.m_ui.actionConnect.setEnabled(True)
self.m_ui.actionDisconnect.setEnabled(False)
self.m_ui.actionQuit.setEnabled(True)
self.m_ui.actionConfigure.setEnabled(True)
self.m_ui.actionConfigure.triggered.connect(self.m_settings.show)
self.m_ui.actionConnect.triggered.connect(self.open_serial_port)
self.m_ui.actionDisconnect.triggered.connect(self.close_serial_port)
def open_serial_port(self):
s = self.m_settings.setting()
self.m_serial.setPortName(s.name)
self.m_serial.setBaudRate(s.baud_rate)
self.m_serial.setParity(s.parity)
self.m_serial.setDataBits(s.data_bits)
self.m_serial.setStopBits(s.stop_bits)
self.m_serial.setFlowControl(s.flow_control)
try:
if self.m_serial.open(QIODevice.ReadWrite):
self.m_ui.actionConnect.setEnabled(False)
self.m_ui.actionDisconnect.setEnabled(True)
self.m_ui.actionConfigure.setEnabled(False)
print("open success")
else:
QMessageBox.critical(self, "Error", self.m_serial.errorString())
self.show_status_message("Open error")
print("open failed")
except:
print("can not open this serial")
def close_serial_port(self):
print("close_serial_port")
if self.m_serial.isOpen():
self.m_serial.close()
self.m_ui.actionConnect.setEnabled(True)
self.m_ui.actionDisconnect.setEnabled(False)
self.m_ui.actionConfigure.setEnabled(True)
运行效果:
四、串口数据显示
在MainWindow类中创建一个QPlainTextEdit的实例,用来显示接收到的串口数据
class MainWindow(QMainWindow):
def __init__(self,parent=None):
super().__init__(parent)
。
。
。
self.m_textEdit = QPlainTextEdit(self) #用来显示接收到的串口数据
self.setCentralWidget(self.m_textEdit) #居中显示
定义read_data()函数,用来读取串口数据,并将串口数据显示在m_textEdit中
def read_data(self):
data = self.m_serial.readAll().data().decode("utf8")
self.m_textEdit.insertPlainText(data)
bar = self.m_textEdit.verticalScrollBar() #滚动刷新
bar.setValue(bar.maximum())
当接收到串口数据时,调用read_data()函数
class MainWindow(QMainWindow):
def __init__(self,parent=None):
super().__init__(parent)
。
。
。
self.m_serial.readyRead.connect(self.read_data)
def read_data(self):
data = self.m_serial.readAll().data().decode("utf8")
self.m_textEdit.insertPlainText(data)
bar = self.m_textEdit.verticalScrollBar()
bar.setValue(bar.maximum())
运行效果:
背景颜色、字体、大小等设置
class MainWindow(QMainWindow):
def __init__(self,parent=None):
super().__init__(parent)
。
。
。
self.m_serial.readyRead.connect(self.read_data)
p = self.palette()
p.setColor(QPalette.Base, Qt.black) # 设置背景颜色
p.setColor(QPalette.Text, Qt.white) # 设置字体颜色
self.setPalette(p)
font = QFont("Monaco", 11) # 设置字体,大小
self.m_textEdit.setFont(font)
运行效果: