麦子学院---《使用pyqt开发 windows gui程序及打包》学习笔记
1. python GUI框架简介,pyqt介绍,为什么使用pyqt
python开发GUI程序,了解一个框架需要了解:
(1)运行效果
(2)能够运行在哪些平台
(3)学习成本,因为每一个GUI框架都有自己的特点
(4)开发效率的比较,python的运行效率比c c++低,但是开发效率是比较快的
python GUI框架:
(1)Tkinter: python内置的GUI框架,使用TCL实现,python中内嵌了TCL解释器,使用它的时候不用安装额外的扩展包,直接import,跨平台。不足之处在于UI布局全靠代码实现,只有15种常用部件,显示效果简陋。
(2)Wxpython:用得比较广泛,跨平台,C++编写,需要安装扩展模块;文档少,遇到问题不好解决,代码布局控件,不直观。
(3)Pygtk: python对GTK+GUI库的封装,在linux平台上运行的比较好,需要安装扩展模块,在windows下的兼容性有一些问题。
(4)pyqt:QT原本是诺基亚的产品,源码用C++写的,python对QT的包装,跨平台,本地显示效果,根据系统决定,在win7下就是win7的显示效果;pyqt与qt的函数接口一致,qt开发问的那个丰富,所以pyqt开发文档也比较丰富;控件丰富,函数/方法多,拖曳布局;方便打包成二进制文件;GPL协议,商业程序需要购买商业版授权
(5)pyside:诺基亚的亲儿子,python对QT的封装,安装扩展模块,跨平台,与pyqt的API一样,LGPL协议,新软件可以是私有的,代码布局
(6)Kivy: 针对多点触控程序,智能手机平板等,也可以在没有触屏功能的系统上,全平台支持;使用python和cython(python和c语言的接口)编写;中文支持差,需要自己下载中文库并且制定路径。
为什么使用pyqt:
- 因为API与qt一致,学会了pyqt再使用qt很简单
- 文档丰富
- 学习成本低
- 开发迅速,qt designer拖曳布局,如果使用代码布局还需要构建全局并且调试
- 学习经验容易迁移到pyside来开发商业应用
- 方便打包发布软件,python本身解释语言的特点是写好的程序不编译和链接,使用文本运行解释器,边解释边执行,用户不可能装一个解释器再发源码再执行,所以打包成exe再发布
本课程内容(假设已经掌握python语法):
(1)pyqt常用控件使用(标签,按钮,radio button,文本框,旋钮,滑块,图片显示)
(2)python一些常用扩展包的使用,结合pyqt完成实用小软件(从大量excel中查找关键词,语音识别程序开发)
(3)使用python和百度云语音完成语音识别程序,并通过语音控制台灯开关(需要硬件支持)
(4)pyqt程序在windows平台下的打包,linux下可以直接运行打包
2. 使用python开发pyqt程序的环境搭建
python版本选择:python3
永远选择easy模式,不在搭建环境中浪费时间,传统开发模式在网上下载python各种安装包,再一个个安装,python原生的IDE不是很好用。
Anaconda介绍与安装
Eric6安装,需要安装一个集成环境,可以作为python的IDE,在官网上下载的安装包是一个文件目录,使用python命令运行install.py文件完成安装,安装后安装目录到anaconda下scripts文件中,其实也就相当于一个包,双击eric6.bat文件运行
- 下载地址:https://sourceforge.net/projects/eric-ide/files/latest/download
- 解压后安装,安装后可以删去下载的文件
安装pycharm,(老师使用的eclipse+pydev插件,并且还要配置解释器位置)
还需要配置环境
3. 第一个eric GUI程序的创建以及运行方法
eric开发流程:
- 新建工程
- 新建ui文件,后缀名为.ui
- 编辑ui文件
- 编译ui文件为py文件,编译为py文件才能运行,直接在eric中文件右键点击compile from,成功会提示编译成功。
- 运行py文件
新建好项目之后,会自动生成一个 init.py文件,这个文件的存在意义就是告诉python解释器,接下来都是python脚本。
点击forms,在空白区域右键新建一个窗体,默认是dialog类型,我们选择main window主窗体,然后保存为.ui文件。步骤如下图:
run script后弹窗不需要设置选项内容,直接ok,那么第一个eric GUI程序就运行成功了。
报错1: 找不到designer,新建文件过程中报错了,如图,原因为:
解决办法:
- 在cmd中执行pip install PyQt5-tools,安装designer工具,会在anaconda3\Lib\site-packages目录下,多出pyqt5-tools这个文件夹
-
在eric6中settings-preferences中-QT中指明designer.exe所在的bin目录,问题就解决了,如图:
解决好问题之后,可以顺利创建.ui文件,并且创建好文件之后自动弹出Qt designer工作界面。
报错2: py文件无法run,eric6中start和debug选项都是灰色的
原因是python解释器没有配置好,解决办法在settings-preferences中debugger-python3一项,选择默认的解释器。针对自己用python版本,检查debugger是否配置好。
4. Qt designer的使用
拖曳布局,多种空间,属性界面(修改控件属性)
常用的界面布局:
- 横向布局
- 纵向布局
- 网格布局
没有整体布局,直接拖动控件其实也是一种布局,叫做绝对位置布局,每一个控件在窗口中的位置都有一组坐标确定的,geometry属性,里面有4个参数,分别是距离左上角的高与宽,以及这个控件的高度和宽度。优点是可以随意拖动,不用考虑其余控件,缺点是两个控件实现对齐等操作时很困难。
会自动计算间距,排列整齐,前三种比较常用,并且这些布局可以嵌套使用,混合使用,比如某个格子里面再使用一个垂直布局之类的。
报错3:could not start pyuic5
每次使用qt designer布局保存之后,需要重新编译文件,如果编译时报错,could not start pyuic5,找到报错原因是,在settings-preference设置中,重复设置了qt tools和pyqt tools的工具目录,删除掉pyqt tools设置的地址就解决了。
6. 第一个控件:label控件使用
- 主要目的是显示信息,label框以及字体的颜色通过stylesheet中进行修改,可以增加颜色,字体等,要注意修改样式时必须保证语法正确,比如每条样式设置间“;”不能丢失等。否则会报错:invalid style sheet,修改样式无效。
- 可以发射信号,配合槽函数实现特定功能
- 可以修改样式表,显示图片
7. 加入一点交互,button控件的使用
button控件经常是用户发起请求,确认或者取消,发出请求之后程序要做相应的处理
初步了解pyqt的信号与槽
掌握在Qt designer编辑信号与槽的方法
实现button和label控件联动
button控件作用:
- 主要用于用户提交,确认,关闭窗口等情况,button用相应的用户处理,比如点击之类的
- 需要有时间处理函数实现特定功能
pyqt的信号与槽
总步骤:
1. 切换编辑模式到信号与槽模式
2. 拖动链接
3. 选择相应的槽函数
在Qt designer编辑信号与槽的方法:
- 默认的是在编辑UI的界面,在edit下选择edit signals/slots,切换到编辑信号和槽的界面。
- 鼠标在push button上是,按住鼠标向左拖动出现像地线一样的符号,并且弹出配置链接的窗口,左边就是push button所支持的发射信号的方法,即感知用户的哪些动作。选择一个动作可以发射一个信号,右侧即为槽可以接收发射出来的信号,右侧小窗口内为空白,当勾选继承主窗口的事件之后,可以出来一堆的事件,从而可以进行选择事件。比如,选择,close(),那么保存ui文件编译好之后执行,效果就是,点击push button按钮,整个窗口将关闭。
- 选择的槽函数可以对控件进行操作,或者mian window,也可以对跟控件无关的东西进行操作。
button与label联动
将push button拖动到链接上label,那么就可以发射信号,对label进行操作,后面会深入讲解button控件槽函数的使用和控制方法,这里使用GUI方式拖拽,不是特别方便,并且只能操作GUI上面的控件,功能比较少,有的方法还不是很灵活,后面会用代码的方式去实现,这样不会限制控件的操作,点击控件之后后台可以完成很多事件。
8. 理解信号与槽,QT的核心概念
学习内容:
1. 了解QT的信号与槽机制
2. 了解通过代码链接信号与槽的方法
3. 掌握使用eric生成槽函数的方法
4. 理解pyqt自动连接信号与槽的机制
5. 编写槽函数
QT对时间响应提供了两种机制:和大多数GUI一样相对底层的(按钮的鼠标点击或者触摸屏的点击,键盘选中敲回车点击,这三种事件底层不一样,有不同的实现)和高级的信号与槽的机制(底层响应没有太多的意义)
信号与槽
屏蔽底层细节,不管你是鼠标点击还是触屏点击或者键盘各种动作来源,只要被点击,就有一种槽函数去处理,对减少代码量很重要。
所有控件都支持信号与槽机制,预定义信号和槽。控件触发后,QT默认的机制就是发出信号,就不管了,信号需要连接到槽才能获得处理。预定义的信号和槽(即内置的一些动作和响应事件)可以连接到一起,零代码实现一定功能,但是功能有限,需要自己使用代码去扩展。
不同控件发射出的信号类型可能不同,比如按钮只有点击信号发出来不带有参数,但是输入框可能发出的信号可能会带有一段字符串。
pyqt比C++版的QT更加强大,C++版的qt的槽函数必须固定格式声明,定义以及实现,pyqt槽函数的特点是可以是任何能够调用的东西,也没有特殊格式要求。
通过代码连接信号与槽
1. 手动连接信号与槽的方法有以下几种:
这些方法是在生成的GUI主类里面的初始化函数中去实现,或者是自定义一个函数去实现这个信号与槽的连接。
self.connect(widgets, SIGNAL("signal"),func)
# widgets控件,这个控件带有一个信号参数,引号里面signal表示信号名称,比如click,拖拽之类的,func就是pyqt定义的槽函数,可以是自己去定义的一个函数来实现
self.connect(widgets, SIGNAL("signal"), instance.methodname)
# instance.methodname 这个是调用一个类其他控件的方法,这个方法与上一个不同的是,上一个直接自己定义的槽函数,第二种是从已有的类里边去调用一个方法作为槽函数
self.connect(widgets, SIGNAL("signal"), instance, SLOT("slotSignature"))
# 前面一样,是哪一个控件,去发出一个信号,然后instance去实现这个槽函数,这个instance是另外一个控件,slotSignature自定义的槽去接受前面发出的信号。
2. Eric生成槽函数
类似python的核心价值观,方便,eric可以自动生成,就不要手动编写。以一个push button
来做测试,首先需要记住这button
的编号,实现步骤如下:
步骤1:在form栏中,在ui文件上鼠标右键选择,generate dialog code,出现一个弹框,需要设置classname
,点击new新增一个会出来一个弹框,默认里面内容。
步骤2: 在弹窗下面找到刚才指定的push button
,点开前面的三角符号,出来一系列动作。on_pushButton_3_clicked()
表示在这个控件上的点击事件。勾选后点击OK。
之后我们会看到工程项目下自动生成了一个文件,名字与项目名字相同的一个py文件。这个文件就包含了对信号的处理,单独运行这个文件是无法显示窗体的,因为这个文件中,类没有实例化。需要自己补充代码,并且运行。
Eric如何连接信号与槽
没有使用IDE去连接信号和槽,实际上,Eric6自动生成的代码里面有一句调用了setupUi函数,其中最后一句就很有用。关于文件中代码的作用见代码注释。
QtCore.QMetaObject.connectSlotsByName(MainWindow)
# 调用这个函数之后,pyqt就做了一件事情,自动连接信号与槽通过控件的名字去连接
如何编写槽函数
告别拖曳式编辑信号和槽,拖曳方式实现的功能实在有限,通过代码实现,更加灵活,可以实现复杂的功能,Pyqt开发过程中,主要的代码也就是实现槽函数的地方。首先注释掉自动生成的槽函数中抛出异常的这句代码raise NotImplementedError
,然后编写要执行的内容。
下面是push button
修改文本框显示内容并且在控制台输出内容的槽函数例子:
@pyqtSlot()
# 装饰器,避免重复命名产生错误
def on_pushButton_3_clicked(self):
# 自动生成的槽函数很傻,只有函数声明,没有定义
"""
Slot documentation goes here.
这是测试按钮的槽函数
"""
# TODO: not implemented yet
# raise NotImplementedError
# 这句话就是抛出异常,就是槽函数还没有实现
print ('按钮被按下')
# 注意,我们使用的是python3,关于print函数需要使用括号
self.label.setText(u'修改文本框内容测试成功啦')
总的来说,在有好的IED工具基础上,我们可以使用界面化的方式完成pyqt开发GUI的界面快速布局,然后再自己完成槽函数部分,这样开发的效率也很快,不用自己写代码布局尽量就不写代码,还节约时间。Eric6可以自己调用qt designer,快速设计界面以及简单的低级信号和槽。最主要的写代码部分也就是链接好以后补充槽函数的内容,以及实现py文件的启动部分,弄清楚窗口间的继承关系。