目录

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设计系列博文终于到了实战篇,本篇博文将贯穿之前的基础知识点实现一款串口调试助手。

关注【公众号】 美男子玩编程,回复关键字:串口调试助手,获取项目源码~

资源下载:PythonQt串口调试助手-嵌入式文档类资源-CSDN下载

1、UI设计

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

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

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

import os
import os.pathdir ='./' #文件所在的路径#找出路径下所有的.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、初始化程序

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

    # 初始化程序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 = 0self.Lineedit2.setText(str(self.data_num_sended))self.data_num_received = 0self.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、串口检测程序

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

    # 串口检测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、 设置及打开串口程序

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

    # 打开串口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.FIVEBITSelif flag_data == 6:self.ser.bytesize = serial.SIXBITSelif flag_data == 7:self.ser.bytesize = serial.SEVENBITSelse:self.ser.bytesize = serial.EIGHTBITSflag_data = self.Combobox4.currentText()  # 校验位if flag_data == "None":self.ser.parity = serial.PARITY_NONEelif flag_data == "Odd":self.ser.parity = serial.PARITY_ODDelse:self.ser.parity = serial.PARITY_EVENflag_data = int(self.Combobox5.currentText()) # 停止位if flag_data == 1:self.ser.stopbits = serial.STOPBITS_ONEelse:self.ser.stopbits = serial.STOPBITS_TWOflag_data = self.Combobox6.currentText()  # 流控if flag_data == "No Ctrl Flow":self.ser.xonxoff = False  #软件流控self.ser.dsrdtr  = False  #硬件流控 DTRself.ser.rtscts  = False  #硬件流控 RTSelif flag_data == "SW Ctrl Flow":self.ser.xonxoff = True  #软件流控else:         if self.Checkbox3.isChecked():self.ser.dsrdtr = True  #硬件流控 DTRif self.Checkbox4.isChecked():self.ser.rtscts = True  #硬件流控 RTStry: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)# 打开串口接收定时器,周期为1msself.timer.start(1)

3.4、定时发送数据程序

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

    # 定时发送数据def data_send_timer(self):try:if 1<= int(self.Lineedit1.text()) <= 30000:  # 定时时间1ms~30s内if self.Checkbox7.isChecked():self.timer_send.start(int(self.Lineedit1.text()))self.Lineedit1.setEnabled(False)else:self.timer_send.stop()self.Lineedit1.setEnabled(True)else:QMessageBox.critical(self, '定时发送数据异常', '定时发送数据周期仅可设置在30秒内!')except:QMessageBox.critical(self, '定时发送数据异常', '请设置正确的数值类型!')

3.5、发送数据程序

可以发送ASCII字符和十六进制类型数据,并且可以在数据前显示发送的时间,在数据后进行换行,发送一个字节,TX标志会自动累加,实现代码如下所示:

    # 发送数据def data_send(self):if self.ser.isOpen():input_s = self.Text2.toPlainText()# 判断是否为非空字符串if input_s != "":# 时间显示if self.Checkbox5.isChecked():self.Text1.insertPlainText((time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + " ")# HEX发送if self.Checkbox1.isChecked():  input_s = input_s.strip()send_list = []while input_s != '':try:num = int(input_s[0:2], 16)except ValueError:QMessageBox.critical(self, '串口异常', '请输入规范十六进制数据,以空格分开!')return Noneinput_s = input_s[2:].strip()send_list.append(num)input_s = bytes(send_list)# ASCII发送else:  input_s = (input_s).encode('utf-8')# HEX接收显示if self.Checkbox2.isChecked():  out_s = ''for i in range(0, len(input_s)):out_s = out_s + '{:02X}'.format(input_s[i]) + ' 'self.Text1.insertPlainText(out_s)# ASCII接收显示else:  self.Text1.insertPlainText(input_s.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)# 统计发送字符数量num = self.ser.write(input_s)self.data_num_sended += numself.Lineedit2.setText(str(self.data_num_sended))else:pass

3.6、接收数据程序

可以接收ASCII字符和十六进制类型数据,并且可以在数据前显示发送的时间,在数据后进行换行,接收一个字节,RX标志会自动累加,实现代码如下所示:

    # 接收数据def data_receive(self):try:num = self.ser.inWaiting()if num > 0:time.sleep(0.1)num = self.ser.inWaiting()  #延时,再读一次数据,确保数据完整性except:QMessageBox.critical(self, '串口异常', '串口接收数据异常,请重新连接设备!')self.port_close()return Noneif num > 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 += numself.Lineedit3.setText(str(self.data_num_received))else:pass

3.7、保存日志程序

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

    # 保存日志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文本中的数据信息到发送框中,实现代码如下所示:

    # 加载日志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、打开博客、公众号程序

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

    # 打开博客链接和公众号二维码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、清除发送和接收数据显示程序

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

    # 清除发送数据显示def send_data_clear(self):self.Text2.setText("")self.data_num_sended = 0self.Lineedit2.setText(str(self.data_num_sended))# 清除接收数据显示def receive_data_clear(self):self.Text1.setText("")self.data_num_received = 0self.Lineedit3.setText(str(self.data_num_received))

3.11、关闭串口程序

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

    # 关闭串口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 = 0self.Lineedit2.setText(str(self.data_num_sended))self.data_num_received = 0self.Lineedit3.setText(str(self.data_num_received))self.formGroupBox1.setTitle("串口状态(关闭)")

资源下载:PythonQt串口调试助手-嵌入式文档类资源-CSDN下载

