python3+tkinter+pyserial编写一个串口控制工具

2024-02-25 04:50

本文主要是介绍python3+tkinter+pyserial编写一个串口控制工具,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

python3+tkinter+pyserial编写一个串口控制工具

首先展示一下自己做的串口工具界面的全貌

在这里插入图片描述
可以看到其中包括文本框、选项框、按键、输入框还有列表,整个界面是用tkinter 实现的。

tkinter是一个方便使用python语言做界面的库,内涵多种控件,使用灵活方便

在windows系统下,tkinter 是python的自带库,就和re、os一样,直接import就能用;
但是在linux系统下,tkinter需要自行安装,指令如下:

sudo apt-get update
sudo apt-get install python3-tk

如果不行的话,需要自己去github或者 pypi.org网站找安装包,然后在终端切换到包所在的目录,输入

python setup.py install 

一般上面两种办法都能安装成功的, import tkinter试一下,不报错就说明安装成功了。
下面代码主要是tkinter对各控件的布局、参数设置的内容,可以直接运行。具体的执行内容pass掉了。

简单概括这个脚本所包含的tkinter的使用:

1.创建Tk父窗口,作为对象调用set_init_window进行窗口控件初始化
2.涉及到按钮Button、框架Frame、标签Label、输入框Entry
还有普通文本框Text、滚动文本框scrolltext、滚动条scrollbar
以及可以用作列表的Treeview控件、下拉选项框Combobox
3.控件的place、grid布局的使用和区别

4.自动获取电脑上可用的串口,作为串口下拉选项框的值

