时间:2026-03-02 19:43
人气:
作者:admin
使用qt设计师
需要注意的是
最后设置整体自动调整大小时,对于QMainWindow窗口需要右键最基本的框,选择布局,不然在右侧是没有布局选项的
设置对应窗口的对齐为 0
默认时
选择自己使用的是QMainWindow还是QWidget
from PySide6.QtWidgets import QApplication,QMainWindow,QWidget
#ui为上一层目录
from ui.Ui_serial_up import Ui_MainWindow
class MyWindow(QMainWindow,Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
if __name__ == "__main__":
app = QApplication()
window = MyWindow()
window.show()
sys.exit(app.exec())
from PySide6.QtCore import QThread,Signal
import serial
import serial.tools.list_ports
#接收线程
class SerialReadThread(QThread):
ReadSignal = Signal(str) #接收信号
def __init__(self,serial_obj):
super().__init__()
def run():
def stop():
子窗口现在qt设计师设计好,使用QSialog类型
#子窗口界面
class SettingSerial(QDialog,Ui_Dialog):
def __init__(self,parent = None):#parent 为传入形参接口
super().__init__(parent)
self.setupUi(self)#调用子窗口Ui
#绑定自带的确认和取消键
#连接固定的确定取消方法
#self.reject()和self.accept()是取消和确认方法
self.buttonBox.accepted.connect(self.buttonAccept)
self.buttonBox.rejected.connect(self.reject)
def buttonAccept(self):
self.accept()
def backSetting(self):
'''子窗口返回方法,同与父窗口调用后关闭子窗口时调用'''
#界面
class MyWindow(QMainWindow,Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)#调用父窗口Ui
def SerialSend(self):
def SerialReceive(self):
def SerialStart(self):
def SerialStop(self):
def ClearTx(self):
def ClearRx(self):
首先编写主界面的基本操作
#清除
def clearTx(self):
self.TextEdit_2.clear()
def clearRx(self):
self.TextEdit_1.clear()
#变量定义
def initVariable(self):
self.baudrate = "115200"
self.bytesize = '8'
self.stopbits_set = '1'
self.parity_set = 'None'
# 串口对象
self.serial_port = None
self.reader_thread = None
self.send_byte_count = 0 #发送字节总数
self.receive_byte_count = 0 #接收字节总数
#按键关联方法
def ConnectButton(self):
#关联按键
self.pushButton_5.clicked.connect(self.clearTx)
self.pushButton.clicked.connect(self.clearRx)
#打开串口
self.pushButton_2.clicked.connect(self.SerialSwitch)
#刷新端口
self.action10.setShortcut('F5')
self.action10.setStatusTip('刷新端口')
self.action10.triggered.connect(self.RefreshSerial)
#串口设置
self.pushButton_4.clicked.connect(self.open_dialog)
self.action20.setStatusTip('配置串口')
self.action20.triggered.connect(self.open_dialog)
#更改baud下拉栏
self.comboBox_2.currentIndexChanged.
connect(self.backBaudrate)
#发送数据
self.pushButton_3.clicked.connect(self.SendData)
def SerialSwitch(self):
'''设置标志位,区分打开关闭串口'''
if self.serial_port and self.serial_port.is_open:
self.closeSerial()
else:
self.StartSerial()
def StartSerial(self):
#读取当前com口
is_com = self.comboBox.currentText()
if not is_com :
QMessageBox.warning(self,"warning","没有可用的串口")
return
#读取的端口从 - 分割开
com = is_com.split(" - ")[0]
#把确认的端口信息赋值给局部变量,后面赋值给串口库形参
baudrate = self.baudrate
bytesize = int(self.bytesize)
stopbits = serial.STOPBITS_ONE
if self.stopbits_set == '1.5':
stopbits = serial.STOPBITS_ONE_POINT_FIVE
elif self.stopbits_set == '2':
stopbits = serial.STOPBITS_TWO
parity = serial.PARITY_NONE
if self.parity_set == 'Odd':
parity = serial.PARITY_ODD
elif self.parity_set == 'Even':
parity = serial.PARITY_EVEN
elif self.parity_set == 'Mark':
parity = serial.PARITY_MARK
elif self.parity_set == 'Space':
parity = serial.PARITY_SPACE
try:
self.serial_port = serial.Serial(
port=com,
baudrate=baudrate,
bytesize=bytesize,
stopbits=stopbits,
parity=parity,
timeout=0.1 # 读超时,让线程可以循环检查停止标志
)
except Exception as e:
QMessageBox.critical(self, "错误", f"无法打开串口:{e}")
return
#开启多线程
self.reader_thread = SerialReadThread(self.serial_port)
#判断ReadSignal信号是否接收到数据,接收到进入数据处理
self.reader_thread.ReadSignal.connect(self.on_data_received)
self.reader_thread.start()
#打开串口后将按钮改为关闭
self.pushButton_2.setText('关闭串口')
#失能部分按键,防止误触,出错
self.set_serial_settings_enabled(False)
def closeSerial(self):
if self.reader_thread:
self.reader_thread.stop()
self.reader_thread = None
if self.serial_port and self.serial_port.is_open:
self.serial_port.close()
self.serial_port = None
self.pushButton_2.setText("打开串口")
self.set_serial_settings_enabled(True)
失能使能模块方法包装
def set_serial_settings_enabled(self, enabled):
self.comboBox.setEnabled(enabled)
self.comboBox_2.setEnabled(enabled)
self.pushButton_4.setEnabled(enabled)
self.action20.setEnabled(enabled)
打开串口的时候,关闭其他使能
class SerialReadThread(QThread):
#创建信号 , bytes类型
ReadSignal = Signal(bytes)
def __init__(self,serial_port):
super().__init__()
self.serial_port = serial_port
self.is_running = False
def run(self):
self.is_running = True
while self.is_running and self.serial_port and self.serial_port.is_open:
try:
#接收数据
data = self.serial_port.read(self.serial_port.in_waiting or 1)
if data:
#将接收到的数据连接上信号
self.ReadSignal.emit(data)
except Exception as e:
break
def stop(self):
self.is_running = False
#等待主线程完成,使子线程完全退出
self.wait()
def on_data_received(self,data):
#状态栏的变量,接收数据+1
self.receive_byte_count += len(data)
self.update_status_bar()
#判断hex是否勾选
if self.checkBox_3.isChecked():
hex_str = data.hex().upper()
hex_str = ' '.join(hex_str[i:i+2] for i in range(0, len(hex_str), 2))
self.TextEdit_1.insertPlainText(hex_str + " ")
else:
try:
text = data.decode('utf-8', errors='replace')
except:
text = str(data)
self.TextEdit_1.insertPlainText(text)
#自动滚动
#返回光标
cursor = self.TextEdit_1.textCursor()
#光标移动到最后
cursor.movePosition(cursor.MoveOperation.End)
#页面到光标处
self.TextEdit_1.setTextCursor(cursor)
class SettingSerial(QDialog,Ui_Dialog):
def __init__(self,parent = None):
super().__init__(parent)
self.setupUi(self)
self.buttonBox.accepted.connect(self.buttonAccept)
self.buttonBox.rejected.connect(self.reject)
#刷新子窗口com,父子一致
def refreashCom(self,postList,currentPort):
self.comboBox.clear()
self.comboBox.addItems(postList)
if currentPort :
Index = self.comboBox.findText(currentPort)
if Index>=0:
self.comboBox.setCurrentIndex(Index)
#刷新子窗口,父子一致
def refreashBaud(self,baudrate):
if baudrate :
Index = self.comboBox_2.findText(baudrate)
if Index>=0:
self.comboBox_2.setCurrentIndex(Index)
#刷新子窗口,父子一致
def refreashother(self,bytesize,stopbits_set,parity_set):
if bytesize :
Index = self.comboBox_3.findText(bytesize)
if Index>=0:
self.comboBox_3.setCurrentIndex(Index)
if stopbits_set :
Index = self.comboBox_4.findText(stopbits_set)
if Index>=0:
self.comboBox_4.setCurrentIndex(Index)
if parity_set :
Index = self.comboBox_6.findText(parity_set)
if Index>=0:
self.comboBox_6.setCurrentIndex(Index)
def buttonAccept(self):
self.accept()
def backSetting(self):
com = self.comboBox.currentText()#.split(" - ")[0]
return (com
,self.comboBox_2.currentText()
,self.comboBox_3.currentText()
,self.comboBox_4.currentText()
,self.comboBox_6.currentText()
,self.comboBox_5.currentText()
)
父窗口按键关联
def open_dialog(self):
dialog = SettingSerial(self)
'''刷新数据'''
self.RefreshSerial()
dialog.refreashCom(self.postList,self.currentPort)
dialog.refreashBaud(self.baudrate)
dialog.refreashother(self.bytesize,self.stopbits_set,self.parity_set)
#使用.exec()方法,等待子窗口点击确认,此时可以返回一些数据
if dialog.exec() == QDialog.Accepted:
self.settings = dialog.backSetting()
self.settingAccept(self.settings)
返回数据
def settingAccept(self,settings):
self.currentPort,self.baudrate,self.bytesize,self.stopbits_set,self.parity_set,flow_set = settings
if self.currentPort :
Index = self.comboBox.findText(self.currentPort)
if Index>=0:
self.comboBox.setCurrentIndex(Index)
if self.baudrate :
baud = self.comboBox_2.findText(self.baudrate)
if baud>=0:
self.comboBox_2.setCurrentIndex(baud)
def SendData(self):
if not self.serial_port or not self.serial_port.is_open:
QMessageBox.warning(self, "警告", "请先打开串口!")
return
#读取当前发送框有什么
text = self.TextEdit_2.toPlainText()
if not text:
return
#判断是不是 使用hex方式
if self.checkBox_3.isChecked():
hex_str = ''.join(text.split())
try:
#.fromhex 转16进制
data = bytes.fromhex(hex_str)
except ValueError as e:
QMessageBox.warning(self, "错误", f"无效的十六进制字符串:{e}")
return
else:
#ASCII发送
data = text.encode('utf-8', errors='ignore')
try:
#返回发送的长度
sent_bytes = self.serial_port.write(data)
#状态栏
self.send_byte_count += sent_bytes
self.update_status_bar()
except Exception as e:
QMessageBox.critical(self, "错误", f"发送失败:{e}")
if __name__ == "__main__":
app = QApplication()
window = MyWindow()
window.setWindowIcon(QIcon("icon.png"))
window.show()
sys.exit(app.exec())
可以创建QLabel窗口,然后使用.addPermanentWidget(self.label)一直添加到状态栏右侧
def status_bars(self):
'''多状态栏'''
status_text = f"接收:{self.receive_byte_count} 字节 | 发送:{self.send_byte_count} 字节"
self.serial_status_label = QLabel(status_text)
self.statusBar.addPermanentWidget(self.serial_status_label)
self.textlabel = QLabel(' 天天好心情')
self.statusBar.addPermanentWidget(self.textlabel)
def update_status_bar(self):
"""更新状态栏显示:发送/接收字节数"""
# status_text = f"接收:{self.receive_byte_count} 字节 | 发送:{self.send_byte_count} 字节"
# self.statusBar.setStyleSheet("QStatusBar { padding-left: 1000px; }")
# 设置状态栏文本(showMessage默认显示5秒,传0表示永久显示)
# self.statusBar.showMessage(status_text, 0)
self.serial_status_label.setText(f"接收:{self.receive_byte_count} 字节 | 发送:{self.send_byte_count} 字节")