Python Qt GUI设计:做一款串口调试助手(实战篇—1)相关推荐

  1. Python Qt GUI设计:QSpinBox计数器类(基础篇—15)

    QSpinBox是一个计数器控件,允许用户选择一个整数值,通过单击向上/向下按钮或按键盘上的上/下箭头来增加/减少当前显示的值,当然用户也可以输入值. 在默认情况下,QSpinBox的取值范围是0-9 ...

  2. Python Qt GUI设计:QComboBox下拉列表框类(基础篇—14)

    QComboBox是一个集按钮和下拉选项于一体的控件,也被称为下拉列表框. QComboBox类中的常用方法如下表所示: QComboBox类中的常用信号如下表所示: 来看看QComboBox按钮类的 ...

  3. Python Qt GUI设计:QLabel标签类(基础篇—11)

    QLabel对象作为一个占位符可以显示不可编辑的文本或图片,也可以放置一个GIF动画,还可以被用作提示标记为其他控件,纯文本.链接或富文本可以显示在标签上. QLabel类中的常用方法如下表所示: Q ...

  4. Python Qt GUI设计:窗口布局管理方法【强化】(基础篇—6)

    目录 1. 水平布局类(QHBoxLayout) 2.垂直布局类(QVBoxLayout) 3.网格布局类(QGridLayout) 3.1.单一的网络布局 3.2.跨越行.列的网络布局 4.表单布局 ...

  5. Python Qt GUI设计:信号与槽的使用方法(基础篇—7)

    目录 1.信号与槽的概念 2.信号与槽的基础函数 2.1.创建信号函数 2.2.连接信号函数 2.3.断开信号函数 2.4.发射信号函数 3.信号和槽的使用方法 3.1.内置信号与槽的使用 3.2.自 ...

  6. Python Qt GUI设计:窗口布局管理方法【基础】(基础篇—5)

    目录 1.布局管理器进行布局 2.容器控件进行布局 3.geometry属性:控件绝对布局 4.sizePolicy属性:微调优化控件布局 Qt Designer提供4种窗口布局方式,分别如下: Ve ...

  7. Python Qt GUI设计:将UI文件转换为Python文件的三种妙招(基础篇—2)

    目录 1.创建项目 2.将.ui文件生成.py文件 2.1.Eric 6编译 2.2.Python命令行编译 2.3.脚本编译 3.界面.逻辑分离思想 在开始本文之前提醒各位朋友,Python记得安装 ...

  8. Python Qt GUI设计:QPushButton、QRadioButton和QCheckBox按钮类(基础篇—12)

    目录 1.QPushButton按钮类 2.QRadioButton按钮类 3.QCheckBox按钮类 在GUI设计中,按钮都是最重要的和常用的触发动作请求的方式,用来与用户进行交互操作.在PyQt ...

  9. Python Qt GUI设计:多线程中信号与槽的使用(基础篇—9)

    有时候在项目开发时,经常会遇到一些耗时操作导致界面迟缓卡顿,为了解决这个问题,可以创建多线程,使用主线程更新界面使用子线程实时处理数据,最后将结果显示到界面上. PyQt多线程将使用QThread函数 ...

  10. Python Qt GUI设计:UI界面可视化组件、属性概述(基础篇—4)

    目录 1.界面组件 1.1.布局组件(Layouts) 1.2.分隔组件(Spacers) 1.3.按钮组件(Buttons) 1.4.表项视图(Item Views) 1.5.表项组件(Item W ...

最新文章

  1. 3.Chrome数据同步服务分析--server一片
  2. apidoc学习(接口文档定义取代word)
  3. 【DIY】一个名叫“故事鸡”的儿童玩具是如何用树莓派3B+练成的
  4. 在Delphi程序中应用IE浏览器控件
  5. Vue 实现前后端分离项目
  6. 【软件工程】实体类的持久性
  7. KindleConverter:Word批量转换为6寸PDF
  8. Vysor Pro 手工破解-简单至极的方法
  9. Axure元件库web组件库典藏版 (含五大类159小类组件 )
  10. Javakeytool生成RSA密钥
  11. 计算机画图如何把二寸照片修改为一寸,【2人回答】用画图工具怎么制作一寸、二寸照片?-3D溜溜网...
  12. MATLAB中求某个函数的积分并绘图
  13. 图像情感识别研究方向
  14. 2022年数维杯国际数模赛浅评
  15. max31865模块 PT100测温 PT1000测温 接线说明要点说明 使用说明 程序 单片机
  16. 电子产品电池使用年限计算
  17. Scrapy 2.6 Items 数据项定义、加载、传输使用指南
  18. 快时钟到慢时钟的同步问题
  19. Android 8.1 第三方apk通过数据库调用系统定时开关机功能
  20. 如何开发出成功的iOS应用(流程图)

热门文章

  1. 网络摄像机目前的主流解决方案
  2. SEO网络营销培训机构都是如何给新手SEO培训的,新手SEO看完就知道套路,以后就不会上当受骗
  3. 公有云与私有云的概念解读与优势分析
  4. nginx下的一级域名跳转到二级域名的配置
  5. Elasticsearch 的 Task 停止方法
  6. 蓝桥杯 2015 javaB组 校赛
  7. windows下网络测试工具
  8. 应聘总经理的答卷,供大家打分!(一)
  9. 有些梦想任时光侵袭也无法忘记,社科院杜兰金融管理硕士项目助你圆梦
  10. OUC_SE_Group04_Blog1