import tkinter
from tkinter import ttk,filedialog,messagebox,scrolledtext
from tkinter import *
import openpyxl
import threading
import time
import serial
import serial.tools.list_ports
import re
from code_dic import MY_CODE
class MY_GUI():#构造函数def __init__(self,name):self.init_window_name=name#窗口控件设置初始化def set_init_window(self):                        #控件设置的内容主要是这个函数,使用非常简单,主要是调用并设置参数self.init_window_name.title('串口控制')self.init_window_name.geometry('1168x631+20+10')self.init_window_name['bg']='pink'self.init_window_name.attributes('-alpha',1)#每个控件都需要用pack、place、grid布局去安置,就是设计了一个控件,要放在什么位置的意思。#按钮self.file_choose_button=Button(self.init_window_name,text='选择文件',bg='lightblue',width=10,command=self.thread_file)self.file_choose_button.place(x=40,y=170)   #place布局,x、y指的是距离父窗口左上端点的位置,像素位置self.conduct_button=Button(self.init_window_name,text='执行',bg='lightblue',width=10,command=self.com_output)self.conduct_button.place(x=40,y=455)self.log_save_button=Button(self.init_window_name,text='保存日志',bg='lightblue',width=10,command=self.thread_save)self.log_save_button.place(x=335,y=455)self.clear_button=Button(self.init_window_name,text='清空',bg='lightblue',width=10,command=self.thread_clear)self.clear_button.place(x=460,y=455)#按钮的command参数必须要指向一个函数进行调用,我这里用多线程实现,可以使各按钮的功能无干涉#串口选择框架self.com_choose_frame=Frame(self.init_window_name)self.com_choose_frame.place(x=20,y=12)#框架容纳多个控件,使界面布局更有层次感#串口选择框架内部标签,标签的值一般不做改变self.com_label=Label(self.com_choose_frame,text='COMx: ')self.com_label.grid(row=0,column=0,sticky=E)self.baudrate_label=Label(self.com_choose_frame,text='Baudrate: ')self.baudrate_label.grid(row=1,column=0,sticky=E,pady=10)#串口框架内部下拉选项框self.com_choose=StringVar()self.com_choose_combo=ttk.Combobox(self.com_choose_frame,width=30,textvariable=self.com_choose)self.com_choose_combo['state']='readonly'self.com_choose_combo.grid(row=0,column=1,padx=15)   #grid是表格式结构,行列都从0开始,padx表示x方向上两栏的间距self.com_choose_combo['values']=self.com_name_get()   #这里调用了一个函数,函数的返回值是一个数组#下拉选项框下拉的时候出现很多选项,选中之后只显示选中的选项#波特率选项框self.baudrate_value=StringVar(value='9600')     #StringVar是一个字符串变量控件self.baudrate_choose_combo=ttk.Combobox(self.com_choose_frame,width=30,textvariable=self.baudrate_value)#选项框中选中的值会赋值给字符串变量,并显示在combobox上self.baudrate_choose_combo['values']=('9600','115200')self.baudrate_choose_combo['state']='readonly'self.baudrate_choose_combo.grid(row=1,column=1,padx=15)#串口框架内部按钮self.connect_button=Button(self.com_choose_frame,text='连接',bg='lightblue',width=10,command=self.com_connect)self.connect_button.grid(row=0,column=2,padx=15)self.cancel_button=Button(self.com_choose_frame,text='取消',bg='lightblue',width=10,command=self.com_cancel)self.cancel_button.grid(row=1,column=2,padx=15)#处理结果显示滚动文本框self.result_text=scrolledtext.ScrolledText(self.init_window_name,width=77,height=42)self.result_text.place(x=600,y=50)#滚动文本框是tkinter库自带的一个小封装,将text构件scrollbar滚动条控件组合形成的,可以直接调用#其他文本框self.file_path_text=Text(self.init_window_name,width=57,height=1)self.file_path_text.place(x=150,y=175)self.com_log_text=Text(self.com_choose_frame,width=78,height=5)self.com_log_text.grid(row =2,column =0,columnspan=3,pady=5)self.com_log_text.insert(END,'此处显示串口工作信息'+'\n')           #这一句给字符串变量赋初值#标签self.result_data_label=Label(self.init_window_name,text='输出结果')self.result_data_label.place(x=600,y=15)self.num_input_label=Label(self.init_window_name,text='输入编号: ')self.num_input_label.place(x=150,y=460)#输入编号框self.input_num=StringVar()self.input_num_entry=Entry(self.init_window_name,textvariable=self.input_num,width=10)self.input_num_entry.place(x=215,y=460)#代码解析后进行显示self.code_frame=Frame(self.init_window_name,width=78,height=29,bg='white')self.code_frame.place(x=20,y=210)#解析后的代码放在表格内显示self.code_tree=ttk.Treeview(self.code_frame,show='headings',height=10,columns=('0','1','2','3','4')) #show='headings'会隐藏首列,否则首列太宽self.code_bar=ttk.Scrollbar(self.code_frame,orient=VERTICAL,command=self.code_tree.yview)self.code_tree.configure(yscrollcommand=self.code_bar.set)self.code_tree.grid(row=0,column=0,sticky=NSEW)self.code_bar.grid(row=0,column=1,sticky=NS)self.code_tree.column('0',width=30)self.code_tree.column('1',width=250)self.code_tree.column('2',width=50)self.code_tree.column('3',width=100)self.code_tree.column('4',width=100)self.code_tree.heading('0',text='序号')self.code_tree.heading('1',text='命令')self.code_tree.heading('2',text='状态')self.code_tree.heading('3',text='失败则执行次数')self.code_tree.heading('4',text='再失败则跳转至')#执行结果显示frameself.result_frame=Frame(self.init_window_name,width=78,height=15,bg='white')self.result_frame.place(x=20,y=500)self.result_tree=ttk.Treeview(self.result_frame,show='headings',height=4,columns=('0','1','2'))self.result_bar=ttk.Scrollbar(self.result_frame,orient=VERTICAL,command=self.result_tree.yview)self.result_tree.configure(yscrollcommand=self.result_bar.set)self.result_tree.grid(row=0,column=0,sticky=NSEW)self.result_bar.grid(row=0,column=1,sticky=NS)self.result_tree.column('0',width=30)self.result_tree.column('1',width=80)self.result_tree.column('2',width=420)self.result_tree.heading('0',text='编号')self.result_tree.heading('1',text='是否成功')self.result_tree.heading('2',text='从哪句指令开始失败')#自动获取当前连接的串口名def com_name_get(self):pass#连接按键的执行内容def com_connect(self):pass#取消按键的执行内容def com_cancel(self):pass#执行按键的执行内容def com_output(self):pass#新建线程,负责选择代码文件、保存代码执行结果和清空代码表格#新建选择文件线程def thread_file(self):thisthread=threading.Thread(target=self.file_choose)thisthread.start()#选择文件打开,并在界面中显示def file_choose(self):pass#新建线程保存执行结果def thread_save(self):thisthread=threading.Thread(target=self.code_log_save)thisthread.start()#保存代码执行结果日志def code_log_save(self):pass#新建线程清空所选文件以备重新选择def thread_clear(self):thisthread=threading.Thread(target=self.file_clear)thisthread.start()#删除所选文件,清空解析后的代码表格def file_clear(self):pass
#主线程
def start():init_window=Tk()            #因为写了一个类,所以要产生一个窗口对象,调用类的函数,进行窗口的构造和控件设置my_window=MY_GUI(init_window)my_window.set_init_window()init_window.mainloop()start()

pyserial 库是python用来控制串口的库,串口的开闭、读写都可以直接调用函数

将界面中的控件和串口的控制建立联系,才能在界面里用按钮控制串口,并将读写的内容在界面的滚动文本框里进行打印。
其中,重要的部分是:

