Python Qt GUI设计:做一款串口调试助手(实战篇

您所在的位置:网站首页 设计助手做什么 Python Qt GUI设计:做一款串口调试助手(实战篇

Python Qt GUI设计:做一款串口调试助手(实战篇

2024-07-17 07:14| 来源: 网络整理| 查看: 265

目录

1、UI设计

2、将UI文件转换为Py文件

3、逻辑功能实现

3.1、初始化程序

3.2、串口检测程序

3.3、 设置及打开串口程序

3.4、定时发送数据程序

3.5、发送数据程序

3.6、接收数据程序

3.7、保存日志程序

3.8、加载日志程序

3.9、打开博客、公众号程序

3.10、清除发送和接收数据显示程序

3.11、关闭串口程序

Python Qt GUI设计系列博文终于到了实战篇,本篇博文将贯穿之前的基础知识点实现一款串口调试助手。

1、UI设计

UI设计使用Qt Creator实现,组件布局如下所示:

2、将UI文件转换为Py文件

这里使用Python脚本的方式将UI文件转换为Python文件,代码如下所示:

代码语言:javascript复制import os import os.path dir ='./' #文件所在的路径 #找出路径下所有的.ui文件 def listUiFile(): list = [] files = os.listdir(dir) for filename in files: #print(filename) if os.path.splitext(filename)[1] == '.ui': list.append(filename) return list #把扩展名未.ui的转换成.py的文件 def transPyFile(filename): return os.path.splitext(filename)[0] + '.py' #通过命令把.ui文件转换成.py文件 def runMain(): list = listUiFile() for uifile in list: pyfile = transPyFile(uifile) cmd = 'pyuic5 -o {pyfile} {uifile}'.format(pyfile=pyfile, uifile=uifile) os.system(cmd) if __name__ =="__main__": runMain()3、逻辑功能实现3.1、初始化程序

首先初始化一些组件和标志位的状态,设置信号与槽的关系,实现代码如下所示:

代码语言:javascript复制 # 初始化程序 def __init__(self): super(Pyqt5_Serial, self).__init__() self.setupUi(self) self.init() self.ser = serial.Serial() self.port_check() # 设置Logo和标题 self.setWindowIcon(QIcon('Com.png')) self.setWindowTitle("串口调试助手 【公众号】美男子玩编程") # 设置禁止拉伸窗口大小 self.setFixedSize(self.width(), self.height()) # 发送数据和接收数据数目置零 self.data_num_sended = 0 self.Lineedit2.setText(str(self.data_num_sended)) self.data_num_received = 0 self.Lineedit3.setText(str(self.data_num_received)) # 串口关闭按钮使能关闭 self.Pushbuttom3.setEnabled(False) # 发送框、文本框清除 self.Text1.setText("") self.Text2.setText("") # 建立控件信号与槽关系 def init(self): # 串口检测按钮 self.Pushbuttom2.clicked.connect(self.port_check) # 串口打开按钮 self.Pushbuttom1.clicked.connect(self.port_open) # 串口关闭按钮 self.Pushbuttom3.clicked.connect(self.port_close) # 定时发送数据 self.timer_send = QTimer() self.timer_send.timeout.connect(self.data_send) self.Checkbox7.stateChanged.connect(self.data_send_timer) # 发送数据按钮 self.Pushbuttom6.clicked.connect(self.data_send) # 加载日志 self.Pushbuttom4.clicked.connect(self.savefiles) # 加载日志 self.Pushbuttom5.clicked.connect(self.openfiles) # 跳转链接 self.commandLinkButton1.clicked.connect(self.link) # 清除发送按钮 self.Pushbuttom7.clicked.connect(self.send_data_clear) # 清除接收按钮 self.Pushbuttom8.clicked.connect(self.receive_data_clear)3.2、串口检测程序

检测电脑上所有串口,实现代码如下所示:

代码语言:javascript复制 # 串口检测 def port_check(self): # 检测所有存在的串口,将信息存储在字典中 self.Com_Dict = {} port_list = list(serial.tools.list_ports.comports()) self.Combobox1.clear() for port in port_list: self.Com_Dict["%s" % port[0]] = "%s" % port[1] self.Combobox1.addItem(port[0]) # 无串口判断 if len(self.Com_Dict) == 0: self.Combobox1.addItem("无串口")3.3、 设置及打开串口程序

检测到串口后进行配置,打开串口,并且启动定时器一直接收用户输入,实现代码如下所示:

代码语言:javascript复制 # 打开串口 def port_open(self): self.ser.port = self.Combobox1.currentText() # 串口号 self.ser.baudrate = int(self.Combobox2.currentText()) # 波特率 flag_data = int(self.Combobox3.currentText()) # 数据位 if flag_data == 5: self.ser.bytesize = serial.FIVEBITS elif flag_data == 6: self.ser.bytesize = serial.SIXBITS elif flag_data == 7: self.ser.bytesize = serial.SEVENBITS else: self.ser.bytesize = serial.EIGHTBITS flag_data = self.Combobox4.currentText() # 校验位 if flag_data == "None": self.ser.parity = serial.PARITY_NONE elif flag_data == "Odd": self.ser.parity = serial.PARITY_ODD else: self.ser.parity = serial.PARITY_EVEN flag_data = int(self.Combobox5.currentText()) # 停止位 if flag_data == 1: self.ser.stopbits = serial.STOPBITS_ONE else: self.ser.stopbits = serial.STOPBITS_TWO flag_data = self.Combobox6.currentText() # 流控 if flag_data == "No Ctrl Flow": self.ser.xonxoff = False #软件流控 self.ser.dsrdtr = False #硬件流控 DTR self.ser.rtscts = False #硬件流控 RTS elif flag_data == "SW Ctrl Flow": self.ser.xonxoff = True #软件流控 else: if self.Checkbox3.isChecked(): self.ser.dsrdtr = True #硬件流控 DTR if self.Checkbox4.isChecked(): self.ser.rtscts = True #硬件流控 RTS try: time.sleep(0.1) self.ser.open() except: QMessageBox.critical(self, "串口异常", "此串口不能被打开!") return None # 串口打开后,切换开关串口按钮使能状态,防止失误操作 if self.ser.isOpen(): self.Pushbuttom1.setEnabled(False) self.Pushbuttom3.setEnabled(True) self.formGroupBox1.setTitle("串口状态(开启)") # 定时器接收数据 self.timer = QTimer() self.timer.timeout.connect(self.data_receive) # 打开串口接收定时器,周期为1ms self.timer.start(1)3.4、定时发送数据程序

通过定时器,可支持1ms至30s之间数据定时,实现代码如下所示:

代码语言:javascript复制 # 定时发送数据 def data_send_timer(self): try: if 1 0: data = self.ser.read(num) num = len(data) # 时间显示 if self.Checkbox5.isChecked(): self.Text1.insertPlainText((time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + " ") # HEX显示数据 if self.Checkbox2.checkState(): out_s = '' for i in range(0, len(data)): out_s = out_s + '{:02X}'.format(data[i]) + ' ' self.Text1.insertPlainText(out_s) # ASCII显示数据 else: self.Text1.insertPlainText(data.decode('utf-8')) # 接收换行 if self.Checkbox6.isChecked(): self.Text1.insertPlainText('\r\n') # 获取到text光标 textCursor = self.Text1.textCursor() # 滚动到底部 textCursor.movePosition(textCursor.End) # 设置光标到text中去 self.Text1.setTextCursor(textCursor) # 统计接收字符的数量 self.data_num_received += num self.Lineedit3.setText(str(self.data_num_received)) else: pass3.7、保存日志程序

将接收框中收发的数据保存到TXT文本中,实现代码如下所示:

代码语言:javascript复制 # 保存日志 def savefiles(self): dlg = QFileDialog() filenames = dlg.getSaveFileName(None, "保存日志文件", None, "Txt files(*.txt)") try: with open(file = filenames[0], mode='w', encoding='utf-8') as file: file.write(self.Text1.toPlainText()) except: QMessageBox.critical(self, '日志异常', '保存日志文件失败!')3.8、加载日志程序

加载保存到TXT文本中的数据信息到发送框中,实现代码如下所示:

代码语言:javascript复制 # 加载日志 def openfiles(self): dlg = QFileDialog() filenames = dlg.getOpenFileName(None, "加载日志文件", None, "Txt files(*.txt)") try: with open(file = filenames[0], mode='r', encoding='utf-8') as file: self.Text2.setPlainText(file.read()) except: QMessageBox.critical(self, '日志异常', '加载日志文件失败!')3.9、打开博客、公众号程序

点击按钮,打开我的公众号二维码和博客主页,实现代码如下所示:

代码语言:javascript复制 # 打开博客链接和公众号二维码 def link(self): dialog = QDialog() label_img = QLabel() label_img.setAlignment(Qt.AlignCenter) label_img.setPixmap(QPixmap("./img.jpg")) vbox = QVBoxLayout() vbox.addWidget(label_img) dialog.setLayout(vbox) dialog.setWindowTitle("快扫码关注公众号吧~") dialog.setWindowModality(Qt.ApplicationModal) dialog.exec_() webbrowser.open('https://blog.csdn.net/m0_38106923')3.10、清除发送和接收数据显示程序

清除发送数据框和接收数据框的内容和计数次数,实现代码如下所示:

代码语言:javascript复制 # 清除发送数据显示 def send_data_clear(self): self.Text2.setText("") self.data_num_sended = 0 self.Lineedit2.setText(str(self.data_num_sended)) # 清除接收数据显示 def receive_data_clear(self): self.Text1.setText("") self.data_num_received = 0 self.Lineedit3.setText(str(self.data_num_received))3.11、关闭串口程序

关闭串口,停止定时器,重置组件和标志状态,实现代码如下所示:

代码语言:javascript复制 # 关闭串口 def port_close(self): try: self.timer.stop() self.timer_send.stop() self.ser.close() except: QMessageBox.critical(self, '串口异常', '关闭串口失败,请重启程序!') return None # 切换开关串口按钮使能状态和定时发送使能状态 self.Pushbuttom1.setEnabled(True) self.Pushbuttom3.setEnabled(False) self.Lineedit1.setEnabled(True) # 发送数据和接收数据数目置零 self.data_num_sended = 0 self.Lineedit2.setText(str(self.data_num_sended)) self.data_num_received = 0 self.Lineedit3.setText(str(self.data_num_received)) self.formGroupBox1.setTitle("串口状态(关闭)")


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3