欢迎,Python 程序员!
Python 是系统管理、数据分析、web 服务和命令行程序的优秀语言;很可能您已经发现 Python 至少在其中一个领域很有用。然而,构建最终用户可以轻松识别为程序的 GUI 驱动的应用确实令人满意,这项技能应该在任何软件开发大师的工具箱中。在本书中,您将学习如何使用 Python 和 Qt 框架开发从简单的数据输入窗体到功能强大的多媒体工具等令人惊叹的应用。
我们将从以下主题开始介绍这些强大的技术:
- 介绍 Qt 和 PyQt
- 创建
Hello Qt
——我们的第一个窗口 - 创建 PyQt 应用模板
- 介绍 Qt 设计器
对于本章以及本书其余大部分内容,您将需要以下内容:
-
运行微软 Windows、苹果 macOS或 64 位风格的GNU/Linux的电脑。
-
Python 3,可从获取 http://www.python.org 。本书中的代码需要 Python 3.7 或更高版本。
-
PyQt 5.12,您可以使用以下命令从 Python 包索引安装:
$ pip install --user PyQt5
- Linux 用户还可能希望从其发行版的软件包存储库安装 PyQt5。
- Qt Designer 4.9,一个所见即所得 GUI 构建工具,可从获得 https://www.qt.io 。有关安装说明,请参阅以下章节。
- 来自的示例代码https://github.com/PacktPublishing/Mastering-GUI-Programming-with-Python/tree/master/Chapter01 。
查看以下视频以查看代码的运行:http://bit.ly/2M5OUeg
在 Windows 或 macOS 上,Qt Designer 是 Qt 公司的 Qt Creator IDE 的一部分。这是一个免费的 IDE,您可以使用它进行编码,不过,在编写时,它主要针对 C++,而对 Python 的支持是基本的。无论您是否在 Qt Creator 中进行编码,都可以使用 Qt Designer 组件。
您可以从下载 Qt Creator 的安装程序 https://download.qt.io/official_releases/qtcreator/4.9/4.9.0/ 。
虽然 Qt 公司为 Linux 提供了类似的独立 Qt 安装程序,但大多数 Linux 用户更喜欢使用其发行版存储库中的软件包。一些发行版将 Qt Designer 作为独立应用提供,而其他发行版则将其包含在 Qt Creator 包中。
此表显示了将在几个主要发行版中安装 Qt Designer 的软件包:
分配 | 包名 |
---|---|
Ubuntu、Debian、Mint | qttools5-dev-tools |
软呢帽、CentOS、红帽、苏西 | qt-creator |
Arch、Manjaro、Antergos | qt5-tools |
Qt 是一个跨平台的应用框架,它是为 C++使用的。可在商业和开源许可证(通用公共许可证(GPL)v3 和较低通用公共许可证(LGPL)v3)中获得,广泛用于 KDE Plasma 和 Oracle VirtualBox 等开源项目,商业软件,如 Adobe Photoshop Elements 和 Autodesk Maya,甚至包括 LG 和松下等公司产品中的嵌入式软件。Qt 目前由 Qt 公司拥有和维护(https://www.qt.io 。
在本书中,我们将使用 Qt5.12 的开源版本。如果您使用的是 Windows、macOS 或主要的 Linux 发行版,则不需要显式安装 Qt;安装 PyQt5 时将自动安装它。
Qt 的官方发音为可爱,尽管很多人说,Qt。
PyQt 是一个 Python 库,它允许在 Python 代码中使用 Qt 框架。它是由 Riverbank Computing 根据 GPL 许可证开发的,尽管商业许可证可以为那些想要开发专有应用的人购买。(请注意,这是一个独立于 Qt 许可证的许可证。)它目前在 Windows、Linux、UNIX、Android、macOS 和 iOS 上受支持。
PyQt 的绑定是由一个名为SIP的工具自动生成的,因此,在很大程度上,使用 PyQt 就像使用 Qt 本身一样,只是在 Python 中。换句话说,除了语言语法之外,类、方法和其他对象的用法都是相同的。
Qt 公司最近根据 LGPL 的条款发布了自己的 Python Qt5 库Qt for Python(也称为PySide2。QtforPython 在功能上等同于 PyQt5,代码可以在它们之间移植,只需很少的更改。这本书将介绍 PyQt5,但如果您需要 LGPL 库,您所学到的内容可以轻松地应用于 QtforPython。
Qt 不仅仅是一个 GUI 库;这是一个应用框架。它包含数十个模块和数千个类。它有类来包装简单的数据类型,如日期、时间、URL 或颜色值。它有 GUI 组件,如按钮、文本条目或对话框。它具有摄像头或移动传感器等硬件接口。它有一个网络库、一个线程库和一个数据库库。如果有什么不同的话,Qt 确实是第二个标准库!
Qt 是用 C++编写的,并围绕 C++程序员的需要而设计;它与 Python 配合得很好,但是 Python 程序员一开始可能会发现它的一些概念有点陌生。
例如,Qt 对象通常希望处理包装在 Qt 类中的数据。期望颜色值的方法不会接受 RGB 值的字符串或元组;它想要一个QColor
对象。返回大小的方法不会返回(width, height)
元组;它将返回一个QSize
对象。PyQt 通过在 Qt 对象和 Python 标准库类型之间自动转换一些常见的数据类型(例如,字符串、列表、日期和时间),在某种程度上缓解了这种情况;然而,在 Python 标准库中有数百个 Qt 类没有模拟类。
Qt 严重依赖名为枚举或标志的命名常量来表示选项设置或配置值等内容。例如,如果要在最小化、浮动或最大化之间切换窗口的状态,则需要向窗口传递一个在QtCore.Qt.WindowState
枚举中找到的常量。
设置或检索 Qt 对象上的值需要使用访问器方法,有时称为 setter 和 getter 方法,而不是直接访问属性。
对于 Python 程序员来说,Qt 似乎对定义类和常量有着近乎疯狂的痴迷,您将花费大量时间搜索文档,以找到配置对象所需的项。不要绝望!你很快就会习惯 Qt 的工作方式。
Qt 是一个如此庞大而复杂的图书馆,任何一本印刷书籍都不可能详细记录其中的重要部分。因此,学习如何访问和理解在线提供的文档非常重要。对于 Python 程序员来说,这是一个小挑战。
Qt 本身拥有详细而优秀的文档,记录了所有 Qt 模块和类,包括示例代码和有关使用 Qt 编码的高级教程。但是,这些文档都是针对 C++开发的;所有的示例代码都是 C++的,并且对于 Python 的方法或方法不同,没有任何指示。
PyQt 的文档要少得多。它只涵盖了 Python 特有的差异,缺乏全面的类参考、示例代码和教程,使 Qt 的文档非常出色。对于任何使用 PyQt 的人来说,这是一本必不可少的读物,但它绝不是完整的。
随着 Python 的 Qt 的发布,在 Qualt0 中,将 Qt 的 C++文档移植到 Python 的努力正在进行中。https://doc-snapshots.qt.io/qtforpython/ 。完成后,这也将是 PyQt 程序员的宝贵资源。然而,在撰写本文时,这项工作还远远没有完成;在任何情况下,PyQt 和 qtforpython 之间都存在一些细微的差异,这可能会使本文档既有帮助又令人困惑。
如果你对 C++语法有初步的了解,那么将 QT 文档在心理上翻译成 Python 并不困难,尽管在很多情况下它可能会让人困惑。这本书的目的之一是要缩小那些不精通 C++的人的差距。
在本书的前六章中,我们将主要使用三个 Qt 模块:
QtCore
,其中包含低级数据包装类、实用程序函数和非 GUI 核心功能QtGui
,其中包含特定于 GUI 的数据包装类和实用程序QtWidgets
,它定义 GUI 小部件、布局和其他高级 GUI 组件
这三个模块将用于我们编写的几乎任何 PyQt 程序中。在本书的后面部分,我们将探讨图形、网络、web 渲染、多媒体和其他高级功能的其他模块。
现在您已经了解了 Qt5 和 PyQt5,是时候深入研究并进行一些编码了。确保所有内容都已安装,打开您最喜欢的 Python 编辑器或 IDE,开始吧!
在编辑器中创建一个hello_world.py
文件,并输入以下内容:
from PyQt5 import QtWidgets
我们首先导入QtWidgets
模块。该模块包含 Qt 中的大部分小部件类,以及用于 GUI 创建的一些其他重要组件。对于这样一个简单的应用,我们不需要QtGui
或QtCore
。
接下来,我们需要创建一个QApplication
对象,如下所示:
app = QtWidgets.QApplication([])
QApplication
对象表示我们正在运行的应用的状态,必须先创建一个,然后才能创建任何其他 Qt 小部件。QApplication
应该被传递给脚本的命令行参数列表,但这里我们只传递一个空列表。
现在,让我们创建第一个小部件:
window = QtWidgets.QWidget(windowTitle='Hello Qt')
在 GUI 工具包术语中,小部件指 GUI 的可见组件,如按钮、标签、文本条目或空白面板。Qt 中最通用的小部件是QWidget
对象,它只是一个空白窗口或面板。当我们创建这个小部件时,我们正在将其windowTitle
设置为'Hello Qt'
。windowTitle
是我们所知的物业。所有 Qt 对象和小部件都有属性,用于配置小部件的不同方面。在本例中,windowTitle
是程序窗口的名称,出现在窗口装饰、任务栏或 dock 上,或您的操作系统和桌面环境选择使用它的任何地方。
与大多数 Python 库不同,Qt 属性和方法是使用camelCase而不是snake_case命名的。
可用于配置 Qt 对象的属性可以通过将它们作为构造函数参数传递或使用适当的 setter 方法来设置。通常,这只是set
加上属性的名称,所以我们可以这样写:
window = QtWidgets.QWidget()
window.setWindowTitle('Hello Qt')
还可以使用 getter 方法检索属性,该方法只是属性名称:
print(window.windowTitle())
创建小部件后,我们可以通过调用show()
使其显示,如下所示:
window.show()
调用show()
会自动使window
成为自己的顶级窗口。在第 2 章使用 Qt 小部件构建窗体中,您将看到如何将小部件放置在其他小部件中,但是,对于本程序,我们只需要一个顶级小部件。
最后一行是对app.exec()
的调用,如下所示:
app.exec()
app.exec()
开始QApplication
对象**事件循环。**事件循环将永远运行,直到应用退出,处理用户与 GUI 的交互。请注意,app
对象从不指window
,也不指window
对象。这些对象在后台自动连接;在创建任何QWidget
对象之前,只需确保QApplication
对象存在。
保存hello_world.py
文件并从编辑器或命令行运行脚本,如下所示:
python hello_world.py
运行此操作时,您应该会看到一个标题文本为Hello Qt
的空白窗口:
这不是一个非常激动人心的应用,但它确实向我们展示了任何 PyQt 应用的基本工作流程:
- 创建一个
QApplication
对象 - 创建我们的主应用窗口
- 显示我们的主应用窗口
- 调用
QApplication.exec()
启动事件循环
如果您正在 PythonRead Eval Print Loop(REPL)中试验 PyQt,请通过传入一个带有单个空字符串的列表来创建QApplication
对象,如下图所示:QtWidgets.QApplication([''])
;否则,Qt 将崩溃。此外,由于一些特殊的 PyQt 魔法,您不需要在 REPL 中调用QApplication.exec()
。
hello_world.py
演示了在屏幕上显示 Qt 窗口所需的最少代码,但对于更复杂的应用来说,它有点过于简单。在本书中,我们将创建许多 PyQt 应用,因此,为了使事情更简单,我们将编写一个基本的应用模板。以后的章节将参考此模板,因此请确保完全按照指定创建它。
打开名为qt_template.py
的新文件,并添加以下导入:
import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtGui as qtg
from PyQt5 import QtCore as qtc
我们将从导入sys
开始,这样我们就可以传递QApplication
一个实际的脚本参数列表;然后我们将导入三个主要的 Qt 模块。为了节省一些输入,同时避免星型导入,我们将它们别名为缩写名称。在本书中,我们也将始终如一地使用这些别名。
Star 导入(也称为通配符导入),例如from PyQt5.QtWidgets import *
,非常方便,并且经常出现在教程中,但在实践中,最好避免使用它们。使用 PyQt 模块执行此操作将使用数百个类、函数和常量填充您的命名空间,其中任何一个都可能意外地用变量名覆盖。避免星型导入还将帮助您了解哪些模块包含哪些常用类。
接下来,我们将创建一个MainWindow
类,如下所示:
class MainWindow(qtw.QWidget):
def __init__(self):
"""MainWindow constructor"""
super().__init__()
# Main UI code goes here
# End main UI code
self.show()
为了创建我们的MainWindow
类,我们将QWidget
子类化,然后重写构造函数方法。当我们在以后的章节中使用此模板时,除非另有指示,否则请开始在注释行之间添加代码。
对 PyQt 类进行子类化是构建 GUI 的好方法。它允许我们定制和扩展 Qt 强大的小部件类,而无需重新发明轮子。在许多情况下,子类化是利用某些类或完成某些自定义的唯一方法。
我们的构造函数以调用self.show()
结束,因此我们的MainWindow
将负责显示自己。
始终记得在子类的构造函数中调用super().__init__()
,尤其是使用 Qt 类。如果不这样做,则意味着父类没有正确设置,这无疑会导致非常令人沮丧的 bug。
我们将完成模板的主代码执行:
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
mw = MainWindow()
sys.exit(app.exec())
在这段代码中,我们将创建QApplication
对象,创建MainWindow
对象,然后调用QApplication.exec()
。虽然不是严格必要的,但在全局范围内(在任何函数或类之外)创建QApplication
对象是最佳实践。这可以确保在应用退出时,所有 Qt 对象都被正确关闭和清理。
注意,我们正在将sys.argv
传递到QApplication()
;Qt 有几个默认的命令行参数,可用于调试或更改样式和主题。如果您传入sys.argv
,则QApplication
构造函数将处理这些内容。
另外,请注意,我们在对sys.exit
的调用中调用app.exec()
;这是一个小的触碰,导致app.exec()
的退出代码被传递到sys.exit()
,因此,如果底层 Qt 实例由于某种原因崩溃,我们会将适当的退出代码传递给操作系统。
最后,请注意,我们已将此块包装在该检查中:
if __name__ == '__main__':
如果您以前从未见过这一点,那么这是一个常见的 Python 习惯用法,它的意思是:仅当直接调用此脚本时才运行此代码。通过将我们的主执行放在这个块中,我们可以将这个文件导入到另一个 Python 脚本中,并且能够重用我们的MainWindow
类,而无需运行这个块中的任何代码。
如果运行模板代码,应该会看到一个空白的应用窗口。在接下来的章节中,我们将用各种小部件和功能填充该窗口。
在结束对 Qt 的介绍之前,让我们先看看 Qt 公司提供的一个免费工具,它可以帮助我们创建 PyQt 应用 Qt Designer。
Qt Designer 是 Qt 的图形化所见即所得 GUI设计器。使用 Qt Designer,您可以将 GUI 组件拖放到应用中并对其进行配置,而无需编写任何代码。虽然它当然是一个可选工具,但您可能会发现它对原型设计很有用,或者更适合手工编写大型复杂 GUI。虽然本书中的大部分代码都是手工编码的,但我们将在第 2 章、使用 Qt 小部件构建窗体和第 3 章、使用信号和插槽处理事件中介绍 Qt Designer 和 PyQt 的使用。
让我们花一点时间来熟悉如何启动和使用 QT 设计器:
- 启动 Qt 创建者
- 选择文件|新建文件或项目
- 在文件和类下,选择 Qt
- 选择 Qt 设计器窗体
- 在“选择模板窗体”下,选择小部件,然后单击“下一步”
- 为窗体命名,然后单击“下一步”
- 单击“完成”
您应该看到如下内容:
如果您将 Qt Designer 作为独立应用安装在 Linux 上,请使用designer
命令启动它或从程序菜单中选择它。您不应该需要前面的步骤。
花几分钟时间测试 Qt Designer:
- 将一些小部件从左窗格拖到基本小部件上
- 如果愿意,可以调整小部件的大小,或者在右下窗格中选择一个小部件并检查其属性
- 当您进行了多次更改后,选择工具|窗体编辑器|预览,或点击Alt+Shift+R预览您的 GUI
在第 2 章使用 Qt 小部件构建窗体中,我们将详细介绍如何使用 Qt Designer 构建 GUI 界面;现在,您可以在上的手册中找到有关 Qt Designer 的更多信息 https://doc.qt.io/qt-5/qtdesigner-manual.html 。
在本章中,您了解了 Qt 应用框架和用于 Qt 的 PyQt Python 绑定。我们编写了一个Hello World
应用,并创建了一个用于构建更大 Qt 应用的模板。最后,我们安装了 Qt 设计器,它是 GUI 编辑器,并对它进行了第一次研究。
在第 2 章使用 Qt 小部件构建窗体中,我们将熟悉一些基本的 Qt 小部件,并学习如何在用户界面中调整和排列它们。然后,您将通过在 code 和 Qt Designer 中设计日历应用来应用这些知识。
尝试以下问题来测试您在本章中的知识:
-
Qt 是用 C++编写的,它与 Python 有很大的不同。这两种语言的主要区别是什么?在 Python 中使用 Qt 时,这些差异是如何产生的?
-
GUI 由小部件组成。在您的计算机上打开一些 GUI 应用,并尝试识别尽可能多的小部件。
-
以下程序崩溃。找出原因,并进行修复,使其显示一个窗口:
from PyQt5.QtWidgets import *
app = QWidget()
app.show()
QApplication().exec()
QWidget
类有一个名为statusTip
的属性。以下哪些最可能是此属性的访问器方法的名称?getStatusTip()
和setStatusTip()
statusTip()
和setStatusTip()
get_statusTip()
和change_statusTip()
QDate
是用于包装日历日期的类。您希望在三个主要的 Qt 模块中的哪一个找到它?QFont
是定义屏幕字体的类。您希望在三个主要的 Qt 模块中的哪一个找到它?- 你能用 Qt 设计器重新创建
hello_world.py
吗?确保设置了windowTitle
。
有关 Qt、PyQt 和 Qt 设计器的更多信息,请参阅以下资源:
- 处的PyQt 手册http://pyqt.sourceforge.net/Docs/PyQt5/ 是理解 PyQt 不同方面的便捷资源
- 处的Qt 模块列表https://doc.qt.io/qt-5/qtmodules.html 提供了 Qt 中可用模块的详细说明
- 处的QA 申请文件 https://doc.qt.io/qt-5/qapplication.html#QApplication 列出了
QApplication
对象解析的所有命令行开关 - 的QWidget文档 https://doc.qt.io/qt-5/qwidget.html 显示了
QWidget
对象中可用的属性和方法 - 处的Qt 设计师手册https://doc.qt.io/qt-5/qtdesigner-manual.html 将帮助您探索 Qt Designer 的全部功能
- 如果您想了解更多关于 C++的内容,请从 Potot{OutT0}中查看这些产品。https://www.packtpub.com/tech/C-plus-plus