Python+PyQt5 PyQt 入门从无到串口助手的实现

小七学习网,助您升职加薪,遇问题可联系:客服微信【1601371900】 备注:来自网站

QT 原生态是用 C++ 进行编程,对于没学过 QT 或者 C++ 的人来说,不是很好的选择,Python 的语法简单,学习简单,配合配套的 PyQt5 组件,可以实现快速的界面显示搭建。 带领大家进…

QT 原生态是用 C++ 进行编程,对于没学过 QT 或者 C++ 的人来说,不是很好的选择,Python 的语法简单,学习简单,配合配套的 PyQt5 组件,可以实现快速的界面显示搭建。

带领大家进入 Python 下的界面搭建及简单串口助手的实现。主要内容包含以下内容:

  1. 环境搭建
  2. 涉及的 Python 知识讲解
  3. QT 界面的搭建及涉及的控件说明
  4. QT 信号和槽的应用
  5. Pyserial 串口模块的使用
  6. 串口助手的实现


环境搭建

Python 的搭建

本人使用的是 Python 3.8 版本,各位有使用其他的也可以,这个都是无所谓的,看个人喜欢了。

本人是 Windows 电脑,所以选择的 Windows 的安装包,下载方法有 3 种。

第一种:直接下载最新版本

下载链接:https://www.python.org/downloads/

在这里插入图片描述

第二种:先选版本后选系统

下载链接:https://www.python.org/downloads/

在这里插入图片描述

找到自己需要的版本,并下载,进去的界面选择自己的系统。

第三种:先选系统再下载

下载链接:https://www.python.org/downloads/

进入链接后,鼠标移到 Downloads 的时候,会出现弹窗,选择自己的系统,我这边以 Windows 为例。

在这里插入图片描述

点开之后,选择自己的系统和对应需要的版本进行下载:

在这里插入图片描述

Python 的安装

运行安装包之后,出现以下界面:

在这里插入图片描述

此处注意,一定要选择第一步,添加环境变量,否则后面再 CMD 中使用命令会使用不了。点完安装之后自动安装,安装完成。打开 cmd,输入以下代码:

python -V

如果没反应,尝试输入:

python3 -V

命令窗口显示如下图片信息,则说明成功:

在这里插入图片描述

PyCharm 的安装

Jetbrains-toolbox

这边推荐使用 Jetbrains 的 ToolBox 进行安装,这个工具集合了所有的 Jetbrains 的软件。

下载地址:https://www.jetbrains.com/toolbox-app/

在这里插入图片描述

这边会自动检测你的系统,当然你也可以选择你的系统进行下载安装,此软件安装简单,就不过多讲解了。

安装 PyCharm

点击电脑右下角的 Toolbox,找到你要安装的软件,选择安装,我这边选择的是 PyCharm 的专业版,至于激活工具我在某宝买的 Jetbrains 全家桶激活码,大家可以去搜一下,当然也有免费的,可以度娘搜一下。

在这里插入图片描述

点击 Install 就下载了对应的软件了。安装好之后,就可以点击软件直接打开软件,方便的很。

PyQt5 的安装

这部分就简单了,打开 cmd 命令窗口,输入以下两条命令,就能自动安装完成了,至于安装速度嘛……大家可以开个加速器。

pip install PyQt5

等待安装完成之后,再输入以下指令:

pip install PyQt5-tools

就能安装完成了,如果不行,将 pip 替换成 pip3 尝试一下。

环境配置

主要的环境配置还是 PyCharm 的配置,主要配置两点 UI 界面的显示配置和解码配置。

创建工程

打开 PyCharm,选择 New Project

在这里插入图片描述

再出来的界面中,选择自己工程需要的目录,其他暂时可以先不管。Python 选择到你安装的 Python 安装的地址,找到 exe。

在这里插入图片描述

点击 Creat 建立项目。

进去之后的界面是这样的:

在这里插入图片描述