1.自动获取电脑的可用串口名,并作为串口下拉选项框的选项
import re                       #正则表达式,可匹配任何字段
import serial.tools.list_ports  #获取串口名直接调用这个工具
def com_name_get(self):self.port_list=list(serial.tools.list_ports.comports())self.com_port_names=[]self.pattern=re.compile(r'[(](.*?)[)]',re.S) if len(self.port_list)>0:for i in range(len(self.port_list)):self.com_name=re.findall(self.pattern,str(self.port_list[i]))self.com_port_names.append(self.com_name)return self.com_port_names

在设备管理器里面查看串口的话,会发现COM1这个字段即串口名字是用括号括起来的,用serial.Serial开启串口只需要把COM1这个字段进行赋值,也就是只将电脑的串口名的括号内的字段捕获,并给serial赋值,开启这个串口。

pattern=re.compile(r'[(](.*?)[)]',re.S) 
com_name=re.findall(self.pattern,str(self.port_list[i]))

以上两句是正则表达式匹配括号内的值的方法。

2.点击连接按钮,在串口日志文本框显示串口是否成功打开,如果串口连接的设备有自动启动程序,则读取设备自启动程序的输出内容并显示
import time
def com_connect(self):self.result_text.insert(END,'请连接串口设备'+'\n')self.ser_name=str(self.com_choose.get())self.ser_baudrate=str(self.baudrate_value.get())try:self.ser=serial.Serial(self.ser_name)self.ser.baudrate=self.ser_baudrateself.ser.timeout=0.5self.com_log_text.insert(END,time.ctime(time.time())+'\t\t'+'串口成功打开'+'\n')self.com_log_text.see(tkinter.END)self.com_log_text.update()while True:newline=self.ser.readline()#字节类型self.result_text.insert(END,newline)self.result_text.see(tkinter.END)self.result_text.update()except:newline=time.ctime(time.time())+'\t\t'+'串口打开故障或串口被关闭'+'\n'self.com_log_text.insert(END,newline)self.com_log_text.see(tkinter.END)self.com_log_text.update()

这三句可以实现text文本框的动态打印,不会将原有内容清楚,一直向下滚动打印

text.insert(END,newline)
text.see(tkinter.END)
text.update()

这个串口工具还包括解析一个excel表格,将表格中的内容写入串口,将串口的执行结果写道界面的两个表格里显示,以及保存等,暂时还没写入文章,有了新的文章会把链接贴上。敬请期待~

这篇关于python3+tkinter+pyserial编写一个串口控制工具的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/744442

相关文章

MySQL精准控制Binlog日志数量的三种方案

《MySQL精准控制Binlog日志数量的三种方案》作为数据库管理员,你是否经常为服务器磁盘爆满而抓狂?Binlog就像数据库的“黑匣子”,默默记录着每一次数据变动,但若放任不管,几天内这些日志文件就... 目录 一招修改配置文件:永久生效的控制术1.定位my.cnf文件2.添加核心参数不重启热更新:高手应

Spring Validation中9个数据校验工具使用指南

《SpringValidation中9个数据校验工具使用指南》SpringValidation作为Spring生态系统的重要组成部分,提供了一套强大而灵活的数据校验机制,本文给大家介绍了Spring... 目录1. Bean Validation基础注解常用注解示例在控制器中应用2. 自定义约束验证器定义自

Linux系统调试之ltrace工具使用与调试过程

《Linux系统调试之ltrace工具使用与调试过程》:本文主要介绍Linux系统调试之ltrace工具使用与调试过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、ltrace 定义与作用二、ltrace 工作原理1. 劫持进程的 PLT/GOT 表2. 重定

Python+Tkinter实现Windows Hosts文件编辑管理工具

《Python+Tkinter实现WindowsHosts文件编辑管理工具》在日常开发和网络调试或科学上网场景中,Hosts文件修改是每个开发者都绕不开的必修课,本文将完整解析一个基于Python... 目录一、前言:为什么我们需要专业的Hosts管理工具二、工具核心功能全景图2.1 基础功能模块2.2 进

使用Java编写一个字符脱敏工具类

《使用Java编写一个字符脱敏工具类》这篇文章主要为大家详细介绍了如何使用Java编写一个字符脱敏工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、字符脱敏工具类2、测试工具类3、测试结果1、字符脱敏工具类import lombok.extern.slf4j.Slf4j

使用Python开发Markdown兼容公式格式转换工具

《使用Python开发Markdown兼容公式格式转换工具》在技术写作中我们经常遇到公式格式问题,例如MathML无法显示,LaTeX格式错乱等,所以本文我们将使用Python开发Markdown兼容... 目录一、工具背景二、环境配置(Windows 10/11)1. 创建conda环境2. 获取XSLT

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

Java中的工具类命名方法

《Java中的工具类命名方法》:本文主要介绍Java中的工具类究竟如何命名,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java中的工具类究竟如何命名?先来几个例子几种命名方式的比较到底如何命名 ?总结Java中的工具类究竟如何命名?先来几个例子JD

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模