一文带你走进“PyQt5”
引言:什么是GUI?
GUI是Graphical User Interface(图形用户界面)的缩写。它是一种用户界面的形式,通过使用图形元素(如图标、按钮、菜单等)和鼠标操作来实现用户与计算机程序的交互。
相对于命令行界面(CLI),GUI更直观、易于操作,使用户能够通过点击、拖拽、输入等方式与程序进行交互。GUI广泛应用于各种操作系统、应用软件和网页设计中,提供了更好的用户体验和交互性。现在我们几乎可以在各个领域看到GUI的身影,如手机通讯移动产品, 电脑操作平台, 车载系统产品, 智能家电产品, 游戏产品等等。
Linux的桌面环境
Linux有一套简便易学的图形用户接口( GUI ),用户使用鼠标就可以完成大多数工作。在Linux中,GUI由窗口系统,窗口管理器,工具包和风格等几个部分组成。
- 窗口系统用于组织显示屏上的图形输出
- 窗口管理器用于对窗口的操作如最小化等
- 工具包是用于编程界面的库
- 风格是应用程序的用户界面。
KDE 与GNOME是目前Linux / UNIX系统最流行的图形操作环境。从上个世纪九十年代中期至今,KDE和GNOME都经历了将近十年的漫漫历程,两者也都从最初的设计粗糙、功能简陋发展到相对完善的阶段,可用性逼近Windows系统。
KDE
KDE是桌面环境(Kool Desktop Environment)的缩写。一种著名的运行于 Linux、Unix 以及FreeBSD 等操作系统上面自由图形工作环境,整个系统采用的都是 TrollTech 公司所开发的Qt程序库(现在属于Digia公司)。
- Qt是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。
- Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,易于扩展,允许组件编程。它提供给应用程序开发者建立艺术级的图形用户界面所需的所有功能。
- Qt很容易扩展,并且允许真正地组件编程。基本上,Qt 同 X Window 上的 Motif,Openwin,GTK 等图形界 面库和 Windows 平台上的 MFC,OWL,VCL,ATL 是同类型的东西。
GNOME
GNOME是GNU Network Object Model Environment(GNU,网络对象模型环境)的缩写,是一种让使用者容易操作和设定电脑环境的工具。不管之前使用何种操作系统,都能轻易地使用 GNOME 功能强大的图形接口工具。GNOME使用的图形库是GTK+工具库。
- 它是一套在GIMP的基础上发展而来的高级的、可伸缩的现代化、跨平台图形工具包,它可以很方便地制作图形交互界面( GUI )。
- 同时,它遵循 LGPL 许可证,所以用户可以用它来开发开源软件、自由软件,甚至是封闭源代码的商业软件,而不用花费任何钱来购买许可证和使用权。
- GTK+ 实质上是一个面向对象的应用程序接口 ( API )。尽管完全用 C 写成的,但它是基于类和回调函数 (指向函数的指针) 的思想实现的。具有稳定、跨平台、多种语言绑定、接口丰富、与时俱进、算法丰富、移动嵌入式应用广泛等特点。
01.Python图形界面开发的几种方案
作为编程初学者,我们程序的用户交互界面一开始都是命令行终端窗口。程序的用户交互界面,英文称之为 UI (user interface)当一个应用的 UI 比较复杂的时候,命令行方式就不便用户使用了,这时我们需要图形界面。如果用 Python
语言开发 跨平台
的图形界面的程序,主要有3种选择:
-
Tkinter
基于Tk的Python库,这是Python官方采用的标准库,优点是作为Python标准库、稳定、发布程序较小,缺点是控件相对较少、图形化界面不够美观。
-
wxPython
基于wxWidgets的Python库,优点是控件比较丰富,缺点是稳定性相对差点、文档少、用户少。
-
PySide2/PySide6、PyQt5/PyQt6
基于Qt 的Python库
- 优点是控件比较丰富、跨平台体验好、文档完善、用户多。
- 缺点是库比较大,发布出来的程序比较大。
- 如果大家要开发小工具,界面比较简单,建议采用Tkinter
- 如果是发布功能比较多的正式产品,采用 基于Qt的 PySide2/PySide6、PyQt5/PyQt6
1.1 PySide2、PyQt5 简介
PySide2、PyQt5 都是基于著名的 Qt 开源库。Qt库里面有非常强大的图形界面开发库,但是Qt库是基于**C++**语言开发的,PySide2、PyQt5可以让我们通过Python语言使用Qt。
但是 PySide2、PyQt5 这两者有什么区别呢?
可以形象地这样说: PySide2 是Qt的 亲儿子
, PyQt5 是Qt还没有亲儿子之前的收的 义子
(Riverbank Computing这个公司开发的)。那为什么 PyQt5 这个义子 反而比 PySide2 这个亲儿子更出名呢?
原因很简单:PySide2 这亲儿子最近(2018年7月)才出生。但是亲儿子毕竟是亲儿子,Qt准备大力培养,PySide2 或许更有前途。
已经在使用 PyQt5 的朋友不要皱眉, 两个库的使用 对程序员来说,差别很小:它们的调用接口几乎一模一样。如果你的程序是PyQt5开发的,通常只要略作修改,比如把导入的名字从 PyQt5 换成 PySide2 就行了。反之亦然。
1.2 PySide2 PySide6的安装
在Python相应版本的路径下打开cmd输入如下命令或者直接在pycharm终端运行该命令
pip install pyside2
或者(安装其中一个版本即可,根据个人需求进行安装)
pip install pyside6
如果觉得下载速度慢的话可使用国内镜像源进行下载安装,大约100M左右
比如,使用豆瓣源下载安装:
pip install pyside2 -i https://pypi.douban.com/simple/
1.3 安装 PyQt5 PyQt6
如果选择PyQt5,直接执行
pip install pyqt5-tools
即可同时安装 PyQt5 和 一些重要的工具,比如 Qt designer。
02.使用Pyside2进行简单案例示范
2.1 需求明确
现在我们要开发一个程序,让用户输入一段文本包含:员工姓名、薪资、年龄,格式如下:
薛蟠 4560 25
薛蝌 4460 25
薛宝钗 35776 23
薛宝琴 14346 18
王夫人 43360 45
王熙凤 24460 25
王子腾 55660 45
王仁 15034 65
尤二姐 5324 24
贾芹 5663 25
贾兰 13443 35
贾芸 4522 25
尤三姐 5905 22
贾珍 54603 35
该程序可以把薪资在 2万 以上、以下的人员名单分别打印出来。
当然我们可以像以前一样,开发命令行程序(准确的说应该叫字符终端程序,因为UI是字符终端),让用户在字符终端输入。但是如果我们能开发更加智能化的图形界面程序,会很大程度上提升工作效率。
2.2 实现代码:
from PySide2.QtWidgets import QApplication, QMainWindow, QPushButton, QPlainTextEdit,QMessageBox
# 导入需要的组件
# 将一个窗口和其包含的控件,对应的代码全部封装到类中有利于代码的模块化
class Stats():
def __init__(self):
#QMainWindow、QPlainTextEdit、QPushButton 是3个控件类,分别对应界面的主窗口、文本框、按钮,三者都是他们都是控件基类对象QWidget的子类
self.window = QMainWindow()
self.window.resize(500, 400)
#控件对象的 move 方法决定了这个控件显示的位置。比如:
#window.move(300, 310) 就决定了主窗口的左上角坐标在相对屏幕的左上角的X横坐标300像素, Y纵坐标310像素这个位置。
#textEdit.move(10,25) 就决定了文本框的左上角坐标在相对父窗口的左上角的X横坐标10像素, Y纵坐标25像素这个位置。
self.window.move(300, 300)
#要在界面上创建一个控件 ,就需要在程序代码中创建这个控件对应类的一个实例对象。在Qt系统中,控件(widget)是层层嵌套的,除了最顶层的控件,其他的控件都有父控件
self.window.setWindowTitle('薪资统计')
self.textEdit = QPlainTextEdit(self.window)
self.textEdit.setPlaceholderText("请输入薪资表")
self.textEdit.move(10, 25)
self.textEdit.resize(300, 350)
self.button = QPushButton('统计', self.window)
self.button.move(380, 80)
self.button.clicked.connect(self.handleCalc)
def handleCalc(self):
info = self.textEdit.toPlainText()
# 薪资20000 以上 和 以下 的人员名单
salary_above_20k = ''
salary_below_20k = ''
for line in info.splitlines():
if not line.strip():
continue
parts = line.split(' ')
# 去掉列表中的空字符串内容
parts = [p for p in parts if p]
name,salary,age = parts
if int(salary) >= 20000:
salary_above_20k += name + '\n'
else:
salary_below_20k += name + '\n'
QMessageBox.about(self.window,
'统计结果',
f'''薪资20000 以上的有:\n{salary_above_20k}
\n薪资20000 以下的有:\n{salary_below_20k}'''
)
app = QApplication([])
stats = Stats()
# 放在主窗口的控件,要能全部显示在界面上, 必须加上下面这行代码
stats.window.show()
# 最后通过下面这段代码,进入QApplication的事件处理循环,接收用户的输入事件(),并且分配给相应的对象去处理。
app.exec_()
2.3 界面动作处理
接下来,我们要实现具体的统计功能:
当用户点击 统计 按钮时, 从界面控件 QPlainTextEdit 里面获取 用户输入的字符串内容,进行处理。
首先第一个问题: 用户点击了 统计 按钮,怎么通知程序? 因为只有程序被通知了这个点击,才能做出相应的处理。在 Qt 系统中, 当界面上一个控件被操作时,比如 被点击、被输入文本、被鼠标拖拽等, 就会发出 信号
,英文叫 signal
。就是表明一个事件(比如被点击、被输入文本)发生了。我们可以预先在代码中指定 处理这个 signal 的函数,这个处理 signal 的函数 叫做 slot
。
比如,我们可以像下面这样定义一个函数
def handleCalc():
print('统计按钮被点击了')
然后, 指定 如果 发生了button 按钮被点击 的事情,需要让 handleCalc
来处理,像这样
button.clicked.connect(handleCalc)
用QT的术语来解释上面这行代码,就是:把 button 被 点击(clicked) 的信号(signal), 连接(connect)到了 handleCalc 这样的一个 slot上
大白话就是:让 handleCalc 来 处理 button 被 点击的操作。
但是上面这行代码运行后,只能在字符窗口 打印出 统计按钮被点击了
, 还不能处理分析任务。
要处理分析任务,我们还得从 textEdit 对应的 文本框中 获取用户输入的文本,并且分析薪资范围,最终弹出对话框显示统计结果。
2.4 运行结果展示
连接(connect)到了 handleCalc 这样的一个 slot上
大白话就是:让 handleCalc 来 处理 button 被 点击的操作。
但是上面这行代码运行后,只能在字符窗口 打印出 统计按钮被点击了
, 还不能处理分析任务。
要处理分析任务,我们还得从 textEdit 对应的 文本框中 获取用户输入的文本,并且分析薪资范围,最终弹出对话框显示统计结果。