Python 输出 Hello Word

将自带的代码删掉,输入以下代码:

print(\"Hello Word!\")

打印界面就输出了 Hello Word!

在这里插入图片描述

是不是很简单,甚至连分号都不需要,直接 print。

配置 QtDesigner

点击 File->Settings,找到 Tools,点击 External Tools:

在这里插入图片描述

我这边是已经配置好了,我和大家说下配置方法,点击:

在这里插入图片描述

增加,再弹出来的框中填入信息:

在这里插入图片描述

name:名字,可以自己随便取。

program:exe 的路径。

Python 3.8.8 的路径在:

C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python38\\Lib\\site-packages\\qt5_applications\\Qt\\bin\\designer.exe

Working directory:填

$ProjectFileDir$

点击 OK ,就添加好了 UI 设计器。

PyUIC 的配置

配置方法和 QTdesigner 一样,填写的东西有所区别:

在这里插入图片描述

name:名字,可以自己随便取,这边取 PyUIC。

program:这边是 Python3.8.8 的 exe 路径,默认是

C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python38\\python.exe

Arguments:填写以下字符串,意思就是把 .ui 文件转换成 .py 文件

-m PyQt5.uic.pyuic  $FileName$ -o $FileNameWithoutExtension$.py

Working directory:填

$ProjectFileDir$

至此,环境配置就配置好了。下面我们来测试以下。

UI 显示 Hello Word

你可以在空白处点击 Exteral Tools,然后选择 QTDesigner(刚刚自己取的名字),会出来一个 UI 界面。

在这里插入图片描述

会出现以下界面:

在这里插入图片描述

出现这个界面,以前做过 QT 的,是不是很熟悉了。

下面我们选择默认的 Main Window,点击创建,出现一个空白的界面:

在这里插入图片描述

做个简单介绍:

  1. 控件,这边包含了 QT 自带原生态的所有控件
  2. 菜单栏
  3. 界面布局区域
  4. 资源包含查看狂
  5. 选中控件的属性

我们在控件列表中找到 label 控件,拖到界面中,当然也可以在控件最上面选择搜索控件。

在这里插入图片描述

我们需要显示 Hello Word,我们点击刚刚拿出来的 label 控件,找到右边的属性框,找到 Text:

在这里插入图片描述

将里面的值改成 Hello Word!

在这里插入图片描述

这样我们就编辑好界面了,保存到刚刚的 Python 工程目录下面。命名:HelloWord.ui。

在这里插入图片描述

在我们的工程下面已经显示有这个文件了,然后我们选择这个文件,右击,选择 External tool 中的 PyUIC。

在这里插入图片描述

会自动生成对应的 .py 文件,我们 UI 界面的所有资源都在里面了。

在这里插入图片描述

打开 ui.py 文件,我们发现有报错,这边我们有 2 个办法。

1. 鼠标移到错误会提示安装包,直接安装即可。

在这里插入图片描述

2. 在 File->Setting 中,找到 Project ->Project Interpreter,点击这个加号。

在这里插入图片描述

在弹出来的界面中,搜索你要安装的包,点击安装即可。

在这里插入图片描述

安装完成后,错误消失。

在这里插入图片描述

下面我们要显示这个界面。

拷贝以下代码到 main.py,则可以直接显示。

# ! /usr/bin/env python# -*- coding: utf-8 -*-import sysimport HelloWordfrom PyQt5.QtWidgets import QApplication, QMainWindowif __name__ == \'__main__\':  app = QApplication(sys.argv)  myMainWindow = QMainWindow()  myUi = HelloWord.Ui_MainWindow()  myUi.setupUi(myMainWindow)  myMainWindow.show()  sys.exit(app.exec_())

显示效果:

在这里插入图片描述

好了,Python 输出 Hello Word 和界面显示都完成了。

Qt 信号和槽讲解

我们做一个简单的输入做加法的一个界面,涉及内容:

  • 输入框
  • 按钮事件
  • 框内容获取和修改

UI 布局

首先按照第二讲的说法,拖出一个和我一样的界面,功能实现就是 A+B=C,左边两个输入框和输出框是 Line Edit 控件,然后最右边是一个按键 Push Button 按钮。

在这里插入图片描述

在属性界面找到三个框和按钮的 objectName,分别命名 A、B、C 和 Calculate。

在这里插入图片描述

首先布局界面,然后按照上一讲的方法,进行显示,但是你发现你按计算按钮没有任何反应,这就要讲到下一个知识点,按钮点击事件。

在这里插入图片描述

按钮事件

实现 A+B 之前,我们先熟悉按钮点击事件,我们先再拖两个按钮,命名可以不管,显示文字改为显示和隐藏。如下图:

在这里插入图片描述

然后找到菜单栏,找到添加槽和信号按钮。

在这里插入图片描述

然后鼠标点显示不要放,鼠标移动到 B 输入框会出现以下界面,简单理解就是显示按钮的什么信号会触发 B 输入框的什么动作。

在这里插入图片描述

这边左下角的勾打上,然后左边表示按钮显示出发了什么信号,我们选择点击信号,右边表示需要连接到什么动作,我们选择 B 框的 show(),表示 B 框的显示。隐藏按钮同理,左边选择点击信号,右边选择 hide(),表示隐藏。

在这里插入图片描述

然后保存,转码后,运行 main,显示状态如下,效果是不是很明显。

在这里插入图片描述

那么我们现在回到刚刚的加法,计算按钮上,由于我们使用的是 A+B 算法,所以我们这个触发的动作需要自己写,因此在连接信号和槽框中,信号直接拉出来放在空白处,然后出来的槽动作那边点编辑。

在这里插入图片描述

在出来的弹窗中点击 +,添加槽函数,输入 CalculateClick()。相当于一旦我点击计算按钮,我就会调用这个函数的意思。

在这里插入图片描述

然后对应的选择好之后,点击 OK,保存 UI,并用 PyUIC 进行转码。

在这里插入图片描述

然后我们打开 UI 的 Python 文件,我们会发现这个函数,意思就是我们按钮的点击链接到了 Calculate 函数。然后我们需要在主函数中重写这个函数。因为我们本身 UI 不带这个函数。

在这里插入图片描述

这边我们需要对 UI 界面类进行重写,在主函数中添加以下代码:

class Mywindow(QtWidgets.QMainWindow, Ui_MainWindow):    def __init__(self):        super(Mywindow, self).__init__()        self.setupUi(self)    def CalculateClcik(self):        print(\"触发按钮。\")

这边涉及到几个点。

1. 类的继承

语法:

class 派生类名(基类名)

那么我们的写法就是我们申请了一个 Mywindow 类,这个类继承了 QtWidgets.QMainWindow 和 Ui_MainWindow 两个类的方法。

2. init 函数

这是一个初始化函数,默认类实例化之后,就会自动调用 init 函数。有什么需要初始化的,就在这边完成。

3. def

这是函数的什么指示。

4. self 代表类的实例,而非类

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。

程序中写的 def CalculateClcik(self),表示我们重写 CalculateClcik() 函数,我们这边先输出打印“触发按钮”,实际效果是这样的:

在这里插入图片描述

按钮触发的函数也写好了,现在我们可以做我们的加法了。 做加法,我们首先得获取出 A 和 B 里面的内容,首先我们需要将字符串转为数字就是 ‘123’ 转为数字的 123。

这边用到 int 函数,这是比较方便的函数。

int(self.A.text())

这句话什么意思呢,就是把 A 输入框里面的字符串转为整形。当然浮点型大家可以自行深入。

那么最后 CalculateClcik 函数就写成了这样:

    def CalculateClcik(self):        # print(\"触发按钮。\")        self.C.setText(str(int(self.B.text()) + int(self.A.text())))

self 表示实例本身,这边可以认为是界面自生,self.C 表示界面中的 C 控件。其中 setText 是设置框内的内容。直接 text() 则是取里面的内容。

main.py 代码:

# ! /usr/bin/env python# -*- coding: utf-8 -*-import sysfrom calculate import Ui_MainWindowfrom PyQt5 import QtWidgetsclass Mywindow(QtWidgets.QMainWindow, Ui_MainWindow):    def __init__(self):        super(Mywindow, self).__init__()        self.setupUi(self)    def CalculateClcik(self):        # print(\"触发按钮。\")        self.C.setText(str(int(self.B.text()) + int(self.A.text())))if __name__ == \'__main__\':  app = QtWidgets.QApplication(sys.argv)  window = Mywindow()  window.show()  sys.exit(app.exec_())

效果:

在这里插入图片描述

当然这边还需要做一些保护,比如 A 框输入英文,那么程序运行是会崩溃的。这边就需要用到 try 函数:

    def CalculateClcik(self):        try:            self.C.setText(str(int(self.B.text()) + int(self.A.text())))        except:            print(\'请输入正确的整数\')

这边的意思就是,如果 try 里面的代码运行不成功,就输出下面的打印。

具体效果:

在这里插入图片描述

好了,以下是简单计算器的最终代码:

# ! /usr/bin/env python# -*- coding: utf-8 -*-import sysfrom calculate import Ui_MainWindowfrom PyQt5 import QtWidgetsclass Mywindow(QtWidgets.QMainWindow, Ui_MainWindow):    def __init__(self):        super(Mywindow, self).__init__()        self.setupUi(self)    def CalculateClcik(self):        try:            self.C.setText(str(int(self.B.text()) + int(self.A.text())))        except:            print(\'请输入正确的整数\')            self.C.setText(\"\")if __name__ == \'__main__\':  app = QtWidgets.QApplication(sys.argv)  window = Mywindow()  window.show()  sys.exit(app.exec_())

串口助手的实现

UI 及相关槽函数的建立

首先创建 PyCharm 工程建立新的 UI,并拖拽 QT 控件,进行 UI 的布局,布局如下,当然个人喜好,喜欢怎么放就怎么放。

在这里插入图片描述

当然两个按钮分别对应了 2 个槽。一个打开串口槽:

在这里插入图片描述

一个发送给数据槽:

在这里插入图片描述

点击保存后,用 PyUIC 形成 .py 文件。

代码编写

模块加载

串口小助手,那么我们就需要对串口进行读写,首先我们在 Python 模块中增加串口模块,这边我们说一个新的增加模块的方法,在前面的讲解中,我们有说到增加模块的方法有 2 种,现在说第三种。

打开 PyCharm,下面选择这个选项,打开来发现,这个其实是虚拟环境。这边我们首先输入:

pip list

会打印出当前加载好的模块,这边显示的 pyserial 就是我们需要的串口模块。

在这里插入图片描述

可以在这边输入:

pip install pyserial

来对串口模块进行安装。

在这里插入图片描述

我这边因为已经安装好,所以提示了当前包的版本信息。

代码实现

串口通信,首先我们得得到电脑的串口号,Python 的串口接口可以获取到电脑设备的串口列表:

COM_List = list(serial.tools.list_ports.comports())if len(COM_List) == 0:   print(\'无可用串口\')else:    for i in range(0, len(COM_List)):        print(COM_List[i])

通过这个接口,我们可以看到最终打印可以看到,我们电脑有 2 个串口,前面是串口编号,后面是串口的名称。

在这里插入图片描述

因此,我们需要将这两个放到我们的界面的串口列表中。

这边我们把这部分代码封装成一个函数。

# 获取串口列表def Get_Com_List():    return list(serial.tools.list_ports.comports())# 界面 UI 按键程序重写class Mywindow(QtWidgets.QMainWindow, Ui_MainWindow):    def __init__(self):        super(Mywindow, self).__init__()        self.setupUi(self)        COM_List = Get_Com_List()  # 获取串口列表        for i in range(0, len(COM_List)):  # 将列表导入到下拉框            self.Com_Port.addItem(COM_List[i].name)    def Open_Com_Click(self):        print(\"点击了打开串口按钮\")    def Send_Data_Click(self):        print(\"点击了发送数据按钮\")

首先我们重写 UI 界面,将两个按钮事件进行简单的定义,我们首先完成串口号的获取。

在初始化函数中,我们增加了获取串口号,并且把串口号的名称加入到 Com_Port 控件中,具体效果是这样的:

在这里插入图片描述

串口号中已经可以下拉选择哪个串口。同理我们把串口波特率也加到下面波特率的下拉框中,效果如图:

在这里插入图片描述

我这边就只添加了 2 种进行测试。代码如下:

        self.Com_Band.addItem(\"9600\")        self.Com_Band.addItem(\"115200\")

获取到了串口号了,接下来我们就要来打开串口,发送数据,这边我们需要先知道下拉框选择了哪个串口。 通过接口

        self.Com_Port.currentText()

来进行获取当前是 COM 多少。然后同理选择波特率,然后进行打开串口:

    def Open_Com_Click(self):        global custom_serial  # 全局变量,需要加 global        global Com_Open_Flag        print(\"点击了打开串口按钮\")        if self.Open_Com.text() == \"打开串口\":            print(self.Com_Port.currentText())            custom_serial = serial.Serial(self.Com_Port.currentText(), int(self.Com_Band.currentText()), timeout=0.5)            if custom_serial.isOpen():                print(\"open success\")                Com_Open_Flag = True                self.Open_Com.setText(\"关闭串口\")                self.Com_Band.setEnabled(False)  # 串口号和波特率变为不可选择                self.Com_Port.setEnabled(False)            else:                print(\"open failed\")        else:            Com_Open_Flag = False            self.Open_Com.setText(\"打开串口\")            custom_serial.close()            self.Com_Band.setEnabled(True)  # 串口号和波特率变为可选择            self.Com_Port.setEnabled(True)

这是对打开按钮程序的重写,大体意思我想大家以下就看懂了,首先就是判断当前状态,按钮点击是打开串口还是关闭串口,执行不同的操作,还有打开失败还是成功。大家应该很容易看懂。

接下来就是串口的收发数据了。

数据接收部分,有一个比较难搞的地方,就是一旦你串口打开了,那么数据就必须要一直处于接收状态,如果你按照往常的使用 while True 来使用,你会发现你的显示界面卡着不动了。这边我们需要引入新的知识点。

线程

线程简单应用,就是打开线程,然后一直读串口数据:

import _thread# 获取串口数据def Com_Data_Rsv(threadName):    while True:        while Com_Open_Flag:            data = custom_serial.read_all()            if data == b\'\':                continue            else:                print(\"receive : \", data)                window.Set_Display_Data(data)_thread.start_new_thread(Com_Data_Rsv, (\"Thread-1\",))

然后在 UI 界面的类中添加方法:

    def Set_Display_Data(self, Data):        self.Date_Display.insertPlainText(str(Data, encoding=\"utf-8\"))  # 显示数据

打开线程,一直接收串口数据,只是串口处于打开情况下,我们才处理接收数据,最后把数据打印在界面上显示。

具体效果如下:

在这里插入图片描述

发送数据

综上所述,分为以下几个步骤:

  1. 按钮事件重写
  2. 获取发送文本
  3. 通过串口发送

代码如下:

    def Send_Data_Click(self):        print(\"点击了发送数据按钮\")        Data_Need_Send = self.Send_Data_Dsiplay.toPlainText()        if custom_serial.isOpen():            custom_serial.write(Data_Need_Send.encode(\"gbk\"))        else:            print(\"请先打开串口\")

最终效果:

在这里插入图片描述

好了,当然还有很多不完善的地方,比如很多代码异常保护等等,大家可以自行增加,自行补充功能。本次讲解就到这。

Qt 部分其他功能大多都是这样了,大家有什么功能需要增加的,或者不懂的,可以留言,大家一起交流。

最终代码:

# ! /usr/bin/env python# -*- coding: utf-8 -*-import serialimport serial.tools.list_portsimport sysfrom SerialPortTools import Ui_MainWindowfrom PyQt5 import QtWidgetsimport _threadCom_Open_Flag = False  # 串口打开标志COM_Band = {\"9600\", \"115200\"}custom_serial = serial.Serial# 获取串口列表def Get_Com_List():    return list(serial.tools.list_ports.comports())# 获取串口数据def Com_Data_Rsv(threadName):    while True:        while Com_Open_Flag:            data = custom_serial.read_all()            if data == b\'\':                continue            else:                print(\"receive : \", data)                window.Set_Display_Data(data)# 界面 UI 按键程序重写class Mywindow(QtWidgets.QMainWindow, Ui_MainWindow):    def __init__(self):        super(Mywindow, self).__init__()        self.setupUi(self)        COM_List = Get_Com_List()  # 获取串口列表        for i in range(0, len(COM_List)):  # 将列表导入到下拉框            self.Com_Port.addItem(COM_List[i].name)        self.Com_Band.addItem(\"9600\")        self.Com_Band.addItem(\"115200\")    def Open_Com_Click(self):        global custom_serial  # 全局变量,需要加 global        global Com_Open_Flag        print(\"点击了打开串口按钮\")        if self.Open_Com.text() == \"打开串口\":            print(self.Com_Port.currentText())            custom_serial = serial.Serial(self.Com_Port.currentText(), int(self.Com_Band.currentText()), timeout=0.5)            if custom_serial.isOpen():                print(\"open success\")                Com_Open_Flag = True                self.Open_Com.setText(\"关闭串口\")                self.Com_Band.setEnabled(False)  # 串口号和波特率变为不可选择                self.Com_Port.setEnabled(False)            else:                print(\"open failed\")        else:            Com_Open_Flag = False            self.Open_Com.setText(\"打开串口\")            custom_serial.close()            self.Com_Band.setEnabled(True)  # 串口号和波特率变为可选择            self.Com_Port.setEnabled(True)    def Set_Display_Data(self, Data):        self.Date_Display.insertPlainText(str(Data, encoding=\"utf-8\"))    def Send_Data_Click(self):        print(\"点击了发送数据按钮\")        Data_Need_Send = self.Send_Data_Dsiplay.toPlainText()        if custom_serial.isOpen():            custom_serial.write(Data_Need_Send.encode(\"gbk\"))        else:            print(\"请先打开串口\")if __name__ == \'__main__\':  app = QtWidgets.QApplication(sys.argv)  window = Mywindow()  window.show()  _thread.start_new_thread(Com_Data_Rsv, (\"Thread-1\",))  sys.exit(app.exec_())

总结

PyQt 对于初学 UI 界面的人和想学 Python 的都是一个很好的例子,里面包含了数据转换、数据发送、依赖包的安装、类的继承和重写,包含了很多知识点,学会了这个,相当于对于 Python 的基础基本就没什么问题了。

小七学习网,助您升职加薪,遇问题可联系:客服微信【1601371900】 备注:来自网站

免责声明: 1、本站信息来自网络,版权争议与本站无关 2、本站所有主题由该帖子作者发表,该帖子作者与本站享有帖子相关版权 3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和本站的同意 4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责 5、用户所发布的一切软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。 6、您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 7、请支持正版软件、得到更好的正版服务。 8、如有侵权请立即告知本站(邮箱:1099252741@qq.com,备用微信:1099252741),本站将及时予与删除 9、本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章和视频仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。