Python-开发者的-QT-实用指南-全-
Python 开发者的 QT 实用指南(全)
原文:
zh.annas-archive.org/md5/d5c7eae7becafec937a2fa9cb7e21898译者:飞龙
前言
Qt 是 GUI 应用程序开发中最广泛使用和最灵活的框架之一。本书将向您介绍使用 PyQt 和 PySide 等 Python 绑定开发基于 Python 的 Qt GUI 应用程序。我们将从描述 PyQt 和 PySide GUI 元素开始,这将成为本书的参考。完成本书后,您将能够从头开始创建美观的 Python GUI 应用程序。
本书面向对象
本书面向希望开发现代、响应迅速且吸引人的 GUI 和跨平台应用程序的 Python 开发者。不需要具备 Qt 或 QML 的先验知识。
本书涵盖的内容
第一章,Python 和 Qt 简介,描述了 Qt 的基础知识,并将其与 Python 进行比较。它还讨论了使用 Python 实现各种 GUI 的领域。
第二章,QML 概述,介绍了 Qt 建模语言。
第三章,Qt Quick 库,讨论了 Qt Quick 库的实现。
第四章,PyQt 和 PySide 入门,介绍了 PyQt、PySide 以及 GUI 应用程序构建中最有用的方法,以及样式化的概念。
第五章,使用 QWidget 和主窗口,展示了如何在 GUI 应用程序中使用小部件和框架,并讨论了 PyQt5、PySide2 及其小部件和框架的功能。
第六章,使用框架、标签和文本字段,处理 PyQt5 和 PySide2 的标签、文本字段、组合框和相关元素特性。
第七章,使用组合框和列表视图,讨论了 PyQt5 和 PySide2 中的组合框、列表视图和表格,以及这些元素的功能和特性。
第八章,实现按钮,描述了在 PyQt5 和 PySide2 GUI 应用程序中实现按钮和其他控件元素。
第九章,图形基础,描述了用于处理图形、绘图和绘画、图形视图、图形场景和其他可视化组件的 PyQt 和 PySide 类。
第十章,图形表示,专注于在应用程序中使用的图形和其它可视化组件的 PyQt 和 PySide 类。
第十一章,图形效果和多媒体,专注于在应用程序中表示图形的 PyQt 和 PySide 类、图形动画以及使用应用程序中的附加图形工具。
第十二章,文件、打印机和其他对话框,处理了 PyQt 和 PySide 类用于处理文件,如打开、保存和创建。它还关注输入对话框和信息框。
第十三章,创建布局,专注于 PyQt 和 PySide 类用于定位元素,并解释了如何创建布局以使您的 GUI 应用程序响应并具有分辨率无关性。
第十四章,实现数据库,展示了如何创建数据库以及如何与 SQL/NoSQL 一起工作,并添加持久性。
第十五章,信号、槽和事件处理器,介绍了信号和槽,并解释了如何添加 PyQt 和 PySide 元素以及元素之间的功能特性和通信可能性。此外,它还描述了 PyQt 和 PySide GUI 中的事件以及如何实现事件处理器。
第十六章,线程和多进程,展示了使用 PyQt 和 PySide 创建 GUI 时的线程和多进程方法的实现。此外,它还关注构建大型应用程序的主要原则以及数据库处理。
第十七章,完成应用程序、嵌入式设备和测试,完成了应用程序,进行了测试,并描述了将应用程序部署到嵌入式平台的基础知识。
为了充分利用本书
本书致力于在 Python 编程语言及其相关工具的背景下进行 Python 的实现开发。为了充分利用这些材料,读者必须对 Python 有一定的了解。Qt 有许多子版本;请确保您安装了 Qt 5、Python 2 和 Python 3,以便代码与本书兼容。
下载示例代码文件
您可以从www.packt.com的账户下载本书的示例代码文件。如果您在其他地方购买了此书,您可以访问www.packt.com/support并注册,以便将文件直接通过电子邮件发送给您。
您可以通过以下步骤下载代码文件:
-
在www.packt.com上登录或注册。
-
选择 SUPPORT 标签。
-
点击代码下载与勘误表。
-
在搜索框中输入书名,并遵循屏幕上的说明。
下载文件后,请确保使用最新版本的以下软件解压缩或提取文件夹:
-
Windows 上的 WinRAR/7-Zip
-
Mac 上的 Zipeg/iZip/UnRarX
-
Linux 上的 7-Zip/PeaZip
本书代码包也托管在 GitHub 上,地址为github.com/PacktPublishing/Hands-On-Qt-for-Python-Developers。如果代码有更新,它将在现有的 GitHub 仓库中更新。
我们还有其他来自我们丰富的书籍和视频目录的代码包,可在github.com/PacktPublishing/找到。查看它们吧!
下载彩色图像
我们还提供包含本书中使用的截图/图表的彩色图像的 PDF 文件。您可以从这里下载:www.packtpub.com/sites/default/files/downloads/9781789612790_ColorImages.pdf。
使用的约定
本书使用了多种文本约定。
CodeInText:表示文本中的代码单词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 昵称。以下是一个示例:“您可以通过遵循说明从 Qt 官方源下载并安装 PySide2 绑定,或者您可以通过pip从PyPI(Python 包索引)安装它。”
代码块设置如下:
...
class UApp(UTools):
def __init__(self):
UTools.__init__(self)
self.uaps1 = "I am a coder, and I do"
当我们希望您注意代码块中的特定部分时,相关的行或项目将以粗体显示:
import "Path/To/JavaScript/File" as Identifier
任何命令行输入或输出都如下所示:
> pip install PyQt5
粗体:表示新术语、重要单词或您在屏幕上看到的单词。例如,菜单或对话框中的单词在文本中显示如下。以下是一个示例:“导航到 选择一个模板 | 应用程序 | Qt Quick 应用程序 - 空白 然后点击 选择....”
警告或重要注意事项如下所示。
小技巧和技巧如下所示。
联系我们
我们始终欢迎读者的反馈。
一般反馈:如果您对本书的任何方面有疑问,请在邮件主题中提及书名,并通过customercare@packtpub.com与我们联系。
勘误:尽管我们已经尽一切努力确保内容的准确性,但错误仍然可能发生。如果您在这本书中发现了错误,我们将不胜感激,如果您能向我们报告这一点。请访问www.packt.com/submit-errata,选择您的书籍,点击勘误提交表单链接,并输入详细信息。
盗版:如果您在互联网上以任何形式遇到我们作品的非法副本,如果您能提供位置地址或网站名称,我们将不胜感激。请通过copyright@packt.com与我们联系,并提供材料的链接。
如果您有兴趣成为作者:如果您在某个主题上具有专业知识,并且您有兴趣撰写或为书籍做出贡献,请访问authors.packtpub.com。
评论
请留下评论。一旦您阅读并使用过这本书,为何不在您购买它的网站上留下评论呢?潜在读者可以查看并使用您的客观意见来做出购买决定,Packt 公司可以了解您对我们产品的看法,我们的作者也可以看到他们对书籍的反馈。谢谢!
如需了解 Packt 的更多信息,请访问 packt.com.
第一部分:PyQt 和 PySide 入门
在本节中,读者将了解 Qt 和 PyQt 的基础知识、编程原理以及使用 Python 编程语言创建 GUI。
本节包含以下章节:
-
第一章,Python 和 Qt 简介
-
第二章,QML 概述
-
第三章,Qt Quick 库
-
第四章,PyQt 和 PySide 入门
第一章:Python 和 Qt 简介
要了解使用 Python 和 Qt 创建图形用户界面(GUI)的过程,我们需要了解语言和框架的基本语法和结构。本章将涵盖 Python 编程语言的基础知识——用于 GUI 创建的最常见方法和操作,以及 Qt 库使用的 C++ 基本语法。此外,还将介绍 Qt 框架。如果没有对此进行解释,开发者在开发过程的早期阶段可能会遇到一些问题。
本章将涵盖以下主题:
-
Python 的基础知识
-
Qt 的基础知识
-
C++ 的基础知识
-
Qt 框架简介
-
比较
Python 的基础知识
Python 是一种作为高级解释器实现的编程语言。它易于学习,具有高效的高级数据结构,简单且面向对象编程的方法高效。它具有优雅的语法,动态类型和解释性,如官方源所述。它是脚本和快速应用开发的最佳语言。我们可以通过使用在 C 或 C++(或可以从 C 调用的其他语言)中实现的新函数和数据类型轻松扩展 Python 解释器。考虑到这一点,使用 Qt 库和 Python 创建 GUI 是一个好的选择。要开始使用 Python,您需要从官方源(如果尚未安装)下载 Python 解释器,并按照说明进行安装。
然后,为了安装 PyQt 和 PySide,您需要在 Linux/Unix 终端或 Windows 命令行中运行以下命令:
> pip install PyQt5
您可以通过遵循说明从 Qt 官方源下载并安装 PySide2 绑定,或者您可以通过 pip 从 PyPI(Python 包索引)安装它:
> pip install PySide2
在本书中,当您需要从终端/命令提示符运行命令时,将使用 >。
使用 Python 和 Qt 创建 GUI 的一个好方法是使用 Anaconda 工具包,这是最佳的基于 Python 的编程生态系统。强烈推荐安装 Anaconda。当您安装 Python 时,您会得到 IDLE,这是一个简单的编辑器。Anaconda 默认包含 Spyder 编辑器,它优于 IDLE。
要运行 IDLE 编辑器,只需在您的终端/命令提示符中键入以下命令:
> idle
使用以下命令打开 Anaconda 的 Spyder 编辑器:
> spyder
安装 Anaconda 后,您也可以在操作系统的开始菜单中找到它。
Python 语法
让我们对 Python 进行简要介绍。在这里,您将找到本书中将使用到的最有用和最流行的定义和操作。有关 Python 编程语言的完整信息,您需要查看官方文档(docs.python.org/3/)。让我们将注意力集中在 Python 开发过程中最常见的事物上。首先,打开终端/命令提示符并输入以下内容:
> python
或者,在命令提示符/终端中输入idle。这两个命令都会运行 Python 解释器:
> idle
变量和值
任何编程语言的基础,不仅仅是 Python,也许不仅仅是编程,都是变量和值的定义和规则。变量和值是描述世界中的对象及其之间关系的元素。变量和值的概念通常以如下形式使用——某些值根据所使用的运算符与变量有关。以下是一个示例:
>>> name = "Name"
>>> number = 1
在这里,name和number是变量。同样,"Name"和1是这些变量的值。在 Python 编程语言中,变量有定义规则。它们必须在使用前定义,并且不能是数字。
以下定义是不正确的:
>>> 1 = 1
此外,变量不能以数字开头。以下定义是不正确的:
>>> 1name = "Name"
变量名不能包含空格。也不建议使用标准 Python 库中内置函数的名称或 Python 模块中导入和定义的名称作为变量名。
以下定义是不正确的:
>>> str = 1
此外,还应避免使用导入模块、函数和类的其他名称,因为使用它们可能会导致意外结果。您不能使用 Python 关键字名称。
以下定义是不正确的:
>>> True = 1
Python 文档中提供了完整的关键字、内置函数和常量列表。值必须是 Python 数据类型,如下所示:
-
字符串:
str(1),"string",'string',和"""documented_string""" -
布尔值:
True或False -
数字:
int(1.1),float(1),complex(1)和1 -
二进制 数据:
bytes("string", encoding='utf-8')不可变和bytearray("string", encoding='utf-8')可变 -
元组:
(1, "string")和tuple("string") -
列表:
[1, "string"]和list("string") -
字典:
{"key1": 1, "key2": "value"}和dict(key1=1, key2="value") -
唯一元素的集合:
set("string")和frozenset("string")不可变集合 -
函数:
def func():pass -
类:
class C:pass -
模块:具有
file_name.py等扩展名的文件 -
NoneType 对象:
None
字符串
当它们被创建时,字符串需要使用引号,'some text',双引号"some text",或文档字符串"""some text"""。Python 中的字符串被解释为字符序列,可以用于以下操作:
切片——结果是字符串,从0开始到第 2 个字符。第一个字符是0:
>>> strings = "string"
>>> strings[0:3]
'str'
反向切片——结果是字符串,从字符串中指定的字符索引开始到 0 字符:
>>> strings[2::-1]
'rts'
连接——结果是合并后的字符串:
>>> strings = "string" + "string"
>>> strings
'stringstring'
乘法——"string"的结果与第二个值相乘:
>>> strings = "string" * 3
'stringstringstring'
分割——结果是按分隔符(如空格或逗号)分割的列表:
>>> strings = "string_some_sep_string".split("_some_sep_")
>>> strings
['string', 'string']
替换——结果是包含新字符的字符串:
>>> strings = "string".replace("str", "programm")
>>> strings
'programming'
最有用的字符串方法如下:
将整数转换为字符串,结果是字符串:
>>> strings = str(1)
>>> strings
'1'
字符串长度——结果是整数:
>>> len("some strings")
12
使用 UTF 进行编码——结果是编码后的二进制对象:
>>> "some strings".encode('utf-8')
b'some strings'
使用 UTF 进行解码——结果是解码后的字符串:
>>> b'\xd0\xa1\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0'.decode('utf-8')
'Строка'
非常常见的是,我们必须处理字符串并解决应用中需要理解不同文本操作的不同编码问题。这只是字符串的简要描述;建议您在 Python 文档中详细了解字符串。
布尔值
Python 提供了逻辑常量,如True和False。
这里是定义值为True的var变量的示例,当我们调用var变量时,结果是布尔值,即True:
>>> var = True
>>> var
True
定义值为False的var变量:
>>> var = False
>>> var
False
使用标准库中的bool函数:
>>> bool(1)
True
>>> bool(0)
False
最终的逻辑运算返回True,如果变量存在或其值等于1。如果它不存在或等于0,则返回False。
数字
Python 解释器可以用作简单的计算器,并提供一些用于处理数字的有用工具:
>>> 1 + 1
2
这段代码定义了值为2的num变量:
>>> num = 2
>>> num
2
当我们使用除法运算符(/)进行数字操作时,Python 2.x 的结果是整数,而 Python 3.x 的结果是浮点数:
>>> num ** num * num / num + num - num
4.0
当我们使用地板除法运算符(//)进行数字操作时,Python 2.x 的结果是整数,Python 3.x 的结果也是整数:
>>> num ** num * num // num + num - num
4
在这里,以及在整个书中,我们将通过示例尝试阐明 Python 主要版本之间的差异。正如我们所见,Python 2.x 使用经典除法返回int()值,而 Python 3.x 返回float()值。使用地板除法,所有版本都返回int()值。
以下操作的结果是整数(除法的余数):
>>> 17 % num
1
这里有一些数字操作示例:
将字符串值转换为整数时,结果是整数:
>>> int('2')
2
int到float——结果是float:
>>> float(2)
2.0
复数——结果是包含实数和虚部的数:
>>> complex(2, 2)
(2+2j)
二进制
要开始处理图像、视频、照片和其他图形对象,我们需要了解这些数据是二进制的,而最有用的工具是bytes()和bytearray():
将字符串转换为二进制对象;结果是二进制对象:
>>> bytes("111", encoding='utf-8')
b'1'
将字符串转换为 bytearray;结果是 bytearray:
>>> b = bytearray("111", encoding='utf-8')
>>> b
bytearray(b'111')
改变二进制数组(此操作仅在bytearray()中可用):
>>> b[0] = 0 >>> b bytearray(b'\x0011')
元组
元组是 Python 中不可变的元素序列。元素可以是字符串、数字或其他 Python 数据类型。
创建并调用以下元组:
>>> tu = (1, (2,), "3")
>>> tu
(1, (2,), '3')
元组是由逗号分隔的元素序列,因此,以("string")的形式定义元组是不正确的。如果元组只有一个元素,则需要逗号,例如,("string",)。
元组切片——元组的所有元素 tu[0:],最后一个元素,索引为 [2] 的元素:
>>> tu[0:]; tu[-1:]; tu[2]
(1, (2,), '3')
('3',)
'3'
这将返回元组中存在的指定元素的数量:
>>> tu.count("3")
1
这将返回元组中指定元素首次出现的索引:
>>> tu.index("3")
2
列表
数据处理中最有用的工具是列表。让我们看看涉及列表的一些方法和操作:
定义一个列表。结果是列表:
>>> li = [1, [2], "3"]
>>> li
[1, [2], '3']
这将返回列表的所有元素。结果是列表:
>>> li[0:]
[1, [2], '3']
这将返回列表的第一个元素:
>>> li[0]
1
这将返回列表的最后一个元素:
>>> li[-1]
'3'
这将返回包含最后一个对象的列表:
>>> li[-1:]
['3']
这将返回列表第二个元素的第一个字符。该元素必须按顺序排列:
>>> li[1][0]
2
这是错误的。整数对象是不可索引的:
>>> li[0][0]
TypeError: 'int' object is not subscriptable
以下是一个列表的列表:
>>> li = [[1], [2, ["3"]]]
>>> li[0]; li[1]; li[1][0]
[1]
[2, ['3']]
2
定义一个名为 var 的列表,然后在这个列表内部定义一个新的列表:
>>> var = [1, 2, 3]
>>> li = [[1], [2, ['3', var]]]
>>> li
[[1], [2, ['3', [1, 2, 3]]]]
以下代码片段展示了如何更改列表的第一个和第二个元素:
>>> li[0] = 1; li[1] = 2
>>> li
[1, 2]
列表可以按以下方式连接:
>>> li + li
[1, 2, 1, 2]
这是列表乘法。列表必须乘以一个数字(整数)值:
>>> li * 3
[1, 2, 1, 2, 1, 2]
列表中最常用的操作如下:
这是在列表末尾添加新项的方式:
>>> li.append(3)
>>> li
[1, 2, 3]
这是在列表的0位置插入新项的方式:
>>> li.insert(0, 0)
>>> li
[[0, 1, 2, 3]]
要检查一个项目是否在列表中,可以使用in运算符:
>>> 0 in li
True
这将找到具有指定值的元素索引并返回第一个元素的索引:
>>> li.index(1)
1
这将移除指定索引的元素:
>>> li.pop(3)
>>> li
[0, 1, 2]
这将移除具有指定值的元素:
>>> li.remove(0)
>>> li
[1, 2]
Python 提供了比其他列表创建机制(如for循环)更快的列表生成器。
列表可以按以下方式生成:
>>> li = [i for i in range(0, 10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> li = [str(i) for i in li]
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
使用指定的分隔符将列表连接到字符串上。列表项必须是字符串:
>>> " ".join(li); "-".join(li);
'0 1 2 3 4 5 6 7 8 9'
'0-1-2-3-4-5-6-7-8-9'
词典
在 Python 中创建数据的另一种方法是使用字典。实际上,字典不是一个序列;它是一个数据映射,因此,适用于元组和列表的操作不适用于字典。常用的字典方法和操作如下。
创建词典:
>>> di = {"key1": "value1", "key2": {2: 2}, 3: 3}
>>> di
{'key1': 'value1', 'key2': {2: 2}, 3: 3}
字典表示存在一个键和一个值,并且每个键/值对在字典中需要用逗号分隔,例如,{key: value, key: value, ...}。
这通过键获取字典值。结果是字典的值:
>>> di["key1"]
'value1'
与字典最相关的操作如下。
这通过键获取字典值,我们只获取存在键的值:
>>> di.get("key1"); di.get("key")
'value1'
这获取字典的所有键。结果是具有键的 dict_keys 对象:
>>> di.keys()
dict_keys(['key1', 'key2', 3])
这获取字典的所有值,结果是具有值的 dict_values 对象:
>>> di.values()
dict_values(['value1', {2: 2}, 3])
这将以元组形式获取字典的所有键和值,结果是 dict_items:
>>> di.items()
dict_items([('key1', 'value1'), ('key2', {2: 2}), (3, 3)])
这在字典中添加了一个新条目:
>>> di.update("key3"=di.values)
{'key1': 'value1', 'key2': {2: 2}, 3: 3, 'key3': <built-in method values of dict object>}
这删除了具有指定键的字典值。结果是已删除的值:
>>> di.pop("key1", "key is not exist")
'value1'
如果键不存在,则返回第二个值:
>>> di.pop("key", "key is not exist")
'key is not exist'
这清除了字典。结果是空字典:
>>> di.clear()
>>> di
{}
集合
此外,在某些情况下,我们还可以使用集合。集合是一组唯一的元素(或组),可以用于数据创建。Python 中的集合可以按以下方式创建。
这将从列表的元素中创建一个集合:
>>> set([1, 2, 2, 3])
{1, 2, 3}
集合是可变的。
创建一个名为 se 的集合,并通过添加新元素来更改集合:
>>> se = set((1, 2, 2, 3))
>>> se.add(4)
{1, 2, 3, 4}
要创建一个不可变集合,我们需要使用 Python 标准库中的 frozenset()。
函数
我们可以将函数视为复变数及其相关操作的结果。Python 中的函数可以接收参数,返回结果,以及/或使用变量和值执行一些操作。要在 Python 中构建函数,请使用以下函数定义方法。
定义函数——param 是函数的参数,被设置为 None:
>>> def func(param=None):
param += 1
return param
>>> func(param=1)
2
前面的代码增加参数并返回,然后使用参数调用函数。
类
现代应用程序创建风格遵循 面向对象编程(OOP)方法,因此使用和理解类是强制性的。使用 Python 创建类的最简单方法是以下:
>>> class C():
def __init__(self):
self.var1 = 2
self.func1()
def func1(self):
self.var2 = self.var1 * 2
def func2(self):
print(self.var2)
# print var2
__init__() 方法是类的构造函数,self.var 是类的属性,self.func() 调用函数,def func1(self) 和 def func2(self) 是类的方法。第一个 print() 函数用于 Python 3.x,第二个注释的 print 函数用于 Python 2.x。
这创建了一个类的实例,并调用了类的 func2():
>>> c = C()
>>> c.func2()
4
如我们所见,类允许我们构建具有广泛功能的代码。通过使用 self 参数,我们可以在类的任何地方使用我们的变量,利用 Python 的动态特性。此外,类提供了基本方法,如继承,这使得类成为 OOP 的基础,我们将在后面讨论。
现在,让我们从命令提示符/终端输入中跳出来,尝试创建一个标准的 Python 模块,以展示标准语法。
要创建一个 Python 模块,请按照以下步骤操作:
-
打开您的设备。
-
打开您喜欢的编辑器,例如记事本、PyCharm、Eclipse 或 Emacs。Anaconda 预装了一个名为 Spyder 的 Python 编辑器,我们在 Python 基础 部分提到了它。
-
创建一个名为
App/的新目录。 -
创建一个新文件,例如我们的 GUI 应用程序的将来名称为
u_app.py。 -
将注意力转向此文件。
Python 模块是一个包含 Python 定义和指令的文件,具有.py扩展名。还有其他扩展名,如.pyc、.pyw和.pyd,这些将在本书的后续部分进行解释。Python 中简单文件和模块之间的一个区别是,模块具有将定义从模块导入到另一个模块的能力。为了演示这一点,让我们在App/目录中创建另一个新文件,命名为u_tools.py。
根据普遍接受的 Python 编码规则,这些规则在Python 增强提案(PEP8)Python 语言风格指南中描述,模块应该有简短的小写名称,例如u_app.py。类应该使用大驼峰命名法,例如UTool()。对于函数,首选小写,例如def func():;。
因此,现在文件已经创建,请在u_app.py文件中包含以下行:
- 在导入部分,从
u_tools.py文件中导入UTools类:
# -*- coding: utf-8 -*-
from u_tools import UTools
...
- 创建继承自
UTools的UApp类:
...
class UApp(UTools):
def __init__(self):
UTools.__init__(self)
self.uaps1 = "I am a coder, and I do"
在__init__()构造函数中,调用UTools类构造函数并将属性作为字符串变量。
- 将
u_app1()函数添加到UApp类中:
...
def u_app1(self):
print(self.uaps1 + " " + self.us1)
# print self.uaps1 + " " + self.us1
此函数将UApp和UTools类的字符串连接起来并打印结果。在 Python 2.x 中使用的注释print函数,如果取消注释并注释上一行,则可以使用print()函数。
- 将
u_app2()函数添加到UApp类中:
...
def u_app2(self):
uap_list1 = []
i = 0
for ul in self.u_list()
if ul.isalnum():
if ul != ".":
uap_list1.insert(i, ul.lower())
elif ul == " ":
uap_list1.insert(i-i, ul)
i = 0
continue
else:
break
i += 1
print(' '.join(uap_list1))
# print ' '.join(uap_list1)
此函数创建一个新的列表;for语句是UTools类列表的循环,并检查它是否是数字或字母。如果不等于".",则将所有字母设置为小写。然后将列表连接到字符串并打印。
- 完成以下
u_tools.py文件:
if __name__ == "__main__":
uap = UApp()
uap.u_app1()
uap.u_app2()
此指令用于定义代码在此文件中的运行方式。如果此模块被导入,__name__将不是"__main__",我们可以在其他地方使用此模块的某些部分。如果此模块作为文件运行(从终端,作为子进程),__name__将是"__main__",并且将通过调用第一个和第二个函数创建类实例。因此,现在我们需要将UTools类添加到u_tools.py文件中。
- 将以下代码添加到
u_tools.py文件中:
# -*- coding: utf-8 -*-
class UTools():
def __init__(self):
self.us1 = "Application with Python."
def u_list(self):
self.ul1 = []
for s in self.us1:
self.ul1.append(s)
return self.ul1
if __name__ == "__main__":
ut = UTools()
print(ut.us1)
# print ut.us1
ut.u_list()
在此模块中,UTools类已在__init__()方法中使用字符串变量创建。u_list()函数将字符串转换为列表。代码符合 PEP8 风格。
现在,让我们看看一些 Python 语法。建议在类的定义之前和类内的函数之前各添加两个空行。此外,如果你没有使用类,建议在函数定义之间也添加两个空行。Python 解释器将脚本作为一个块来执行。代码块从比上一行少四个空格的位置开始。当下一块的空格比前一个块小四个空格时,解释器可以决定这是块的结束。正如你所见,#在行上标记了一个注释,注释文本被解释器忽略。类、函数和语句的定义使用:实现。行尾用;标记,一行上执行多个命令是可能的,但不推荐。为了便于理解,最好将脚本的每一行都写在新的一行上。因此,我们可以读取这两个文件并尝试启动它们。为此,我们需要打开终端/命令提示符并输入以下命令:
> cd Path/To/The/New/Created/Dir/App
> python u_app.py
上述命令的输出显示在下图中:

如果你看到类似的结果,那么一切就都正确了。那么 Python 在运行这个文件时做了什么呢?
Python 解释器
全局解释器锁(GIL)是解释器用来确保一次只有一个线程执行 Python 字节码的一种机制。将解释器锁定到一个实时线程有助于解释器成为多线程的,以支持多处理器机器的并行性。当执行 I/O 操作时,GIL 总是被释放。Python 解释器是一个程序,它将其他包含指令的程序翻译并启动。
它有时被称为Python 虚拟机(PVM),类似于Java 虚拟机(JVM),它提供了将代码翻译成字节码并执行下一步的进程,与像 C++这样的语言不同,这些语言将代码翻译成直接在硬件上运行的指令。理解像 Python 和 Java 这样的语言非常重要,它们构成了编程技术进步的一大步。
让我们看看 Python 解释器是如何运行代码行的。首先,它从上到下逐行执行代码。Python 3.x 将位于文件所在位置的_pycache_目录中的导入模块编译,并将.pyc扩展名添加到编译文件中。然后,PVM 将指令翻译成字节码并执行它们。
Qt 框架
Qt 是一个跨平台的应用程序框架和窗口工具包,用于创建在所有主要桌面、移动和嵌入式平台上运行的 GUI 应用程序。大多数使用 Qt 开发的 GUI 程序都具有本地外观的界面。在这种情况下,Qt 被归类为窗口工具包。要使用 Qt 作为开发框架,您需要从官方源([www.qt.io/](https://www.qt.io/))下载 Qt,然后将其安装到您的设备上。Qt 支持 GCC C++ 编译器和 Visual Studio 套件等编译器。Qt 提供了 Qt Creator、Qt Designer、Qt Assistant 和 Qt Linguist 等强大的 IDE 和工具。要使用 Qt 创建 GUI,只需打开 Qt Creator,欢迎您创建图形应用程序!然而,本书不会描述如何使用 Qt Creator 或 Qt Designer 等 IDE 创建 GUI。本书主要关注使用 Qt 和 Python 创建 GUI。但如果您想从 Qt Creator 开始,那么欢迎您继续前进。因为 Qt 主要是 C++ 库,我们首先需要了解 C++ 的基本方法和语法。
C++
如您从名称中可能猜到的,C++ 是一种基于 C 的语言,并且具有类似的语法。我们可以假设 Python 也与 C 有关,但不要混淆这些语言。如果 C++ 是可调用的 C 语言并且具有类似的语法,那么我们可以将 Python 解释器称为我们之前讨论过的基于 C 的、低级虚拟机。Python 语法和 C 语法并不相同。
为了演示这一点,我们需要在为应用程序开发创建的 App/ 目录中创建一个名为 cpp_file1.cpp 的文件,并向文件中添加以下行:
#include <iostream>
int main() {
std::cout << "C++ console program\n";
}
带有 # 的行是读取和解释的指令,称为预处理器。然后,是 C++ 中函数的声明,main()。花括号 {} 内的内容是一个函数体。要获取此代码的结果,您需要安装一个 C++ 编译器。如 DEV-C++、Code::blocks 和 Visual Studio Express 等 IDE 允许我们编译代码。如果您是 Linux/Mac 用户,C++ 编译器可以安装到您的系统上(如 GCC 或 Clang),然后您可以使用终端编译此代码。下载并安装 C++ 编译器后,您需要根据编译器的特性编译此代码。
因此,将生成一个如 cpp_file1.exe 的文件,然后您需要在终端/命令提示符中输入以下内容:
> cd Path/To/The/Directory/App/ // Windows
> cpp_file1.exe
// Linux
> g++ -o cpp_file1 cpp_file1.cpp
> ./cpp_file1
您可以在 C++ 中看到程序的结果:

让我们描述一些在学习 Qt 库的过程中可以遇到的 C++ 语法。
C++运算符
C++ 中有以下运算符可用:
-
::: 范围限定符 -
++ --: 后缀自增/自减 -
(): 函数形式 -
[]: 下标 -
. ->: 成员访问 -
++ --: 前缀自增/自减 -
~ !: 按位非/逻辑非 -
+ -: 一元前缀 -
& *: 引用/解引用 -
new delete: 分配/释放 -
sizeof: 参数包 -
(type): C 风格的类型转换.* ->*: 访问指针 -
* / %: 乘法、除法和取模 -
+ -: 加法和减法 -
<< >>: 左移和右移 -
< > <= >=: 比较运算符 -
== !=: 等于/不等于 -
& ^ | && ||: 位与、位异或、位或、逻辑与和逻辑或 -
= *= /= %= += -= >>= <<= &= ^= |=: 赋值/复合赋值 -
?:: 条件运算符 -
,: 逗号分隔符
C++ 语法要求在第一次使用之前必须声明每个变量的类型。
在 App/ 文件夹中创建 cpp_file2.cpp 文件,包含以下行:
#include <iostream>
int main() {
int a = 7;
float b;
float result;
b = 7.14;
result = a + b;
std::cout << result;
std::cout << "\nCompleted\n";
}
此代码将 a 变量声明为 int 类型,并赋予值为 7,然后声明 b 变量为 float 类型。声明 result 变量为 float 类型。然后,它将变量相加。结果输出到终端/cmd。按照以下方式编译和运行代码:
// Windows
> cpp_file2.exe
// Linux
> ./cpp_file2
上述命令的结果如下:

在 App/ 文件夹中创建 cpp_file3.cpp 文件,包含以下行。
这就是 cpp_file3.cpp 文件的样子:
#include <iostream>
#include <string>
using namespace std;
int main() {
int arr[5] = { 7, 14, 77, 140, 1414 };
if (arr[0] == 7) {
cout << arr[0] << '\n';
}
for (int s = 2; arr[s]; arr[s++]) {
if (arr[s] <= 1414){
cout << arr[s-1] << '\n';
}
else {
break;
}
}
}
此代码首先定义一个数组并构建一个 if 语句。如果条件为真,则打印结果并换行。构建 for 语句以及 if else 语句。然后,中断循环并编译并运行 cpp_file3.exe:
// Windows
> cpp_file3.exe
// Linux
> ./cpp_file3
上述命令的输出如下所示:

让我们来看看 C++ 函数。
C++ 函数
C++ 中的函数语法为 type name ( parameters ) { statements },其中 type 是函数返回值的类型,name 是函数的标识符,parameters 是函数的参数,例如 int x 和 int y,最后 statements 是函数体,它是一组指定函数实际做什么的语句。在 C++ 中,可以在声明变量的命名空间内访问变量,但如果从外部访问,则必须使用 ::(作用域运算符)正确限定。在 App/ 文件夹中创建 cpp_file4.cpp 文件,包含以下行。
这就是 cpp_file4.cpp 文件的样子:
#include <iostream>
#include <string>
using namespace std;
namespace space1 {
string func() {
string str1 = " C++ ";
return str1;
}
}
namespace space2 {
string func() {
string str2 = " Program \n";
return str2;
}
}
int main() {
string newstring;
string newstr1 = space1::func();
string newstr2 = space2::func();
newstring = newstr1 + newstr2;
cout << newstring;
return 0;
}
标准 C++库中的变量、类型、常量和函数在 std 命名空间内声明。按照以下方式编译和运行:
// Windows
> cpp_file4.exe
// Linux
> ./cpp_file4
上述命令的输出如下所示:

让我们看看无类型的函数。
无类型的函数
在 C++ 中创建函数时,需要声明函数返回值的类型。如果函数不需要返回值,则使用 void,这是一个特殊类型,用于表示没有值。在 App/ 文件夹中创建 cpp_file5.cpp 文件,包含以下行。
这就是 cpp_file5.cpp 文件的样子:
#include <iostream>
using namespace std;
void printstr() {
cout << "C++ Program\n";
}
int main() {
printstr();
return 0;
}
它定义了一个 void 类型的函数,并在函数被调用时打印结果。
按照以下步骤编译和运行:
// Windows
> cpp_file5.exe
// Linux
> ./cpp_file5
前一个命令的输出显示在以下屏幕截图:

现在,让我们继续讨论 C++ 类。
C++ 类
在这个简短的 C++ 语法演示结束时,让我们描述一下类。以下是一个在 cpp_file6.cpp 文件中具有继承构造的类的示例。在 App/ 文件夹中创建以下内容:
#include <iostream>
using namespace std;
class Result {
public:
static void print(int i);
};
void Result::print(int i) {
cout << i << '\n';
}
class Class1 {
protected:
int x, y, z;
public:
Class1(int a, int b, int c): x(a), y(b), z(c) {}
};
class Class2: public Class1, public Result {
public:
Class2(int a, int b, int c): Class1(a, b, c) {}
int result() {
return x*y*z;
}
};
int main () {
Class2 c2(7, 7, 7);
c2.print(c2.result());
Class2::print(c2.result());
return 0;
}
按照以下步骤编译和运行:
// Windows
> cpp_file5.exe
// Linux
> ./cpp_file5
前一个命令的输出显示在以下屏幕截图:

如果你得到这样的结果,那么一切正常。
Qt
我们简要介绍了 C++ 语法的基础知识。现在,让我们看看 Qt 的结构。目前支持的 Qt 版本是 5.6-5.13。例如,4.x 或以下版本有一些差异,但这些差异不是根本性的,并且使用低于 5 的版本编写的代码可以轻松转换。本书将考虑 Qt 的 5.9-5.13 版本,并在可能的情况下考虑其他版本。
如前所述,Qt 是一个强大的框架,支持 Windows 10/8/7、大多数 Linux/X11-RHEL6/7、Ubuntu、openSUSE、Android、macOS 和 iOS。下载并安装后,Qt 框架提供以下工具:
-
Qt Creator: 这是一个 IDE,它包括以下集成工具:
-
Qt 设计器: 这是为了从 Qt 小部件设计并构建 GUI。
-
qmake: 这是为了为不同平台构建应用程序。
-
Qt 语言学家: 这包括本地化工具。
-
Qt 助手: 这就是 Qt 文档。
Qt 框架还提供以下集成工具:
-
makeqpf: 这是为了为嵌入式设备创建预渲染字体。
-
元对象编译器(moc): 这是为了为 QObject 子类生成元对象信息。
-
用户界面编译器(uic): 这是为了从 UI 文件生成 C++ 代码。
-
资源编译器(rcc): 这是在构建过程中将资源嵌入到 Qt 应用程序中。
-
Qt D-Bus XML 编译器(qdbusxml2cpp): 这将 D-Bus 接口描述转换为 C++ 源代码。
-
D-Bus 观察器: 这是为了检查 D-Bus 对象和消息。
-
Qt 快速编译器: 这是一个用于 Qt 模型语言(QML)的编译器,可以在不部署 QML 源文件的情况下构建 Qt 快速应用程序。
-
Qt VS 工具: 这是为了使用 Visual Studio IDE 创建 Qt 应用程序,而不是 Qt Creator。
Qt 5 提供以下模块:
-
Qt 核心: 这包含核心的非图形类。
-
Qt GUI: 这包含包括 OpenGL 在内的 GUI 组件类。
-
Qt 多媒体: 这包含音频、视频、收音机和摄像头功能类。
-
Qt 多媒体小部件: 这提供了多媒体功能。
-
Qt 网络: 这是为了提供网络支持。
-
Qt QML:包含 QML 和 JavaScript 的类。
-
Qt Quick:这是一个用于构建高度动态应用的框架。Qt Quick 控件:包含可用于创建经典桌面风格 UI 的 UI 控件。
-
Qt Quick 对话框:用于从 Qt Quick 应用程序制作系统对话框。
-
Qt Quick 布局:用于为基于 Qt Quick 的项目制作布局。
-
Qt SQL:用于 SQL 数据库集成。
-
Qt 测试:包含测试库。
-
Qt 小部件:用于使用 C++小部件制作 Qt GUI。
此外,它还提供了与不同平台和/或商业许可相关的附加组件:
-
ActiveQt:ActiveX 和 COM(Windows)。
-
Qt 3D:二维和三维渲染。
-
Qt Android 扩展:Android 平台的特定 API。
-
Qt 蓝牙:访问蓝牙硬件。
-
Qt Canvas 3D:从 Qt Quick 进行类似 OpenGL 的 3D 绘图调用。
-
Qt 并发:不使用低级线程原语的多线程程序。
-
Qt D-Bus:通过 D-Bus 协议进行进程间通信。
-
Qt 游戏手柄:Qt 应用程序的游戏手柄硬件。
-
Qt 图形效果:Qt Quick 2 的图形效果。
-
Qt 位置 API:在 QML 中提供地图、导航和地点内容。
-
Qt Mac 扩展:macOS 平台的特定 API。
-
Qt NFC:访问近场通信(NFC)硬件。
-
Qt 平台头文件:封装特定平台的信息。
-
Qt 定位 API:位置、卫星和区域监控。
-
Qt 打印支持:打印。
-
Qt 购买:Qt 应用程序中的产品内购买。
-
Qt Quick 控件 2:嵌入式和移动设备。
-
Qt Quick 扩展:用于在 Qt Quick 中构建界面的控件集。
-
Qt SCXML:从状态图 XML(SCXML)文件创建状态机并将其嵌入到应用程序中。
-
Qt 传感器 API:传感器硬件和运动手势识别。
-
Qt 串行总线 API:访问串行工业总线接口(Linux)。
-
Qt 串行端口:访问硬件和虚拟串行端口。
-
Qt SVG:显示 SVG 文件的内容。
-
Qt WebChannel:从 HTML 客户端访问 QObject 或 QML 对象,以集成 Qt 应用程序与 HTML/JavaScript 客户端。
-
Qt WebEngine:使用 Chromium 浏览器项目嵌入网页内容。
-
Qt WebSocket:WebSocket 通信。
-
Qt WebView:显示网页内容。
-
Qt Win 扩展:Windows 平台的特定 API。
-
Qt XML:简单 XML API(SAX)和文档对象模型(DOM)的 C++实现。
-
Qt XML 模式:XPath、XQuery、XSLT 和 XML 模式验证。
-
Qt Wayland 合成器:用于开发 Wayland 合成器(Linux)的框架。
所有这些模块,包括 C++ 类、QML 类型(我们将在下一章中介绍)、额外的包和工具,都提供了使用 Qt 框架进行应用程序创建过程的机制。在这本书中,我们无法详细描述库中的所有类。这是不可能的,因为它们有超过 1,500 个。我们将查看开发者尝试使用 GUI 创建应用程序时最有用和最受欢迎的类。
比较
之前描述的原则对于使用 Qt 和 Python 进行编程过程非常重要。我们涵盖了 Python、C++ 和 Qt 模块的基本语法和规则,这些是我们创建 GUI 时将使用的主要工具。官方 Qt 文档通常提供了 C++ 类的描述。强烈建议阅读这些文档,无论是 Qt (doc.qt.io/) 还是 C++ (www.cplusplus.com/doc/tutorial/)。Python 的描述非常简短,因此建议您查阅官方 Python 文档 (docs.python.org/3/)。
现在,让我们阅读一些官方示例,并尝试理解它们。我们需要在官方网站上找到 QtWidgets 模块。打开并查看文档的前几行。注意 #include <QtWidgets>——这一行在 Python 代码中可以表示为 import QtWidgets,但当我们开始使用 Python 时,我们将使用 Python 绑定到 Qt 或 PyQt5 作为包。因此,我们需要编写 from PyQt5 import QtWidgets。然后,为了在 Python 中创建一个新的小部件,我们需要使用 widget = QtWidgets.QWidget(parent)。
在应用程序中使用布局的函数是 void QWidget::setLayout(QLayout *layout),其具体代码如下:
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(formWidget);
setLayout(layout);
在前面的代码中,我们创建了一个新的 QVBoxLayout 类,向布局中添加了一个小部件,并设置了布局。这可以使用 PyQt5 实现:
layout = QtWidgets.QVBoxLayout()
layout.addWidget(formWidget)
widget.setLayout(layout)
Qt 是创建图形应用程序最大和最强大的库。Python 提供了世界上最大的功能工具集,可以处理任何现代编程任务。它们一起可以产生最伟大的应用程序。使用线程、多进程和异步编程可以使应用程序高效和高效。Python 编程语言的范式位于实时宇宙中,这是其强大的一面。
摘要
在本章中,我们介绍了开始 GUI 开发所需的基本仪器和工具。这是学习使用 Python 进行开发的第一个阶段的介绍。当然,这还远远不够,但它将有助于接下来的章节。当开发者想要使用 PyQt 和 PySide 创建应用程序时,Python、C++ 和 Qt 是最常用的。有关这些语言的语法详细信息,强烈建议学习官方文档。
在下一章中,我们将学习关于 QML——实现不同功能的强大标记语言。
第二章:QML 概述
在创建图形用户界面(GUI)时,你可以采取各种方法并做出设计决策。其中之一是使用Qt 建模语言(QML)实现来创建 GUI。本章将探讨 QML 的基础知识,揭示最常用的类型,并以一些使用 QML 构建应用程序的实践结束。
在本章中,我们将涵盖以下主题:
-
QML 简介
-
QML 的基本语法
-
语言和引擎
-
QML 样式
-
QML 动画
关于 QML
QML 是一种 UI 标记语言,是一种类似于 CSS 和 JSON 的多范式声明性语言。它用于设计具有 GUI 的应用程序。QML 很受欢迎,对于创建高质量的 GUI 非常重要。QML 是一种允许开发者用其视觉组件以及它们如何相互交互和关联来描述不同界面的语言。
QML 是一种高度可读的语言,允许组件动态地相互连接。在这种情况下,组件将在 UI 中重用和定制。QML 提供了一种可读的、类似 JSON 的声明性语法,并支持命令式 JavaScript 表达式,结合动态属性绑定。应用程序功能可以通过 JavaScript 进行脚本化。QML 使用 Qt,这使得 Qt 功能可以从 QML 应用程序中访问。在 Qt 框架中,QML 语言和引擎基础设施由QtQml模块提供。为了完全理解 QML,建议阅读官方 Qt 文档(doc.qt.io)。
本章将展示许多 QML 示例,这些示例将以 QML 文件中的脚本形式展示。常用的模块如QtQML和QtQuick(将在第三章“Qt Quick 库”中讨论)将展示如何使用 Qt 实现 QML。要运行 QML 脚本并显示结果,你可以使用 Qt Creator。为此,你需要执行以下步骤:
-
在
App/文件夹内创建一个名为Qt/的目录,例如,App/Qt/。 -
打开 Qt Creator 并导航到文件 | 新文件或项目:

- 导航到选择模板 | 应用程序 | 空 Qt Quick 应用程序并点击“选择...”:

- 将名称设置为
qml1并在“创建在”字段中输入Path/To/The/App/Qt/:

-
点击后续窗口中的“下一步”,并在到达“工具包”窗口时选择所有工具包。然后,点击“下一步”和“完成”。
-
将
RectangleQML 类型添加到main.qml文件中的WindowQML 类型内。 -
点击“构建项目”按钮。
-
最后,点击“运行”按钮:

以下截图显示了前面代码的输出:

或者,您也可以使用 Python。要使用 Python 和 PyQt5 绑定(也可以使用 PySide2)运行这些示例,您需要在App/目录内创建一个文件,例如u_qml.qml,如第一章,“Python 和 Qt 介绍”中所述,然后在u_app.py和u_tools.py文件中进行一些更改。
u_tools.py文件中的更改如下:
# -*- coding: utf-8 -*-
from PyQt5.QtCore import QUrl
from PyQt5.QtQml import QQmlApplicationEngine
class UTools():
def __init__(self):
self.us1 = "QML with Python."
def u_qml(self):
self.qwid = QQmlApplicationEngine()
self.qwid.load(QUrl('u_qml.qml'))
if __name__ == "__main__":
ut = UTools()
在这个类中创建的u_qml()函数将被用来显示 QML 应用程序。使用 QML 应用程序引擎将加载指定 URL 的 QML 文件。
u_app.py文件中的更改如下:
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets
from u_tools import UTools
class UApp(QtWidgets.QWidget, UTools):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
UTools.__init__(self)
self.start_qml()
def start_qml(self):
self.u_qml()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
uap = UApp()
# uap.show()
sys.exit(app.exec_())
start_qml()函数将启动UTools类的u_qml()函数,这将显示 QML 应用程序。然后,我们需要在App/文件夹中创建u_qml.qml文件,这将作为 QML 应用程序。
u_qml.qml文件看起来是这样的:
import QtQuick.Window 2.2
Window {
visible: true
width: 350
height: 590
title: qsTr("First Qml")
}
您应该看到一个标题为“First Qml”的空白窗口。
语法基础
让我们逐步描述 QML 语法的要点。
导入语句
一个 QML 文档可以在文件开头有一个或多个导入。导入可以是以下任何一个:
- 已将类型注册到其中的命名空间:
import QtQuick 2.7
QtQuick模块和其他与 QML 相关的模块的版本号可能因您安装的 Qt 版本而异。
- 一个包含类型定义的 QML 文档的目录:
import QtQuick.LocalStorage 2.0 as Database
import "../privateComponents"
- 一个 JavaScript 文件:
import "somefile.js" as Script
导入类型
QML 有三种不同类型的导入。每种导入类型都有略微不同的语法和语义。
模块命名空间导入
模块命名空间导入是导入到给定命名空间中的 QML 模块,这些模块将 QML 对象类型和 JavaScript 资源注册到该命名空间中。一个例子是import <ModuleIdentifier> <Version.Number> [as <Qualifier>]。以下是一个无限定符模块导入的例子:
import QtQuick 2.7
这允许我们使用所有类型的QtQuick 2.7,而无需指定限定符。
u_qml.qml文件演示了在 QML 中使用导入:
import QtQuick 2.7
import QtQuick.Window 2.2
Window {
...
}
这是一个合格的模块导入:
import QtQuick.Window 2.2 as UQml
UQml.Window {
visible: true
width: 350
height: 590
title: qsTr("First Qml")
}
这段代码将QtQuick.Window导入为UQml并声明了一个具有属性的窗口。这防止了导入冲突的类型名称。
非模块命名空间导入
类型也可以使用如qmlRegisterType()之类的注册函数在 C++的命名空间中注册。如果我们像导入模块标识符一样导入一个命名空间,那么这些类型就可以被导入。类似于导入到限定本地命名空间,import语句可以使用as关键字来指示类型应该导入到特定的文档本地命名空间。如果定义了命名空间,则必须使用本地命名空间限定符来前缀通过导入可访问的类型引用。
在u_qml.qml文件中有一个示例:
import QtQuick 2.7 as UQml
import QtQuick.Window 2.2 as UQml
UQml.Window {
...
UQml.Rectangle {
color: "#FF0000"
width: 140
height: 140
border.color: "#FF0000"
border.width: 1
radius: width * 0.5
}
}
首先是Rectangle QML 类型的声明。然后,设置Rectangle的color的十六进制值,以及width和height。接着,设置边框颜色的十六进制值,包括Rectangle的border.width和radius。
目录导入
这些导入了一个包含 QML 文档的目录,这些文档提供了对 QML 类型进行分割的功能,以便在文件系统中形成可重用的组和目录。
这些导入的例子如下:
import "Path/To/The/Directory/With/Qml/" as Qualifier
为了演示这一点,将u_qml.qml文件分为两部分。第一部分创建一个窗口,而第二部分创建一个圆形。在App/内部创建qmls/目录,并将UCircle.qml文件放入其中。
UCircle.qml文件的内容如下:
import QtQuick 2.7
Rectangle {
color: Qt.rgba(1, 0, 0, 1);
border.color: Qt.rgba(0.9, 0, 0, 1);
border.width: 1
radius: width * 0.5
}
首先是Rectangle QML 类型的声明。然后,设置Rectangle的颜色 RGBA 值、Rectangle的width、Rectangle的height、Rectangle的border.width以及将矩形变为圆形的radius。
在u_qml.qml文件中,我们可以通过导入App/qmls/文件夹来添加这个圆形:
import QtQuick.Window 2.2 as UQml
import "qmls" as Uqmls
UQml.Window {
...
Uqmls.UCircle {
width: UQml.Window.width
height: UQml.Window.height
}
}
我们使用了在单独的 QML 文件中创建的圆形。
JavaScript 资源导入
这些导入可以直接将 JavaScript 资源导入到 QML 文档中。每个 JavaScript 资源都必须有一个标识符,可以通过以下方式访问:
import "Path/To/Javascript/File" as Identifier
为了演示这一点,让我们在App/文件夹内创建一个名为App/jscripts/的目录,并将u_js.js文件放在那里:
function hsize(height) {
return height - 10;
}
在u_qml.qml文件中,我们可以添加对 JavaScript 的导入:
...
import "qmls" as Uqmls
import "jscripts/u_js.js" as Ujs
UQml.Window {
...
以下代码展示了如何在u_qml.qml文件中将圆形和鼠标区域添加到UQml.Window:
...
UQml.Window {
...
Uqmls.UCircle {
id: rcircle
anchors.centerIn: parent
...
}
MouseArea {
anchors.fill: parent
onClicked: rcircle.height = Ujs.hsize(rcircle.height);
}
}
在这个例子中,我们导入 JavaScript 来调整圆形的大小。MouseArea QML 类型实现了可点击的区域。
QML 对象声明
QML 文档中的对象声明语法如下。
对象
对象通过类型指定,用一对花括号括起来。每个对象类型以大写字母开头。在大括号内,我们可以指定有关对象的信息,例如其属性。属性设置为property: value。每个对象可以声明一个嵌套的子对象作为子对象,并且可以包含任意数量的子对象,如前例所示。让我们看看一些新的例子:
- 在
qmls/目录下创建一个新的 QML 文件,命名为URect.qml——这将是一个矩形。添加以下行:
import QtQuick 2.7
Rectangle {}
- 在
u_qml.qml文件中,添加创建的矩形:
import QtQuick 2.7
import QtQuick.Window 2.2 as UQml
import "qmls" as Uqmls
UQml.Window {
visible: true
width: 350
height: 590
title: qsTr("First Qml")
...
}
我们正在重写之前创建的行,并添加Window QML 类型和新属性。
- 现在,
rect1将被添加到UQml.Window的底部:
...
....
Uqmls.URect {
id: rect1
color: "#000000"
width: parent.width - (parent.width / 5)
height: parent.height
MouseArea {
anchors.fill: parent
onClicked: rect1.color = "#222222";
}
}
}
我们在URect.qml文件中添加了具有id、width、height和color属性的矩形。使用MouseArea QML 类型来点击矩形,从而改变其颜色。
- 然后,在第一个矩形之后添加
rect2:
...
...
Uqmls.URect {
id: rect2
color: "#00293b"
x: rect1.width
width: parent.width / 5
height: parent.height
MouseArea {
anchors.fill: parent
onClicked: rect2.color = "#340147";
}
}
}
第二个矩形是窗口的嵌套对象。id属性必须是唯一的。rect2的位置依赖于rect1的位置。
注释
QML 注释可以是单行或多行的。单行注释以//开头,并在行尾结束。多行注释以/*开头,以*/结束。
对象属性
每个 QML 对象类型都有一组属性。对象类型的实例是用为该对象类型定义的属性集构建的。QML 对象属性类型如下:
-
id属性 -
property属性 -
signal属性 -
信号处理程序属性
-
方法属性
-
附加属性和附加信号处理程序属性
id 属性
每个 QML 对象类型都有一个由语言本身提供的id属性,并且不能被任何对象类型重新定义或覆盖。可以为对象实例的id属性赋值,这可以标识对象并允许其他对象引用它。
id属性必须以小写字母或下划线开头,可以包含数字、字母和下划线等字符。可以在声明它的组件作用域内的任何地方通过id引用对象。id值始终唯一是很重要的。当创建对象时,其id属性的值不能更改。为了演示这一点,请执行以下步骤:
- 在
qmls/目录内创建一个名为UText.qml的文件,并添加以下行:
import QtQuick 2.7
Text {
color: "#FFFFFF"
}
这段代码创建将显示为白色的文本。
- 在
u_qml.qml文件的rect1底部添加Uqmls.UText:
...
...
...
Uqmls.UText {
id: utext1
x: 20
y: 50
font.family: "Open"
font.pixelSize: 37
width: rect1.width - (20 * 2)
text: "text 1"
}
Uqmls.UText {
id: utext2
x: 20
y: utext1.height + (50 * 2)
font.family: "Verdana"
font.pixelSize: 27
width: rect1.width - (20 * 2)
}
Uqmls.UText {
id: utext3
x: 20
y: (utext1.height + utext2.height) + (50 * 3)
font.family: "Open Sans"
font.pointSize: 14
width: rect1.width - (20 * 2)
}
...
...
...
这演示了字体家族和字体大小等属性。
- 将第二个矩形(将用作右侧面板)添加到
UQml.Window:
...
...
Uqmls.URect {
...
MouseArea {
anchors.fill: parent
onClicked: {
rect2.color = "#340147";
utext2.text = "text 2";
utext3.text = "text 3";
}
}
}
}
这段代码将为点击rect2时使用的新功能添加新功能,例如更改颜色和设置rect2的文本。我们可以如下看到这个 QML 的结果:

如果我们点击这个窗口的左侧区域,这个区域的颜色将会改变。如果点击右侧区域,将显示两段文本,并且右侧面板的颜色将改变。
属性属性
QML 中的属性是对象的属性,可以是静态值或绑定到动态表达式。您可以通过注册Q_PROPERTY()宏并在 QML 类型系统中注册它来在 C++中为类型定义属性。如前所述的示例中,可以在对象声明中使用以下语法定义自定义属性:property propertyType propertyName。声明的属性名称必须以小写字母开头,可以包含字母、数字和下划线。不允许使用保留的 JavaScript 单词作为属性名称。自定义属性隐式创建一个值更改信号。与此属性关联的信号处理程序将采用onPropertyNameChanged的形式,其中PropertyName是属性名称,首字母大写。QML 的一个主要特性是属性的绑定。绑定允许我们通过指定对象属性之间的关系,根据变化使用动态对象行为。让我们实现以下步骤:
- 在
qmls/目录中创建UButton.qml文件,并在其中包含一个简单的Button类型:
import QtQuick.Controls 2.2
Button {
flat: true
highlighted: true
}
这将创建标准的 QML 按钮。
- 查看
u_qml.qml文件中的功能。更改一些行并添加标准的 QML 按钮。
向第一个矩形添加一个自定义属性,并更改MouseArea,使其类似于以下代码:
...
...
Uqmls.URect {
id: rect1
...
property int rzwidth: parent.width - (parent.width / 5)
width: parent.width
height: parent.height
MouseArea {
...
onClicked: {
rect1.width = rect1.rzwidth;
rect2.visible = true;
}
}
}
...
...
rzwidth是在初始化时定义的自定义属性。
- 更改第二个矩形并添加按钮:
...
...
Uqmls.URect {
id: rect2
visible: false
...
Uqmls.UButton {
text: "Hide"
onClicked: {
rect2.visible = false;
rect1.width = UQml.Window.width;
}
}
}
}
将可见属性设置为false意味着rect2将不可见。当按钮被点击时,使用命令值赋值来调整rect1的大小。结果如下所示:

QML 允许使用自定义属性定义以下有效类型:
-
int 1 -
string "String" -
url "https://doc.qt.io"
任何 QML 对象类型都可以用作属性类型,例如,property Rectangle YouRectangle。
对象实例的属性值可以在初始化时指定为值赋值或通过命令值赋值。在初始化时对属性赋值将采用以下形式:
property int rzwidth: UQml.Window.width - (UQml.Window.width / 5)
命令值赋值是在使用命令 JavaScript 代码将属性值赋给属性时:
onClicked: { rect2.visible = false; }
可以分配给属性的值可以是静态或绑定表达式形式。静态值是一个不依赖于其他属性的常量值,绑定表达式是一个描述属性与其他属性之间绑定关系的 JavaScript 表达式。属性值必须匹配属性类型。此外,还可以分配列表类型属性,其中列表由 QML 对象类型值作为状态组成,例如,[State {name: "value1"}, State {name: "value2"}]。属性可以像这样按font值对Text对象的属性进行分组:
Text {
font {pixelSize: 12; family: "Verdana"}
}
属性可以声明为别名属性,这意味着属性将别名属性作为对被别名属性的引用连接起来。属性别名声明类似于普通属性定义,只是添加了别名关键字和有效的别名引用。
信号属性
信号是从发射对象发出的通知,表明已发生事件。这可能包括文本的变化、按钮的按下、光标的移动等等。通过信号处理程序,某些对象可以被通知已发出信号。信号声明可以以下列形式存在:
Item {
signal clicked
signal hovered()
signal actionPerformed(string action, var actionResult)
}
使用这样的属性,可以通过在 QML 类型系统中注册一个Q_SIGNAL宏来为 C++中的类型定义一个信号。此外,也可以在 QML 文档中定义自定义信号。通常,QML 信号处理程序定义位于将发出信号的物体内部,如前面的MouseArea示例所示。此外,QML 还允许我们使用Connections类型独立于对象使用信号。
信号处理程序属性
为了展示信号处理程序的实现,让我们看看u_qml.qml文件:
...
UQml.Window {
...
color: "#000F1F"
这为应用程序窗口添加了背景颜色。现在,让我们执行以下步骤:
- 为第一个矩形添加一个
Connections类型和自定义处理程序:
Uqmls.URect {
id: rect1
signal colored(color uColor)
...
property int rzwidth
...
height: parent.height / 10
onColored: rect1.color = uColor;
MouseArea {
id: marea1
anchors.fill: parent
}
Connections {
target: marea1
onClicked: {
rect1.width = rect1.rzwidth;
rect2.visible = true;
}
onPressed: rect1.colored("#002737")
}
}
这添加了onColored信号处理程序并创建了矩形的鼠标区域连接。它还将Connections的目标设置为rect1的鼠标区域。
- 为第二个矩形的按钮添加一些额外的属性:
Uqmls.URect {
...
Uqmls.UButton {
id: ubut1
width: rect2.width
height: rect2.height / 10
text: "Hide"
onClicked: {
rect2.visible = false;
rect1.width = UQml.Window.width;
}
}
}
}
此代码为具有指定id的按钮添加了width和height属性。如果我们运行u_app.py文件,我们可以看到此结果:

如我们所见,colored()信号在rect1对象中声明,然后通过id与MouseArea相关的Connections的onPressed信号处理程序一起发出。此信号被rect1的onColored信号处理程序接收。许多 QML 类型都定义了信号。例如,文本字段有accepted()、editingFinished()、textEdited();按钮有Button、RadioButton和CheckBox,而ComboBox分别有clicked()、accepted()和activated()信号。信号将在第十五章中更详细地描述,信号、槽和事件处理程序,以及它们与 PyQt 和 PySide 的关系,但它们的逻辑是相似的。
方法属性
可以定义一些函数以实现特定的功能。方法可以通过Q_INVOKABLE宏或将其注册为Q_SLOT宏(例如,与信号一起)与 QML 类型系统注册。可以通过在对象声明中添加function functionName(parameterName) {函数体}来定义自定义方法。通常,方法提供与 JavaScript 代码的计算或使用相关的某些功能。让我们看看使用此函数与 QML 的示例。
让我们在rect1中添加一个方法:
...
...
Uqmls.URect {
id: rect1
...
function onUcolor(ucolor) {
if (ucolor=="#000F1D") {
return "#000F1F";
} else {
return "#000F1D";
};
}
onColored: rect1.color = onUcolor(rect1.color);
...
...
...
如果rect1不是白色,onUcolor函数将返回白色,如果颜色是白色,则返回shuttle颜色(看起来类似于深蓝色的颜色)。
JavaScript 和 QML
QML 最强大的功能之一是提供 JavaScript 功能。这允许我们使用各种表达式和方法作为 JavaScript 函数。QML 具有深度的 JavaScript 集成,这使得它能够使用 JavaScript 形式的函数定义和信号处理器。我们在导入语句部分讨论了将 JavaScript 作为导入资源的使用。让我们看看 JavaScript 宿主环境和其使用的限制。
QML 引擎提供了一个 JavaScript 环境,并且这个环境与网络浏览器提供的环境略有不同。QML 文档可能包含以下形式的 JavaScript 代码:
-
在属性绑定中,代码描述了 QML 对象属性之间的关系。
-
在实现信号处理器后。
-
在自定义方法的定义中,函数在 QML 对象的主体内部定义,可能包括变量设置、数组、循环和条件运算符。
-
作为独立 JavaScript 文件的导入。
JavaScript 代码存在环境限制:
-
如果此代码位于
somefile.qml内部,JavaScript 代码不能修改全局对象,但可以从somefile.js修改全局对象。 -
除了具有本地脚本变量的代码外,全局代码在缩减的作用域中运行。
-
this关键字仅在绑定属性中可用,在 QML 中未定义。
类型系统和 QML 文档
在 QML 中,类型可以在对象定义中使用 QML 语言本地化,通过 C++注册,或通过 QML 文档注册。这可以表示如下:
-
基本类型:
-
bool:true/false值。 -
double: 双精度小数。 -
enumeration: 命名值。 -
int: 整数。 -
list: QML 对象的列表。 -
real: 小数。 -
string: 文本字符串。 -
url: 通用资源定位符。 -
var: 通用属性。 -
JavaScript 类型:QML 引擎允许的任何 JavaScript 对象。
-
QML 对象类型:由 QML 提供的模块,例如
QtQuick模块。
一个以 QML 文档的语法规则编写的字符串表示的 QML 文档,具有.qml文件扩展名,并包含一个经过验证的结构。文档的结构通常分为两部分。第一部分是import部分,而第二部分是对象声明部分,由一个空行分隔。由于 QML 对网络是透明的,这使得可以从本地和远程路径导入 QML 文档。
QtQml 模块
与提供 UI 组件和功能的QtQuick模块相比,QtQml模块提供了一个使用 QML 开发应用程序的框架,并实现了语言和引擎基础设施。此模块提供了一个 API,用于通过自定义类型实现扩展 QML,并允许我们将 QML 与 JavaScript 和 C++集成。这里描述了一些通常与QtQml一起使用的类型。模块具有import语句:
import QtQml 2.0
这可以解释为 C++预处理器:
#include <QtQml>
让我们回顾一下QtQml包含的基础对象类型。
组件
QML 组件定义具有以下属性:
progress: 一个表示组件加载进度的实数值,范围从0.0到1.0。
status: 这是一个枚举,显示组件加载的状态。
url: 这是用于组件构造的统一资源定位符(URL)。
QtObject
此类型包含objectName属性:
objectName: 这是特定字符串的对象名称。
绑定
此类型用于创建属性绑定。此类型具有以下属性:
delayed: 这可以是true或false。如果是true,则绑定将被延迟。
property: 这可以是任何字符串,并指定要更新的属性的名称。
target: 这是需要更新的对象。
value: 这可以是任何对象或属性,并为目标对象和属性设置值。
when: 这可以是true或false,并在绑定活动时设置。表达式应返回true或false。
连接
此类型提供对信号的连接。这些是可用的属性:
enabled: 这可以是true或false。对于项目,连接和事件被启用。
ignoreUnknownSignals: 这可以是true或false,并允许我们忽略未知信号,例如错误。
target: 这是一个对象,也是信号的发射者。
定时器
此 QML 类型提供了触发动作的定时器。它具有以下属性:
interval: 这是一个整数,用于设置毫秒间隔(默认为1000毫秒)。
repeat: 这可以是true或false,如果此属性为true,则重复此触发器。
running: 这可以是true或false。如果属性为true,则启动定时器。
triggeredOnStart: 这可以是true或false。如果属性为true,则在定时器开始时启动触发器。
此外,QtQml 包含一个子模块 QtQml.Models,它定义了 QML 中的数据模型。
QML 中的样式
我们已经完成了对 QML 语法简介的简短介绍。让我们尝试实现一些对象的属性,以更好地可视化元素并改进它们的样式。
Item
最常用的由几乎所有几何可视化对象类型继承的 QML 类型是 Item。这是 QtQuick 中所有可视项的基础类型。在 QML 中使用的 import 语句如下:
import QtQuick 2.7
注意,QtQuick 的版本可能因你安装的 Qt 版本而异。
项类型的属性如下:
enabled:这可以是 true 或 false。项被启用以接收鼠标和键盘事件(默认为 true)。
x:这是一个设置此项在 x 轴上位置的 real 数值(默认为 0.0)。
y:这是一个设置此项在 y 轴上位置的 real 数值(默认为 0.0)。
z:这是一个设置兄弟项堆叠顺序的 real 数值。具有高于其他项的 z 值的项将覆盖其他项(默认为 0.0)。
width:这是一个设置此项宽度的 real 数值。
height:这是一个设置此项高度的 real 数值。
implicitWidth:这是一个设置此项自然宽度的 real 数值。
implicitHeight:这是一个设置此项自然高度的 real 数值。
opacity:这是一个设置此项不透明度的 real 数值。0.0 表示完全透明,1.0 表示完全不透明(默认为 1.0)。
parent:此(父项名称)设置此项的父项。
resources:这是此项的资源列表。
clip:这可以是 true 或 false,并允许此项剪切其自己的绘制。剪切将启用(默认为 false)。
rotation:这是一个 real 数值,将此项顺时针旋转一定角度(默认为 0)。
scale:这是一个 real 数值,是此项的缩放因子(默认为 1.0)。
smooth:这可以是 true 或 false。如果为 true,则将使用平滑采样。
state:此字符串设置此项当前状态的名称。
states:这是此项可能的州列表。
transform:这是应用于此项的变换列表。
transformOrigin:此 enumeration 设置缩放和旋转将转换此项的基点(默认为 Item.Center)。
transitions:这是此项的过渡列表。
visible:这可以是 true 或 false,并设置此项是否可见(默认为 true)。
visibleChildren:这是将可见的子项列表。
antialiasing:这可以是 true 或 false,并为此项提供抗锯齿。
activeFocus:这可以是 true 或 false,并设置此项是否具有活动焦点。
activeFocusOnTab: 这可以是 true 或 false,并设置项目是否将在标签焦点链中具有活动焦点(默认为 false)。
focus: 这可以是 true 或 false。如果为 true,当包含的 FocusScope 获得活动焦点时,它将获得活动焦点。
anchors.top: 这个 AnchorLine 是项目与此项目顶部位置之间的关系。
anchors.bottom: 这个 AnchorLine 是项目与此项目底部位置之间的关系。
anchors.left: 这个 AnchorLine 是项目与此项目左侧位置之间的关系。
anchors.right: 这个 AnchorLine 是项目与此项目右侧位置之间的关系。
anchors.horizontalCenter: 这个 AnchorLine 是项目与此项目水平中心位置之间的关系。
anchors.verticalCenter: 这个 AnchorLine 是项目与此项目垂直中心位置之间的关系。
anchors.baseline: 这个 AnchorLine 是此项目的文本假想线与另一个项目位置之间的关系。如果文本不存在,这将与 anchors.top 相同。
anchors.fill: 这个 Item 是设置一个项目的几何形状与另一个项目相同的锚点关系。
anchors.centerIn: 这个 Item 在设置此项目位置为指定 Item 中心位置的关系中。
anchors.margins: 这是一个设置相关项目锚点之间边距的 real 数值。
anchors.topMargin: 这是一个设置此项目与另一个项目之间顶部边距的 real 数值。
anchors.bottomMargin: 这是一个设置此项目与另一个项目之间底部边距的 real 数值。
anchors.leftMargin: 这是一个设置此项目与另一个项目之间左边距的 real 数值。
anchors.rightMargin: 这是一个设置此项目与另一个项目之间右边距的 real 数值。
anchors.horizontalCenterOffset: 这是一个设置相关项目水平中心位置偏移的 real 数值。
anchors.verticalCenterOffset: 这是一个设置相关项目垂直中心位置偏移的 real 数值。
anchors.baselineOffset: 这是一个设置文本假想线偏移的 real 数值。
anchors.alignWhenCentered: 这可以是 true 或 false,并将锚点居中以便对齐到整个像素(默认为 true)。
baselineOffset: 这个整数是项目基线在局部坐标中的位置。对于文本项,它是文本所在的假想线。对于非文本项,它是 0(默认为 0)。
children: 这是一个包含此项目子项的列表。
childrenRect.x: 这是一个 real 数值,是此项目子项的 x 轴坐标。
childrenRect.y: 这是一个 real 数值,是此项目子项的 y 轴坐标。
childrenRect.width: 这是一个real数字,是此项目子项的宽度。
childrenRect.height: 这是一个real数字,是此项目子项的高度。
data: 此列表允许我们在一个项目中混合视觉子项和资源。
layer.effect: 组件具有应用于层的效果(例如,ShaderEffect组件)。
layer.enabled: 这可以是true或false。如果为true,则允许此项目分层(默认为false)。
layer.format: 这个枚举定义了纹理的内部 OpenGL 格式。
layer.mipmap: 这可以是true或false。如果为true,则为纹理生成米普贴图。
layer.samplerName: 此字符串是效果的源纹理属性的名称。
layer.smooth: 这可以是true或false。如果为true,则平滑地转换层。
layer.sourceRect: 此Rectangle是应渲染到纹理中的此项目的矩形区域。
layer.textureMirroring: 此枚举设置 OpenGL 纹理的镜像方式(默认为ShaderEffectSource.MirrorVertically)。
layer.textureSize: 此size是层的纹理的像素大小。
layer.wrapMode: 此枚举是与纹理关联的 OpenGL 包装模式。
以下代码行部分解释了Item的功能。在qmls/目录下创建一个名为UItem.qml的文件,并添加以下代码:
main_item是此Item内部所有项目的父项目:
import QtQuick 2.7
Item {
id: main_item
anchors.fill: parent
anchors.margins: 20
此项目的id是main_item。此项目将具有与parent相似的大小,并具有20像素的边距。
- 将第一个项目添加到具有
id: main_item的Item中:
...
...
Item {
id: i1
x: 50
width: parent.width / 2
height: parent.height / 4
z: 1
opacity: 0.5
Rectangle {
id: r1
width: parent.width
height: parent.height
color: "#FF0000"
}
}
..
此Item描述了诸如z索引(此项目将覆盖索引较小的项目)、opacity(此项目将半透明)等属性。
- 将第二个项目添加到具有
id: main_item的Item中:
...
...
Item {
id: i2
parent: i1
y: i1.height
width: parent.width / 2
height: parent.height / 4
scale: 2
z: 2
opacity: 0.7
Rectangle {
id: r2
width: parent.width
height: parent.height
color: "#00FF00"
}
}
...
第二个项目具有parent和scale属性。parent属性为此项目设置parent,而scale属性设置大小,将是父项目大小的两倍。
- 将第三个项目添加到具有
id: main_item的Item中:
...
...
Item {
id: i3
anchors.centerIn: parent
y: i1.height + i2.height
width: parent.width / 2
height: parent.height / 4
rotation: 90
z: 0
opacity: 0.9
Rectangle {
id: r3
width: parent.width
height: parent.height
color: "#FFFF00"
}
}
...
第三项具有anchors.centerIn和rotation属性。anchors.centerIn属性将此项目设置为parent的中心,而rotation属性将此项目旋转90度。此项目几乎不透明。
- 然后,将第四个项目添加到
main_item:
...
...
Item {
id: i4
parent: r3
width: parent.width
height: parent.height
z: 1
rotation: 45
scale: 0.7
Rectangle {
id: r4
anchors.centerIn: parent
width: parent.width
height: parent.height
antialiasing: true
color: "#770077"
}
}
}
rotation属性将按顺时针方向旋转此项目45度,而scale因子将此项目的大小设置为父项目大小的 70%。已将antialiasing属性添加到此项目的矩形中,以获得最佳元素可视化性能。
- 要运行此文件,您可以使用 Qt Creator 或将以下行添加到
u_qml.qml文件中,在第一个矩形之后某处。将项目添加到 QML 应用程序中:
...
...
Uqmls.UItem {
visible: true
width: rect1.width
height: parent.height - rect1.height
y: rect1.height
}
...
...
主要项将是可见的,其width和height与rect1相关。这是结果:

Rectangle
Rectangle类型是在创建 QML 对象时常用的类型。Rectangle从Item类型继承。
使用Rectangle QML 类型的import语句如下:
import QtQuick 2.7
Rectangle的属性如下:
antialiasing: 这可以是true或false。如果矩形应该使用抗锯齿,则提供此选项。
border.width: 这是一个int类型的数字,表示矩形的边框宽度。
border.color: 这是矩形边框的颜色。
color: 这是矩形的颜色。
gradient: 这是矩形的渐变颜色。
radius: 这是矩形项的半径。
RectangularGlow
这用于创建一个具有发光效果的模糊和着色矩形。以下是导入语句:
import QtGraphicalEffects 1.0
RectangularGlow的属性如下:
color: 这是用于发光的颜色。
cornerRadius: 这是一个用于绘制带圆角的发光的real类型的数字。
glowRadius: 这是一个real类型的数字,用于设置发光到达的像素半径。
spread: 这是一个real类型的数字,用于设置源边缘附近发光颜色的强度。
cached: 这可以是true或false。它允许效果的输出像素被缓存以提高性能。
为了演示这个效果,在qmls/目录中创建一个名为URectGlow.qml的文件,并执行以下步骤:
- 将父矩形和矩形发光添加到
URectGlow.qml文件中:
import QtQuick 2.7
import QtGraphicalEffects 1.0
Rectangle {
property color glowcolor
property color txglow
RectangularGlow {
id: rglow
anchors.fill: rectglow
glowRadius: 10
spread: 0.1
color: glowcolor
cornerRadius: rectglow.radius + glowRadius
}
此代码导入图形效果并添加自定义属性glowcolor和txglow。glowcolor属性用于指定发光颜色,而txglow用于文本发光的颜色。
- 然后,在
RectangularGlow之后添加中心矩形:
Rectangle {
id: rectglow
color: parent.color
anchors.centerIn: parent
width: parent.width / 1.5
height: parent.height / 1.5
radius: 14
矩形将具有与父矩形颜色相似的发光效果。设置矩形角落的半径。
- 将
Text和Glow类型添加到中心矩形:
Text {
id: txt1
anchors.centerIn: parent
text: "PUSH"
font.family: "Helvetica"
font.pixelSize: parent.width / 8
font.weight: Font.Medium
font.letterSpacing: 2
color: parent.color
}
Glow {
anchors.fill: txt1
radius: 7
samples: 17
color: txglow
source: txt1
}
}
}
上述代码将Text和Glow QML 类型添加到中心矩形中。Text用于在矩形上显示文本,而Glow用于使矩形内的文本发光。
渐变
渐变用于更好地可视化对象。它们提供的颜色比使用简单的颜色属性更有效。
梯度
这个 QML 类型为元素提供渐变颜色。以下是import语句:
import QtQuick 2.7
它有一个名为stops的属性,提供了渐变停止点的列表。你可以通过使用GradientStop来实现这一点。
GradientStop
这个类型定义了在渐变中的位置的颜色。以下是import语句:
import QtQuick 2.7
属性如下:
color: 这是指定渐变颜色的颜色。它允许使用命名、十六进制和 RGBA 颜色。
position: 这是渐变中颜色的位置,范围从0.0到1.0。
在App/qmls/目录内创建一个名为gradients/的目录,并在其中创建一个名为UGradient1.qml的文件。然后,使用Gradient和GradientStop类型添加渐变颜色:
import QtQuick 2.7
Gradient {
GradientStop {
position: 0.0;
color: "red";
}
GradientStop {
position: 0.27;
color: "#AAFF00";
}
GradientStop {
position: 0.534;
color: Qt.rgba(0.95,0,0,1);
}
GradientStop {
position: 0.7147;
color: "yellow";
}
GradientStop {
position: 1.0;
color: Qt.rgba(1,0,0,1);
}
}
第一个渐变停止和最后一个渐变停止的position属性必须分别等于0.0和1.0。在这两个位置之间的所有渐变停止实现渐变颜色。可以使用命名、RGB 和 RGBA 颜色。
现在,你只需要通过向矩形添加渐变颜色来更改UCircle.qml文件:
import QtQuick 2.7
import "gradients" as UG
Rectangle {
radius: width * 0.5
antialiasing: true
gradient: UG.UGradient1 {}
}
创建的圆将具有渐变颜色而不是简单的颜色。
LinearGradient
此渐变对象提供了一些扩展功能。使用LinearGradient,颜色从起点开始,到终点结束。以下是所需的import语句:
import QtGraphicalEffects 1.0
这些是它所接受的属性:
start:颜色在位置0.0处渲染的像素起点(默认为Qt.point(0, 0))。
end:颜色在位置1.0处渲染的像素终点(默认为Qt.point(0, height))。
gradient:渐变类型,包含两种或更多颜色的渐变。
source:将要填充渐变的项(例如图像或 QML 类型)。
cached:这可以是true或false。它允许效果的输出像素被缓存以提高性能。
这里有一个例子。在qmls/目录下创建一个名为URectLG.qml的文件,并将以下代码添加到其中:
import QtQuick 2.7
import QtGraphicalEffects 1.0
import "gradients" as UG
Rectangle {
antialiasing: true
radius: width * 0.5
LinearGradient {
anchors.fill: parent
start: Qt.point(0, 0)
end: Qt.point(parent.height/2, parent.height/2)
source: parent
cached: true
gradient: UG.UGradient1 {}
}
}
在线性渐变中,使用起点和终点作为 Qt 点。渐变只能用视觉类型对象定义,例如矩形,可以无缝混合两种或多种颜色。
RadialGradient
此类型提供径向渐变。以下import语句用于径向渐变:
import QtGraphicalEffects 1.0
这些是属性:
angle:这是一个real数,是围绕中心点旋转的渐变角度(默认为0.0)。
gradient:这是一个渐变类型的渐变,包含两种或更多颜色。
source:这是一个将要填充渐变的项。
horizontalRadius:这是一个real数,即渐变的形状和大小。
verticalRadius:这是一个real数,即渐变的形状和大小。
horizontalOffset:这是一个real数,即从渐变中心点到项中心的像素偏移(默认为0.0)。
verticalOffset:这是一个real数,即从渐变中心点到项中心的像素偏移(默认为0.0)。
cached:这可以是true或false。它允许效果的输出像素被缓存以提高性能。
这里有一个径向渐变的例子。在qmls/目录内创建一个名为URectRG.qml的文件,并添加以下代码:
import QtQuick 2.7
import QtGraphicalEffects 1.0
import "gradients" as UG
Rectangle {
antialiasing: true
radius: width * 0.5
RadialGradient {
anchors.fill: parent
angle: 27
horizontalRadius: parent.width / 2
verticalRadius: parent.height / 2
horizontalOffset: 3
verticalOffset: 3
source: parent
cached: false
gradient: UG.UGradient1 {}
}
}
此径向渐变的源是一个父矩形。我们已经设置了围绕中心的angle旋转。
ConicalGradient
此类型提供圆锥形梯度。此类型的import语句如下:
import QtGraphicalEffects 1.0
此类型的属性如下:
angle:这是一个实数,用于设置中心点周围梯度的角度(默认值为0.0)。
gradient:Gradient类型的梯度,包含两种或更多颜色。
source:将要填充梯度的项目。
horizontalOffset:这是一个实数,即梯度中心点相对于项目中心的像素偏移量(默认值为0.0)。
verticalOffset:这是一个实数,即梯度中心点相对于项目中心的像素偏移量(默认值为0.0)。
cached:这可以是true或false。它允许缓存效果的输出像素以改善性能。
这里有一个示例。在qmls/目录内创建一个名为URectCG.qml的文件,并添加以下代码:
import QtQuick 2.7
import QtGraphicalEffects 1.0
import "gradients" as UG
Rectangle {
antialiasing: true
radius: width * 0.5.
ConicalGradient {
anchors.fill: parent
angle: 1
horizontalOffset: 7
verticalOffset: 5
source: parent
cached: false
gradient: UG.UGradient1 {}
}
}
颜色的梯度将是圆锥形。source也是父矩形。
完成示例
为了完成本节中的示例,让我们将它们组合成一个网格并查看结果。为此,在u_qml.qml文件中rect1之后添加网格:
- 添加项目的网格定位机制:
...
...
Grid {
visible: true
id: grid1
columns: 2
spacing: 20
padding: 20
width: rect1.width
height: parent.height - rect1.height
y: rect1.height
Uqmls.UCircle {
id: circle1
width: (parent.width / 2 - (parent.spacing * 2)) + 10
height: width
}
...
Uqmls.URectGlow {
id: rectg1
width: (parent.width / 2 - (parent.spacing * 2)) + 10
height: width
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(0.007, 1, 1, 1);
txglow: Qt.rgba(0.007, 0.7, 0.7, 1);
}
...
}
...
我们已经使用Grid类型来排列项目。在这里,我们创建了四个具有梯度如UCircle、URectLG、URectRG和URectCG的圆,以及四个可以添加的URectGlow项目。
- 在创建项目的Item部分,我们需要将
visible属性更改为false:
...
...
Uqmls.UItem {
visible: false
...
...
添加这些行后,梯度元素将可见,而之前创建的项目将不可见。带有一些背景色更改的完整文件可在github.com/PacktPublishing/Hands-On-QT-for-Python-developers找到。
如果我们点击应用程序窗口的右上角,我们将看到以下结果:

我们已经简要介绍了使用 QML 进行样式设置。在下一章中,我们将继续学习 Qt Quick,并学习重要的定位工具,例如布局。
使用 QML 创建动画
Qt Quick 是一个用于使用 QML 创建用户界面的标准库,它为您提供了实现动画的能力。这种动画可以通过多种方式实现,例如状态、转换和动画属性变化。动画也可以通过其他与动画相关的技术实现。
状态和转换对象
这种使用 QML 创建动画的方式使用State对象来声明对象的当前状态,以及使用Transition对象来声明动画过程中的状态变化属性。
这种方法可以用以下几行来描述:
Item {
states: [ State { name: "state1"} ]
transitions: [ Transition {}]
}
Item具有states和transitions属性。states有一个State对象,而transitions有一个Transition对象的列表。
State
作为QtQuick模块的一部分,QML 的State类型提供了一组与对象和属性配置相关的更改。它有以下import语句:
import QtQuick 2.7
这些是其属性:
name:string(状态的名称)。
changes:列表(应用于状态的更改)。
extend:string(状态的名称);状态扩展为状态。
when:这可以是true或false,并设置状态何时应用。此属性的值应为返回布尔值的对象。例如,如果MouseArea.pressed被按下,则返回true。
PropertyChanges
PropertyChanges用于在状态中定义属性值。这允许我们定义目标对象的新属性。import语句如下:
import QtQuick 2.7
它具有以下属性:
target:需要更改属性的对象。
explicit:可以是true或false。它提供属性的显式绑定(默认为false)。
restoreEntryValues:可以是true或false。如果是true,离开状态时应恢复之前的值。
以下是一个示例。打开UItem.qml文件,并将此MouseArea添加到具有id: r1的矩形中,如下所示:
- 将
id: i1的项状态添加到鼠标区域的onClicked信号处理程序:
...
...
...
...
MouseArea {
anchors.fill: parent
onClicked: {i1.state == 'state1' ?;
i1.state = '' : i1.state = 'state1';}
}
...
...
...
当MouseArea被点击时,Item的状态将发生变化。
- 将状态和转换属性添加到
Item的底部,其中id: i1:
...
...
...
states: [
State {
name: "state1"
PropertyChanges { target: i1; x: 140 }
}
]
transitions: [
Transition {
NumberAnimation { properties: "x, y" }
}
]
...
...
在states属性中,已添加具有name和PropertyChanges的State类型,它将被用于目标项的x轴。transitions属性实现动画。
AnchorChanges
此类型用于需要更改对象State中项的锚点时。此类型的import语句如下:
import QtQuick 2.7
以下属性可用:
target:要更改锚的项。
anchors.left:此AnchorLine将修改左锚。
anchors.right:此AnchorLine将修改右锚。
anchors.horizontalCenter:此AnchorLine将修改水平中心锚的位置关系。
anchors.top:此AnchorLine将修改顶部锚。
anchors.bottom:此AnchorLine将修改底部锚。
anchors.verticalCenter:此AnchorLine将修改垂直中心锚的位置关系。
anchors.baseline:此AnchorLine将修改基线锚。
StateChangeScript
StateChangeScript QML 类型用于在状态中运行脚本。import语句如下:
import QtQuick 2.7
它具有以下属性:
name:这是一个字符串,是脚本的名称。与ScriptAction一起使用以定位特定的脚本。
script:将要使用的脚本,例如函数。
StateGroup
使用此类型,QML 为非项类型提供了支持。import语句与之前相同:
import QtQuick 2.7
它具有以下属性:
state:这是一个string。它是此状态组的名称。
states:这是一个列表,定义了与状态组相关的状态列表。
transitions:这是一个列表。它提供了状态组的过渡对象列表。
QtQml模块还提供了state类型,它是声明性状态机框架的一部分。这是import语句:
import QtQml.StateMachine 1.0
它具有以下属性:
childMode:这是一个枚举,指定了如何处理状态。它可以是指QState.ExclusiveStates(状态是互斥的)或QState.ParallelStates(状态是并行的)。
errorState:这是QAbstractState的错误状态。
initialState:这是QAbstractState的初始状态。
此类型与 QML 语言基础设施相关。
过渡
此 QML 类型用于实现状态变化的动画并定义动画过渡。import语句如下:
import QtQuick 2.7
它具有以下属性:
animations:这是一个动画列表,以列表形式提供。
enabled:这可以是true或false(默认为true),表示过渡是否启用。
running:这可以是true或false,表示过渡是否正在运行。
from:这是一个string,表示过渡是从这些状态变化开始的。
to:这是一个string,表示过渡是到这些状态变化的。
reversible:这可以是true或false。如果是true,则在状态变化反转时自动应用过渡。
动画属性变化
实现动画的另一种方法是使用行为。
行为
此 QML 类型提供默认动画,如果属性值更改,则应用此动画。import语句如下:
import QtQuick 2.7
它具有以下属性:
animation:这设置了当行为被触发时运行的动画。
enabled:这可以是true或false。这启用了类型以供使用(默认为true)。
语法如下:
Behavior on width {
Animation {}
}
在这里,构造使用的是width属性的Behavior。动画将根据宽度的行为运行。
打开UItem.qml文件,并将MouseArea和Behavior类型添加到具有id: r2的矩形中:
...
...
...
...
MouseArea {
anchors.fill: parent
onClicked: {parent.y == 140 ?
parent.y = 270 : parent.y = 140}
}
Behavior on y {
NumberAnimation {
duration: 7000
easing.type: Easing.OutInElastic
}
}
...
...
...
如果点击MouseArea,绿色矩形将移动。我们已经在y轴上设置了Behavior,这将使用一个动画,绿色矩形在七秒内落下,并且缓动曲线设置为弹性(指数衰减的正弦波)。
动画类型
QtQuick提供了以下类型来实现动画。
动画
这是所有 QML 动画的基类型。它具有以下import语句:
import QtQuick 2.7
它具有以下属性:
alwaysRunToEnd: 这可以是true或false。如果动画被停止,动画循环应该完成。
loops: 这是一个int,设置动画将播放多少次。
paused: 这是一个布尔值。如果为true,则动画将暂停。
running: 这是一个布尔值。如果为true,则动画正在运行。
以下信号可用:
started(): 当动画开始时发出此信号。
stopped(): 当动画停止时发出此信号。
以下方法可用:
complete(): 跳转到最终属性值。
pause(): 暂停动画。
restart(): 重新启动动画。
resume(): 开始暂停的动画。
start(): 开始动画。
stop(): 停止动画。
AnimationController
这允许手动控制动画。这是必需的import语句:
import QtQuick 2.7
它具有以下属性:
animation: 要控制Animation。
progress: 动画在0.0和1.0之间进行。
PropertyAnimation
这是一个用于动画属性值变化的实用类型。import语句如下:
import QtQuick 2.7
它具有以下属性:
duration: 这个int是动画的持续时间(以毫秒为单位)。
target: 这个对象设置了需要动画化的项目。
targets: 这个列表设置了需要动画化的项目。
property: 这个string设置了要动画化的属性。
properties: 这个string设置了要动画化的属性。
from: 这是动画的起始值。
to: 这是动画的结束值。
exclude: 这是一个不会进行动画的对象列表。
easing.type: 这是一个枚举,是用于动画的缓动曲线类型。
easing.amplitude: 这是缓动曲线的振幅。
easing.overshoot: 这是缓动曲线的超出量。
easing.period: 这是缓动曲线的周期。
easing.bezierCurve: 如果缓动类型是Easing.Bezier,则适用此列表。它是一个包含定义从(0,0)到(1,1)曲线的三点组的real数列表——[x1, y1, x2, y2, endx, endy]。最后一个点必须是(1,1)。
NumberAnimation
这用于动画数值属性。使用以下import语句:
import QtQuick 2.7
它具有以下属性:
from: 这是一个real数,是动画的起始值。
to: 这是一个real数,是动画的结束值。
SequentialAnimation
此动画用于依次运行多个动画。这是import语句:
import QtQuick 2.7
这里是一个语法示例:
SequentialAnimation {
Animation {}
Animation {}
}
// or:
SequentialAnimation on width {
Animation {}
Animation {}
}
这实现了指定动画的顺序动画。
ParallelAnimation
与SequentialAnimation类似,此类型用于同时运行多个动画,但它们将同时运行。使用以下import语句:
import QtQuick 2.7
这里是一个语法示例:
ParallelAnimation {
Animation {}
Animation {}
}
这实现了指定动画的并行动画。
PauseAnimation
此类型用于在动画之间设置暂停。使用以下import语句:
import QtQuick 2.7
它有一个属性:
duration: 这是一个设置动画之间暂停时间的int值,单位为毫秒。
ColorAnimation
这是一个用于在颜色值更改时应用的专用属性动画。你需要以下import语句:
import QtQuick 2.7
它具有以下属性:
from: 这是动画开始时的颜色。
to: 这是动画结束时颜色的颜色。
CoordinateAnimation
这是一个在两个坐标之间实现的地理坐标属性动画。你需要使用以下import语句:
import QtPositioning 5.2
它具有以下属性:
direction: 这是一个表示经度动画方向的enumeration。
from: 这是动画开始时的坐标。
to: 这是动画结束时的坐标。
RotationAnimation
此类型用于在动画期间控制旋转方向。使用以下import语句:
import QtQuick 2.7
它具有以下属性:
direction: 这是一个表示旋转方向的enumeration(默认为RotationAnimation.Numerical)。
from: 这个real数字是动画旋转的起始值。
to: 这是一个表示动画旋转结束值的real数字。
AnchorAnimation
此类型用于动画锚点。你需要以下import语句:
import QtQuick 2.7
它具有以下属性:
targets: 这是一个要重新锚定的项目列表。
duration: 这是一个表示动画持续时间的int值,单位为毫秒。
easing.type: 这个enumeration是用于动画的缓动曲线类型。
easing.amplitude: 这个real数字是缓动曲线的振幅。
easing.overshoot: 这个real类型的数字是缓动曲线的过冲量。
easing.period: 这个real数字是缓动曲线的周期。
这些类型不是QtQuick中可用的所有动画工具的完整列表。
动画示例
现在,我们需要练习使用我们查看过的动画类型:
- 打开
UItem.qml文件,并在具有id: r3的矩形底部添加以下行:
...
...
...
...
SequentialAnimation on x {
id: sa1
running: false
loops: Animation.Infinite
NumberAnimation {
from: 140
to: 270
duration: 7000
easing.type: Easing.OutInElastic
}
NumberAnimation {
from: 270
to: 140
duration: 7000
easing.type: Easing.OutInElastic
}
PauseAnimation { duration: 140 }
}
MouseArea {
anchors.fill: parent
onClicked: sa1.running = true
}
...
...
...
顺序动画用于两个NumberAnimation实现。动画将改变矩形的某些位置,并使用PauseAnimation类型指定一些暂停。
- 将以下动画添加到具有
id: r4的矩形底部:
...
...
...
...
ParallelAnimation {
id: sa2
running: false
loops: Animation.Infinite
PropertyAnimation {
target: r4
property: "rotation"
from: 0
to: 360
duration: 7000
easing.type: Easing.OutInElastic
}
PropertyAnimation {
target: r1
property: "rotation"
from: 0
to: 360
duration: 7000
easing.type: Easing.InQuart
}
}
MouseArea {
anchors.fill: parent
onClicked: sa2.running = true
}
...
...
...
并行动画用于两个PropertyAnimation实现。这些动画将旋转矩形。要查看这些动画,我们需要在u_qml.qml文件中对项目的可见属性进行一些更改,并将Grid的可见属性设置为false。
- 将动画项目的
visible属性设置为true:
...
...
Uqmls.UItem {
visible: true
...
...
项组将可见。
- 将
Grid的visible属性设置为false:
...
...
Grid {
visible: false
...
...
包含项目的网格将不可见。我们已经成功实现了多种不同方法的几个动画。结果如下:

摘要
本章已涵盖 QML 及其基本语法。当创建 GUI 时,QML 非常有用。Qt 提供了制作 GUI 的工具,例如 QtQml 和 QtQuick 模块。QtQml 更多的是用于处理语言和 QML 引擎基础设施的工具,但 QtQuick 模块提供了帮助我们构建具有广泛功能和可视化工具的 GUI 的库。语言和 QML 引擎基础设施代表了库的核心功能,包括信号构建、属性绑定以及使用 Python 运行 QML 应用程序等元素。本章中的几乎所有示例都使用了 QtQuick 模块来实现 QML 应用的视觉组件和功能。
下一章将专注于 QtQuick 模块及其子模块,重点介绍控制元素、定位、布局和可视化。
第三章:Qt Quick 库
在本章中,我们将继续我们的 QML GUI 实现,并描述更详细的 Qt Quick 库——在 Qt 中处理 QML 的主要工具。通过使用 Qt Quick 模块,设计师和开发者可以轻松地在 QML 中构建流畅的动画 UI,并可以选择将这些 UI 连接到任何后端 C++库。Qt Quick 允许开发者创建高性能、流畅动画和视觉吸引力的应用程序。
在本章中,我们将介绍以下主题:
-
Qt Quick 模块简介
-
窗口子模块
-
控件
-
布局
Qt Quick 模块简介
在 Qt 框架中,Qt Quick 模块允许我们使用用户创建的应用程序与 QML 一起工作和实现。Qt Quick 是 Qt 框架中用于处理 UI 和 QML 基础设施的主要模块。此模块扩展了 Qt 的功能并添加了一些功能。
基本类型
除了默认的 QML 类型外,Qt Quick 模块还提供了以下类型:
-
date: 日期值 -
point: 具有 x 和 y 属性的值 -
rect: 具有 x、y、width 和 height 属性的值 -
size: 具有 width 和 height 属性的值 -
color: ARGB 颜色值 -
font: 具有 QFont 属性的字体值 -
matrix4x4: 一个 4 行 4 列的矩阵 -
quaternion: 具有 x、y 和 z 属性的标量 -
vector2d: 具有 x 和 y 属性的 2D 向量 -
vector3d: 具有 x、y 和 z 属性的 3D 向量 -
vector4d: 具有 x、y、z 和 w 属性的 4D 向量
Qt Quick 类型
在第二章“QML 概述”中,我们描述了创建 GUI 最流行的 Qt Quick 类型。这些类型的完整列表可在官方文档中找到:doc.qt.io/qt-5.9/qtquick-qmlmodule.html。让我们看看一些我们尚未介绍的最有用的类型:
-
Canvas: 这提供了一个 2D 画布项,可以使用 JavaScript 进行绘图,以创建图形和其他视觉对象。 -
Context2D: 这为Canvas项上的形状提供 2D 上下文。 -
AnimatedImage: 这播放存储为一系列图像的动画,其中包含一系列帧。 -
Drag: 这指定了项目的拖放事件。 -
DropArea: 这指定了区域内的拖放处理。 -
KeyEvent: 这提供了关于按键事件的信息。 -
MouseEvent: 这允许你处理鼠标事件。 -
WheelEvent: 鼠标滚轮事件。 -
Flickable: 滑动表面。 -
Flipable: 翻转表面。 -
FocusScope: 明确创建一个焦点域。 -
GridView: 项目的模型网格视图。 -
Image: 显示图像。 -
ListView: 模型列表视图。 -
Loader: 从 URL 动态加载子树。 -
MultiPointTouchArea: 用于处理多个触摸点。 -
Column: 用于在列中定位项目。 -
Flow: 用于定位页面上的项目,如文字。 -
Positioner: 显示项目存在位置的附加属性。 -
Row: 用于以行形式定位项目。 -
Repeater: 用于创建基于项目的多个组件。 -
ShaderEffect: 用于向矩形添加着色器。 -
GridMesh: 一个顶点排列成网格的网格。 -
TextEdit: 一个多行文本字段。 -
Matrix4x4: 项目的 4 x 4 变换矩阵。 -
Rotation: 用于旋转一个项目。 -
Scale: 项目将进行缩放。 -
Translate: 用于移动一个项目,而不改变其x或y属性。 -
FontLoader: 用于通过名称或 URL 加载字体。 -
FontMetrics: 字体的度量信息。
Qt Quick 子模块
Qt Quick 库包括包含类型的附加模块。其中一些将在本章中详细描述。以下是子模块列表:
-
XmlListModel: 提供从 XML 数据创建模型的数据类型。 -
LocalStorage: 一个用于 SQLite 数据库的 JavaScript 接口。 -
Particles: QML 应用程序的粒子系统。 -
Window: 用于创建顶级窗口和访问屏幕信息的数据类型。 -
Dialogs: 用于创建和交互系统对话框。 -
Controls: 可重用的 UI 组件(如按钮、复选框、标签等)。 -
Layouts: 用于排列项目。 -
Tests: 用于测试 QML 应用程序。
在本章中,我们将重点关注在 GUI 开发中使用的 重要类型和子模块。要获取完整信息,建议您访问 Qt Quick 文档(doc.qt.io/qt-5/qtquick-index.html)。在第二章“QML 概述”中,一些类型和模块通过示例实现,并进行了详细描述。让我们在这里做同样的事情。
窗口模块
此模块提供在创建顶级窗口、屏幕信息和窗口事件(例如窗口关闭时)时可以使用的类型。要使用此模块,请使用以下import语句:
import QtQuick.Window 2.2
我们将在以下章节中介绍这些类型。
屏幕
此类型提供有关显示的屏幕、项目或窗口的信息。属性如下:
desktopAvailableHeight: 这个整数表示桌面分辨率的可用高度(以像素为单位)。
desktopAvailableWidth: 这个整数表示桌面分辨率的可用宽度(以像素为单位)。
devicePixelRatio: 这是一个real数,表示物理像素和设备无关像素的比率。在正常显示中值为1.0,在苹果的视网膜显示中为2.0。
width: 这个整数表示屏幕的宽度(以像素为单位)。
height: 这个整数表示屏幕的高度(以像素为单位)。
name: 这个字符串是屏幕的名称。
orientation: 这是屏幕的方向(使用加速度计)。
orientationUpdateMask: 这包含方向的更新掩码。
primaryOrientation: 屏幕的主要方向可以是Qt.PortraitOrientation或Qt.LandscapeOrientation,具体取决于屏幕的高度和宽度。
pixelDensity: 这个real数字是每毫米的物理像素数。
virtualX: 这个整数是屏幕与虚拟桌面相关的x坐标。
virtualY: 这个整数是屏幕与虚拟桌面相关的y坐标。
以下方法可用:
angleBetween(a, b): 这返回a(第一个参数)和b(第二个参数)角度之间的旋转角度(以度为单位)。
让我们创建一个大小取决于设备屏幕分辨率的 QML 应用程序。为此,打开u_qml.qml文件,并使用以下行将UQml.Window的宽度和高度属性更改为屏幕类型值:
...
UQml.Window {
...
width: UQml.Screen.desktopAvailableWidth
height: UQml.Screen.desktopAvailableHeight
...
...
应用程序的窗口将具有width和height属性,这些属性适用于正在使用的设备。
CloseEvent
此类型通知您,窗口即将由窗口系统关闭。它具有以下属性:
accepted: 这可以是true或false,并允许用户关闭窗口(默认为true)。
Window
这为 GUI 应用程序创建了一个新的顶级窗口,该窗口可以包含元素和项目。此类型可用的属性如下:
width: 这个整数设置窗口的像素宽度。
height: 这个整数设置窗口的像素高度。
maximumWidth: 这个整数设置窗口将可用的最大宽度。
maximumHeight: 这个整数设置窗口将可用的最大高度。
minimumWidth: 这个整数设置窗口将可用的最小宽度。
minimumHeight: 这个整数设置窗口将可用的最小高度。
x: 这个整数是窗口在x轴上的位置。
y: 这个整数是窗口在y轴上的位置。
opacity: 这个real数字设置窗口的不透明度。值范围从0.0到1.0,其中0.0是完全透明的,1.0是完全不透明的。
title: 这个string设置窗口的标题。
visible: 这可以是true或false。如果是true,则窗口将是可见的;如果是false,则窗口将不可见(默认为true)。
visibility**: **这设置窗口的屏幕占用状态为normal、minimized、maximized或fullscreen。
color: 这设置窗口的背景颜色。
modality: 这会将窗口设置为模态(默认为QtCore.Qt.NonModal)。
screen: 这设置与此窗口关联的窗口。
active: 这可以是true或false,并设置窗口的状态。
activeFocusItem: 这是当前具有活动焦点的项目;如果没有项目具有活动焦点,则为 null。
contentItem: 这是场景的无形根Item。
contentOrientation: 这是对窗口管理器的额外内容的提示。
data: 这是一个列表,允许我们混合视觉对象、资源和其他窗口。
flags: 这些是此窗口可用的标志。
窗口类型提供了以下属性:
Window.window: Window类型 - 用于项目的窗口。
Window.width: 此整数是项目窗口的宽度。
Window.height: 此整数是项目窗口的高度。
Window.visibility: 此窗口将在窗口系统中显示,例如normal、fullscreen等。
Window.active: 这可以是true或false,表示窗口是否处于活动状态。
Window.activeFocusItem: 这显示当前哪个项目具有活动焦点。
Window.contentItem: 这是场景的无形根项目。
此类型有一个信号:
closing(CloseEvent close): 当窗口尝试关闭时发出。
类型还具有以下方法:
alert(int): 引发一个警告。
close(): 关闭窗口。
hide(): 隐藏窗口。
lower(): 降低窗口。
raise(): 提升窗口。
requestActivate(): 请求窗口被激活。
show(): 显示窗口。
showFullScreen(): 以全屏模式显示窗口。
showMaximized(): 以最大化模式显示窗口。
showMinimized(): 以最小化模式显示窗口。
showNormal(): 以正常模式显示窗口。
我们可以在UQml.Window部分的u_qml.qml文件中尝试更改/添加属性,并查看结果。
Controls
QtQuick.Controls模块允许我们使用一组可重用的 UI 元素来构建应用程序的功能。您需要以下import语句才能使用此模块的类型:
import QtQuick.Controls 1.4
在下一节中,我们将介绍此模块提供的类型。
ApplicationWindow
此类型实现了一个具有以下属性的简单顶级应用程序窗口:
contentItem: 这是ToolBar和StatusBar之间的区域。
menuBar: 这设置应用程序窗口的菜单栏。
toolBar: 这设置应用程序的工具栏。
statusBar: 此项目设置状态栏。
style: 此组件用于设置应用程序的样式。
让我们看看以下示例:
- 在
qmls/目录中创建一个名为UAppwin.qml的文件,并添加以下行:
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.2 as SZ
import QtQuick.Layouts 1.3
import "bars" as Bars
import "." as Qmls
import "gradients" as SApp
ApplicationWindow {
width: SZ.Screen.desktopAvailableWidth / 2
height: SZ.Screen.desktopAvailableHeight / 2
title: "QML Application"
menuBar: Bars.MBar {}
toolBar: Bars.TBar {}
...
应用程序窗口的宽度和高度将取决于设备的分辨率。此外,在qmls/文件夹内创建的bars/目录将用于导入此应用程序的菜单和状态栏。
- 将条带到应用程序窗口的底部添加:
...
...
Bars.TaBar {
id: tabar1
width: parent.width
}
...
标签栏的id和应用程序窗口的width被指定。
- 然后,添加带有
UAppItems的StackLayout类:
...
...
StackLayout {
id: sl1
width: tabar1.width
height: tabar1.height
currentIndex: tabar1.currentIndex
Qmls.UAppItems {
width: tabar1.width
height: tabar1.height
}
}
这将添加用于堆叠布局表示的应用程序项目。
- 在
UAppwin.qml文件的底部添加应用程序窗口的状态栏:
...
...
statusBar: StatusBar {
anchors.fill: parent
Label { text: "Reading..."; color: "red" }
style: StatusBarStyle {
background: Rectangle {
anchors.fill: parent
SApp.UGradientWin {}
}
}
}
}
StatusBar类使用Label进行文本和style进行渐变颜色。
现在,我们需要在qmls/目录内创建一个名为bars/的目录,该目录将用于应用程序窗口的元素,例如标签栏、菜单和状态栏。让我们执行以下步骤:
- 在
bars/文件夹中创建一个名为MBar.qml的文件,并包含以下行:
import QtQuick.Controls 1.4
MenuBar {
Menu {
title: "File"
MenuItem { text: "New" }
MenuItem { text: "Open" }
MenuItem { text: "Save" }
MenuItem { text: "Save as" }
}
Menu {
title: "Edit"
MenuItem { text: "Cut" }
MenuItem { text: "Copy" }
MenuItem { text: "Paste" }
}
Menu {
title: "Tools"
MenuItem { text: "Tool # 1" }
MenuItem { text: "Tool # 2" }
MenuItem { text: "Tool # 3" }
}
}
对于每个菜单部分,我们需要添加带有文本的MenuItem:
- 在
bars/目录内创建一个名为TBar.qml的文件,用于应用程序的工具栏:
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
ToolBar {
RowLayout {
anchors.fill: parent
ToolButton {
iconSource: "Icons/python1.png"
}
ToolButton {
iconSource: "Icons/python2.png"
}
ToolButton {
iconSource: "Icons/Aiconda.png"
}
Item { Layout.fillWidth: true }
}
}
对于每个工具栏项目,使用Icons/文件夹中可用的图标创建一个工具按钮,该文件夹位于bars/目录中。工具按钮以行布局排列。
- 在
bars/目录内的TaBar.qml文件中创建中心元素,或TabBar:
import QtQuick 2.7
import QtQuick.Controls 2.2
TabBar {
anchors.fill: parent
Repeater {
model: ["Actions", "Views", "Models"]
TabButton {
text: modelData
}
}
}
此TabBar将在应用程序中使用几个标签。这些标签添加在model属性中。每个标签使用带有模型数据文本的标签按钮。Repeater类型用于重复TabButton类型以重复模型中的每个元素。为了使用此标签栏与我们的应用程序,我们需要添加一些对象,例如项目、图像、视频和动画。
- 在
qmls/目录内创建一个名为UAppItems.qml的文件(类似于UItems.qml),以实现带有应用程序窗口的动画对象:
import QtQuick 2.7
import QtQuick.Layouts 1.3
import "." as Qmls
GridLayout {
anchors.centerIn: parent
columns: 3
...
GridLayout定位项目。
- 将第一个发光矩形添加到
GridLayout的底部:
...
...
Qmls.URectGlow {
id: rg1
Layout.leftMargin: parent.width / 100
Layout.rightMargin: parent.width / 100
Layout.topMargin: parent.height / 4
Layout.bottomMargin: parent.height / 12
Layout.fillWidth: true
Layout.fillHeight: true
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(0.95, 0, 0, 1);
txglow: Qt.rgba(0.77, 0, 0, 1);
txtext: "PUSH"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
signal acolored(color ucolor)
...
...
在此矩形中,指定了每侧边距的布局属性。这将用于元素之间的空间。
- 将
function添加到第一个矩形:
...
...
...
function onAcolor(ucolor) {
if (ucolor==Qt.rgba(0.95, 0, 0, 1)) {
return [Qt.rgba(0.2, 0.2, 0.2, 1), 0.5,
Qt.rgba(0, 0.07, 0.14, 1), 0.5,
Qt.rgba(0, 0.07, 0.14, 1)];
} else {
return [Qt.rgba(0.95, 0, 0, 1), 10,
Qt.rgba(0, 0.07, 0.14, 1), 0.1,
Qt.rgba(0.77, 0, 0, 1)];
};
}
...
...
此函数返回一个颜色列表,取决于作为参数传递的颜色。
- 将处理程序和
MouseArea添加到第一个网格布局的元素:
...
...
...
onAcolored: {
var acol = onAcolor(rg1.glowcolor)
rg1.glowcolor = acol[0];
rg1.glowr = acol[1];
rg1.color = acol[2];
rg1.spr = acol[3];
rg1.txglow = acol[4];
}
MouseArea {
anchors.fill: parent
onClicked: rg1.acolored(Qt.rgba(0.2, 0.2, 0.2, 1))
}
}
...
onAcolored处理程序调用onAcolor函数,并相应地更改第一个矩形的属性。
- 将第二个发光矩形添加到
GridLayout的底部:
...
...
Qmls.URectGlow {
id: rg2
Layout.leftMargin: parent.width / 100
Layout.rightMargin: parent.width / 100
Layout.topMargin: parent.height / 4
Layout.bottomMargin: parent.height / 12
Layout.fillWidth: true
Layout.fillHeight: true
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(0.95, 0, 0, 1);
txglow: Qt.rgba(0.77, 0, 0, 1);
txtext: "PUSH"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
...
...
第二个矩形使用与第一个类似的属性。
- 然后,将连续动画添加到第二个矩形中:
...
...
...
SequentialAnimation {
id: sa2; running: false
loops: Animation.Infinite
PropertyAnimation {
target: rg2
properties: "glowcolor,txglow"
from: Qt.rgba(0.95, 0, 0, 1);
to: Qt.rgba(0.007, 1, 1, 1);
duration: 7000
easing.type: Easing.OutInElastic
}
PropertyAnimation {
target: rg2
properties: "glowcolor,txglow"
from: Qt.rgba(0.007, 1, 1, 1);
to: Qt.rgba(0.95, 0, 0, 1);
duration: 7000
easing.type: Easing.OutInElastic
}
}
MouseArea {
anchors.fill: parent; onClicked: sa2.running = true;
}
}
...
这些动画用于动画矩形发光和文本发光颜色的颜色变化。
- 将第三个元素添加到应用程序窗口的标签中:
...
...
Qmls.URectGlow {
id: rg3
Layout.leftMargin: parent.width / 100
Layout.rightMargin: parent.width / 100
Layout.topMargin: parent.height / 4
Layout.bottomMargin: parent.height / 12
Layout.fillWidth: true
Layout.fillHeight: true
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(0.95, 0, 0, 1);
txglow: Qt.rgba(0.77, 0, 0, 1);
txtext: "PUSH"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
...
...
此标签元素与该标签中的其他元素类似。
- 向标签的第三个元素(发光矩形)添加并行动画:
...
...
...
ParallelAnimation {
id: pa3; running: false
loops: Animation.Infinite
PropertyAnimation {
target: rg3
properties: "glowcolor,txglow"
to: Qt.rgba(0, 0.07, 0.14, 1);
duration: 7000
easing.type: Easing.OutInElastic
}
PropertyAnimation {
target: rg3
properties: "glowr,spr"
to: 1
duration: 7000
}
}
MouseArea {
anchors.fill: parent; onClicked: pa3.running = true
}
}
}
此类型使用PropertyAnimation类型来并行更改不同的属性。
现在我们需要在URectGlow.qml文件中进行一些更改:
- 向
URectGlow.qml文件添加新属性:
...
Rectangle {
property color glowcolor
property color txglow
property string txtext
property color txcolor
property real glowr: 10
property real spr: 0.1
property real whr: 1.5
property real rdx: 14
...
在这里,我们已向发光矩形添加了自定义属性,可以在任何地方更改,这将重新实现此对象在应用程序中。
- 现在我们需要更改
URectGlow.qml的所有相关属性,以便它们成为自定义属性:
...
...
RectangularGlow {
...
glowRadius: parent.glowr
spread: parent.spr
...
}
Rectangle {
...
width: parent.width / parent.whr
height: parent.height / parent.whr
...
radius: rdx
Text {
...
text: txtext
...
color: txcolor
}
Glow {
...
radius: parent.radius / 2
...
}
}
...
将属性更改为自定义属性的值,以在应用程序中重新实现它们。
- 为了使应用程序正常工作,建议您将以下行添加到应用程序的每个矩形发光元素中:
...
GridLayout {
...
Uqmls.URectGlow {
...
txtext: "PUSH"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
...
...
...
我们已将矩形的属性更改为新创建的自定义属性。
- 要显示此结果,我们可以在
u_qml.qml文件中添加以下行,在矩形之前某处,使用id: rect1:
...
...
Uqmls.UAppwin { id: appwin1; visible: true }
...
...
前一行将演示应用程序窗口添加到主窗口应用程序中。使用u_app.py Python 文件运行u_qml.qml文件。您将看到带有条形、菜单和动画项的应用程序窗口:

应用程序窗口有一个顶部面板、工具栏、中央小部件和状态栏。中央小部件的按钮提供动画效果。
Button
在 GUI 中最受欢迎的类型是按钮。这是一个带有文本标签的推按钮。您需要以下import语句:
import QtQuick.Controls 1.4
它具有以下属性:
action: 这是一个关联的按钮动作,例如文本或工具提示。
checkable: 这可以是true或false。如果是true,按钮将是可检查的,即当用户按下此按钮时它将保持按下状态(默认为false)。
checked: 这可以是true或false。如果是true,按钮将被选中(默认为false)。仅在checkable设置为true时可用。
exclusiveGroup: 这确定按钮是否属于一个组。
hovered: 这可以是true或false,并指示按钮是否正在悬停。
iconName: 这是一个string,是图像源的主题名称。
iconSource: 这是一个 URL。按钮将使用提供的 URL 中的图标图像。
isDefault: 这可以是true或false。此按钮将是默认按钮,或当按下Enter键时将被点击。
menu: 这为按钮提供了一个下拉菜单。
pressed: 这可以是true或false。如果是true,按钮已被按下。
style: 这个组件用于按钮的样式,例如ButtonStyle。
text: 这是一个string,将文本设置到按钮上。
tooltip: 这是一个string,为按钮设置工具提示。
它还具有以下信号:
clicked(): 当按钮被点击时发出。
ButtonStyle
可以使用ButtonStyle类型来样式化按钮。您需要以下import语句:
import QtQuick.Controls.Styles 1.4
它具有以下属性:
background: 这个组件用于按钮的背景样式。
control: 这是Button QML 类型的按钮,它将附加到该按钮上的样式。
label: 这个组件用于样式化此按钮的标签。
让我们看看以下示例:
- 修改
UButton.qml文件:
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import "." as Qmls
Button {
property color bcolor: Qt.rgba(0, 0.07, 0.14, 1);
property color gcolor: Qt.rgba(0.95, 0, 0, 1);
property color tgcolor: Qt.rgba(0.77, 0, 0, 1);
property color tcolor: Qt.rgba(0.2, 0.2, 0.2, 1);
property real glrd: 3
property real sprd: 0.5
property string btext
...
这是一个标准的推按钮,具有指定的自定义属性,如颜色、发光半径、扩散和文本。
- 使用
ButtonStyle类型将style属性添加到按钮中:
...
...
style: ButtonStyle {
background: Qmls.URectGlow {
id: but1
txtext: btext
txcolor: tcolor
color: bcolor
glowcolor: gcolor
txglow: tgcolor
glowr: glrd
spr: sprd
whr: 1.2
rdx: 7
}
}
}
在这里,我们使用ButtonStyle类型和背景属性来设置按钮样式,这将使用按钮的自定义属性。现在我们需要向u_qml.qml文件中添加一些行。
- 在导入部分,添加可以与按钮和其他相关元素一起使用的控件和控件样式:
...
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
...
导入元素的版本可能因你使用的 Qt 库版本而异。
- 在具有
id: rect2的矩形内添加第一个按钮:
...
...
...
Uqmls.URect {
...
Uqmls.UButton {
id: ubut1
width: rect2.width
height: rect2.height / 10
btext: "HIDE"
tooltip: "Hide the panel with buttons"
MouseArea {
anchors.fill: parent; hoverEnabled: true
onEntered: {
parent.tcolor = Qt.rgba(1, 0, 0, 1);
}
onExited: {
parent.tcolor = Qt.rgba(0.2, 0.2, 0.2, 1);
}
onClicked: {
rect2.visible = false;
rect1.width = UQml.Window.width;}
}
}
}
...
...
...
在这里,我们在按钮的鼠标区域使用不同类型的信号处理器。
- 在第一个按钮之后添加第二个按钮:
...
...
...
Uqmls.UButton {
id: ubut2
width: rect2.width
height: rect2.height / 10
y: rect2.height / 10
btext: "APPS"
tooltip: "Run example of the Application Window"
...
...
...
如此按钮中指定的tooltip属性将提供使用动作的提示信息。
- 在第二个按钮的底部添加顺序动画:
...
...
...
...
SequentialAnimation {
id: sa1; running: false; loops: 1
PropertyAnimation {
target: ubut2; property: "glrd"; to: 7;
duration: 100;
}
PropertyAnimation {
target: ubut2; property: "glrd"; to: 3;
duration: 100
}
}
...
...
...
这用于通过动画实现悬停和闪烁效果。
- 将
MouseArea类型添加到第二个按钮:
...
...
...
...
MouseArea {
anchors.fill: parent; hoverEnabled: true
onEntered: {
parent.tcolor = Qt.rgba(1, 0, 0, 1);
}
onExited: {
parent.tcolor = Qt.rgba(0.2, 0.2, 0.2, 1);
}
onClicked: {
sa1.running = true; appwin1.visible = true;
}
}
}
这些信号处理器用于处理诸如光标进入区域、光标从区域退出以及点击等事件。
- 现在在第二个按钮之后添加第三个按钮:
...
...
...
Uqmls.UButton {
id: ubut3
width: rect2.width
height: rect2.height / 10
y: (rect2.height / 10) * 2
btext: "TOOL"
tooltip: "Show animated rectangles as item elements"
...
...
...
点击此按钮将在应用程序窗口中显示动画矩形。
- 将
MouseArea类型和onClicked处理器添加到第三个按钮:
...
...
...
...
MouseArea {
anchors.fill: parent; hoverEnabled: true
onEntered: {
ubut3.tcolor = Qt.rgba(1, 0, 0, 1);
}
onExited: {
ubut3.tcolor = Qt.rgba(0.2, 0.2, 0.2, 1);
}
onClicked: {ubut3.clicked()}
}
onClicked: {
ubut3.glrd == 3 ? ubut3.glrd = 7 : ubut3.glrd = 3;
if (ubut3.glrd==7) {
main_item.visible = true;
grid1.visible = false;
} else {
main_item.visible = false;
grid1.visible = true;
};
}
}
...
...
onClicked处理器使用 JavaScript 指令使应用程序窗口的第一个矩形中的main_item和grid1可见/不可见。
现在我们需要从u_qml.qml文件中剪切Grid,在qmls/目录中创建一个名为UGrid.qml的文件,将Grid粘贴到该文件中,并使用GridLayout重建代码行。
- 将
Grid元素的定位更改为GridLayout构建。
import QtQuick 2.7
import QtQuick.Layouts 1.3
import "." as Uqmls
GridLayout {
Uqmls.UCircle {id: g1;Layout.margins: 20
Layout.fillWidth: true;Layout.fillHeight: true}
Uqmls.URectLG {id: g2;Layout.margins: 20
Layout.fillWidth: true;Layout.fillHeight: true}
Uqmls.URectRG {id: g3;Layout.margins: 20
Layout.fillWidth: true;Layout.fillHeight: true}
Uqmls.URectCG {id: g4;Layout.margins: 20
Layout.fillWidth: true;Layout.fillHeight: true}
...
...
这是我们在使用GridLayout定位之前使用的项目构建。
- 将具有发光效果的第一个矩形添加到
UGrid.qml文件中:
...
...
Uqmls.URectGlow {
id: g5; Layout.fillWidth: true; Layout.fillHeight: true
Layout.margins: 20
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(0.007, 1, 1, 1);
txglow: Qt.rgba(0.007, 0.7, 0.7, 1);
txtext: "PUSH"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
...
...
...
将自定义和布局属性添加到这个矩形中。
- 将
MouseArea和RotationAnimatorQML 类型添加到第一个矩形中:
...
...
...
MouseArea {
anchors.fill: parent
onClicked: {
g5.glowcolor == Qt.rgba(0.007, 1, 1, 1) ?
g5.glowcolor = Qt.rgba(0, 0.07, 0.14, 1) :
g5.glowcolor = Qt.rgba(0.007, 1, 1, 1);
g5.txglow == Qt.rgba(0, 0.07, 0.14, 1) ?
g5.txglow = Qt.rgba(0.007, 1, 1, 1) :
g5.txglow = Qt.rgba(0, 0.07, 0.14, 1);
g5a.running == true ?
g5a.running = false : g5a.running = true;
}
}
RotationAnimator {
id: g5a; running: false; loops: Animation.Infinite
target: g1
to: 360
duration: 1000
easing.type: Easing.Linear
}
}
...
此动画器将以360度顺时针旋转具有指定id属性的项目,速度取决于duration属性。动画将是无限的。
- 将第二个矩形添加到
UGrid.qml文件中:
...
...
Uqmls.URectGlow {
id: g6; Layout.fillWidth: true; Layout.fillHeight: true
Layout.margins: 20
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(0.95, 0, 0, 1);
txglow: Qt.rgba(0.77, 0, 0, 1);
txtext: "PUSH"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
...
...
...
这是具有id和Layout属性的第二个矩形。
- 将
MouseArea和RotationAnimator类型添加到第二个矩形的底部:
...
...
...
MouseArea {
anchors.fill: parent
onClicked: {
g6.glowcolor == Qt.rgba(0.95, 0, 0, 1) ?
g6.glowcolor = Qt.rgba(0, 0.07, 0.14, 1) :
g6.glowcolor = Qt.rgba(0.95, 0, 0, 1);
g6.txglow == Qt.rgba(0, 0.07, 0.14, 1) ?
g6.txglow = Qt.rgba(0.77, 0, 0, 1) :
g6.txglow = Qt.rgba(0, 0.07, 0.14, 1);
g6a.running == true ?
g6a.running = false : g6a.running = true;
}
}
RotationAnimator {
id: g6a; running: false; loops: Animation.Infinite
target: g2
to: 360
duration: 300
easing.type: Easing.InQuad
}
}
...
这个RotationAnimator的duration属性比第一个矩形中的要小,因此这个圆圈将旋转得更快。
- 将第三个矩形添加到
UGrid.qml文件中:
...
...
Uqmls.URectGlow {
id: g7; Layout.fillWidth: true; Layout.fillHeight: true
Layout.margins: 20
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(0,0.95,0.37,1);
txglow: Qt.rgba(0,0.47,0.37,1);
txtext: "PUSH"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
...
...
这是第三个带有发光效果的矩形,具有id: g7属性和填充宽度和高度的Layout属性。
- 将
MouseArea和RotationAnimator添加到第三个矩形中:
...
...
...
MouseArea {
anchors.fill: parent
onClicked: {
g7.glowcolor == Qt.rgba(0, 0.95, 0.37, 1) ?
g7.glowcolor = Qt.rgba(0, 0.07, 0.14, 1) :
g7.glowcolor = Qt.rgba(0, 0.95, 0.37, 1);
g7.txglow == Qt.rgba(0, 0.07, 0.14, 1) ?
g7.txglow = Qt.rgba(0, 0.47, 0.37, 1) :
g7.txglow = Qt.rgba(0, 0.07, 0.14, 1);
g7a.running == true ?
g7a.running = false : g7a.running = true;
}
}
RotationAnimator {
id: g7a; running: false; loops: Animation.Infinite
target: g3
to: 360
duration: 200
easing.type: Easing.InCubic
}
}
...
此RotationAnimator将比前两个旋转目标圆圈更快。
- 最后,将第四个矩形添加到应用程序中:
...
...
Uqmls.URectGlow {
id: g8; Layout.fillWidth: true; Layout.fillHeight: true
Layout.margins: 20
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(1, 1, 1, 1);
txglow: "grey";
txtext: "PUSH"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
...
...
这个矩形使用命名颜色grey为矩形的txtglow属性。
- 最后,对于最后一个矩形,添加
MouseArea和RotationAnimator类型:
...
...
...
MouseArea {
anchors.fill: parent
onClicked: {
g8.glowcolor == Qt.rgba(1, 1, 1, 1) ?
g8.glowcolor = Qt.rgba(0, 0.07, 0.14, 1) :
g8.glowcolor = Qt.rgba(1, 1, 1, 1);
g8.txglow == Qt.rgba(0, 0.07, 0.14, 1) ?
g8.txglow = "grey" :
g8.txglow = Qt.rgba(0, 0.07, 0.14, 1);
g8a.running == true ?
g8a.running = false : g8a.running = true;
}
}
RotationAnimator {
id: g8a; running: false; loops: Animation.Infinite
target: g4
to: 360
duration: 100
easing.type: Easing.InQuart
}
}
}
此动画器将以比前一个圆圈更快的速度旋转目标圆圈。以下示例演示了使用 Button、Rectangle 和 MouseArea QML 类型创建和设置按钮样式的原理。
通过使用此代码进行练习,可以帮助你理解这些基础知识。最后,为了在应用程序中实现按钮,让我们更改 u_qml.qml 文件:
- 将
UAppwin、UItem和UGrid属性添加/设置到应用程序中:
...
...
...
...
Uqmls.UAppwin {
id: appwin1
visible: false
}
Uqmls.UItem {
id: main_item
visible: false
width: rect1.width
height: parent.height - rect1.height
y: rect1.height
}
Uqmls.UGrid {
id: grid1
anchors.fill: parent
visible: true
function wsize() {
if (parent.width > 590) {
return 4;
}
else {return 2;};
}
columns: wsize();
}
...
...
...
将 UItem 和 UAppwin 的可见属性设置为 false。默认情况下,UGrid 将带有圆圈和发光矩形可见。现在我们可以运行应用程序,我们将看到以下结果:

如果我们按下这些按钮,相关的圆圈将旋转,如果我们再次按下,相关的圆圈将停止。
CheckBox
CheckBox 按钮允许用户选择一个或多个选项。复选框按钮可以切换以选中选项,也可以取消选中,它由复选框和文本标签组成。为此类型需要以下 import 语句:
import QtQuick.Controls 1.4
它具有以下属性:
checked: 这可以是 true 或 false。如果复选框被选中,则为 true。
pressed: 这可以是 true 或 false。如果复选框被选中,则为 true。
hovered: 这可以是 true 或 false。如果鼠标指针悬停在复选框上,则为 true。
partiallyCheckedEnabled : 这可以是 true 或 false。它使得 Qt.PartiallyChecked 状态可用。
text: 这是一个 string,用于设置将显示在复选框附近的文本。
tooltip: 这是一个 string,用于为此按钮设置工具提示。
checkedState: 这是一个整数,用于设置按钮的当前状态。1 表示选中,0 表示未选中,2 表示部分选中。
activeFocusOnPress: 这可以是 true 或 false。当按下时,复选框将被聚焦。
exclusiveGroup: 这将设置复选框所属的组。
style: 此组件为此按钮提供样式,例如 CheckBoxStyle 类型。CheckBoxStyle 类型包括 background、control、indicator、label 和 spacing 属性。
ComboBox
此类型允许用户从下拉列表的多个选项中进行选择或实现模型以表示 ComboBox。使用以下 import 语句:
import QtQuick.Controls 1.4
它具有以下属性:
count: 这是一个整数,表示组合框中的项目数量。
currentIndex: 这是一个整数,表示组合框中选中项的索引。
currentText: 这是一个 string,用于设置选中项的文本。
pressed: 这可以是 true 或 false。如果 ComboBox 被按下,则为 true。
hovered: 这可以是 true 或 false。如果鼠标指针悬停在框上,则为 true。
editable: 这可以是true或false。它将使组合框内的文本可编辑。
editText: 这是一个表示可编辑ComboBox中文本的string,可以对其进行编辑。
selectByMouse: 这可以是true或false,它为你提供了使用鼠标选择可编辑ComboBox中文本的能力。
menu: 此组件设置一个菜单,以便你可以处理文本选择,例如menu类型组件。
model: 这将用于实现ComboBox。
inputMethodComposing: 这可以是true或false。如果为true,可编辑的ComboBox有来自输入方法的文本输入。
inputMethodHints: 这个enumeration为输入设置了有关预期内容的提示,例如Qt.ImhHiddenText,这将是一个密码字段,或者Qt.ImhDate,这将是一个日期字段。
acceptableInput: 这可以是true或false。如果为true,可编辑文本字段包含可接受的文本。
activeFocusOnPress: 这可以是true或false。按下时,ComboBox将被聚焦。
textRole: 这是一个可以作为ComboBox模型角色的string。
validator: 这为可编辑的ComboBox设置了一个文本验证器。
style: 此组件用于ComboBox的样式,例如ComboBoxStyle类型。ComboBoxStyle具有background、control、dropDownButtonWidth、font、label、renderType、selectedTextColor、selectionColor和textColor属性。
RadioButton
此类按钮提供在不同选项之间的选择,并且一次只能选择一个。此按钮由单选按钮控件和文本标签组成。你需要以下import语句:
import QtQuick.Controls 1.4
它具有以下属性:
checked: 这可以是true或false。如果单选按钮被选中,则为true。
pressed: 这可以是true或false。如果按钮被按下,则为true。
hovered: 这可以是true或false。如果鼠标指针悬停在按钮上,则为true。
text: 这是一个设置靠近单选按钮显示的文本的string。
tooltip: 这是一个设置此按钮提示的string。
activeFocusOnPress: 这可以是true或false。按下时,单选按钮将被聚焦。
exclusiveGroup: 这是按钮所属的组。
style: 此组件为按钮提供样式,例如RadioButtonStyle类型。在RadioButtonStyle类型中,background、control、indicator、label和spacing属性可用。
TextField
这些元素提供了处理和可视化文本数据的功能。用户可以从文件粘贴、复制、编辑和手动插入文本,或者使用与文本字段中的文本相关的其他操作。在QtQuick模块中,TextArea和TextField类型可用于这些任务。
TextArea
此类型允许编辑格式化的文本行。我们需要使用以下import语句:
import QtQuick.Controls 1.4
它具有以下属性:
text: 这是一个将在文本区域中显示的string。
textFormat: 这个enumeration是TextArea将提供的文本字段类型。它可以是指定文本将自动确定是纯文本还是富文本的TextEdit.AutoText;TextEdit.PlainText,其中文本将是纯文本;以及TextEdit.RichText,这将使文本成为富文本。
textDocument: textDocument属性公开了QQuickTextDocument类。
baseUrl: 这指定了一个基础 URL,该 URL 将用于解析文本中的相对 URL。
hoveredLink: 这是一个链接string。当鼠标悬停时,可以看到文本中已嵌入链接。
wrapMode: 这个enumeration提供了与文本区域宽度相关的文本换行。可用的标志如下:
-
TextEdit.NoWrap: 将不可用换行。 -
TextEdit.WordWrap: 按单词进行文本换行(默认)。 -
TextEdit.WrapAnywhere: 文本将在任何地方换行。 -
TextEdit.Wrap: 如果可能,文本将按单词换行,或者如果文本行长且没有空格,则将在行的适当位置换行。
length: 这是一个整数,表示文本区域中纯文本字符的数量。
lineCount: 这是一个整数,表示文本中的行数。
inputMethodComposing: 这可以是true或false。如果为true,则文本区域将具有来自输入方法的文本输入。
inputMethodHints: 这个enumeration提供了可以与文本区域标志(如Qt.ImhHiddenText用于密码)一起实现的输入方法类型。
readOnly: 这可以是true或false。如果为true,则文本区域将是只读的。
selectByKeyboard: 这可以是true或false,如果为true,则允许用户使用键盘选择文本(默认为true)。
selectByMouse: 这可以是true或false,如果为true,则允许用户使用鼠标选择文本(默认为true)。
selectedText: 这是一个表示当前选中文本的string。
selectionStart: 这是一个整数,表示光标在选中文本第一个字符前的位置。
selectionEnd: 这是一个整数,表示光标在选中文本最后一个字符后的位置。
canPaste: 这可以是true或false,如果剪贴板中的内容可以粘贴到文本区域中,则返回true。
canRedo: 这可以是true或false,如果文本已被编辑并且可以重做,则返回true。
canUndo: 这可以是true或false,如果文本已被编辑并且可以撤销,则返回true。
cursorPosition: 这是一个整数,表示光标在文本区域中的位置。
cursorRectangle: 这是文本光标在文本区域中渲染的矩形。
activeFocusOnPress: 这可以是 true 或 false。如果为 true,则在按下时文本区域将被聚焦。
backgroundVisible: 这可以是 true 或 false,如果为 true,则背景被填充(默认为 true)。
tabChangesFocus: 这可以是 true 或 false。此属性确定制表符是否改变焦点,或作为输入接受(默认为 false)。
effectiveHorizontalAlignment: 这个 枚举 是文本的有效水平对齐。
horizontalAlignment: 这个 枚举 设置文本的对齐方式,例如 TextEdit.AlignHCenter。
verticalAlignment: 这个 枚举 设置文本的对齐方式,例如 TextEdit.AlignTop、TextEdit.AlignVCenter(默认)或 TextEdit.AlignBottom。
textMargin: 这定义了文本区域周围(以像素为单位)的边距。
textColor: 这是区域中文本的颜色。
font: 这是文本的字体。
menu: 这个组件是用于处理文本选择的编辑菜单。
style: 这个组件为文本区域提供样式,例如 TextAreaStyle 类型。TextAreaStyle 中的属性有 backgroundColor、control、renderType、font、selectedTextColor、selectionColor、textColor 和 textMargin。
以下信号可用:
editingFinished(): 当区域失去焦点时,这将发出。处理程序是 onEditingFinished。
linkActivated(string link): 当用户在文本中点击链接时,这将发出。处理程序是 onLinkActivated。
linkHovered(string link): 当文本中的链接被悬停时,这将发出。处理程序是 onLinkHovered。
以下是其方法:
append(string text): 这将在文本末尾添加一个新的 string 行。
copy(): 这将选定的文本复制到剪贴板。
cut(): 这将选定的文本剪切到剪贴板。
paste(): 这将剪贴板中选定的文本插入到文本区域。
deselect(): 这将移除文本选择。
getFormattedText(int start, int end): 这将在起始和结束位置之间返回带有格式的文本。
getText(int start, int end): 这将在起始和结束位置之间返回未格式化的文本。
insert(int position, string text): 这将在文本区域的指定位置插入文本。
isRightToLeft(int start, int end): 如果起始/结束位置之间的文本方向是从右到左,则为 true。
moveCursorSelection(int position, mode=TextEdit.SelectCharacters): 这将光标移动到指定的位置并更新模式参数。
positionToRectangle(position): 这将在文本的位置返回矩形。
undo(): 如果可用,这将撤销文本的最后一个编辑操作。
redo(): 如果可用,这将重做文本的最后一个编辑操作。
remove(int start, int end): 这将删除起始/结束位置之间的文本。
select(int start, int end): 这将选择从起始/结束位置之间的文本。
selectAll(): 这将选择文本区域中的所有文本。
selectWord(): 这将选择距离当前光标位置最近的单词。
TextField
此类型提供一行可编辑的纯文本。TextField类型需要以下import语句:
import QtQuick.Controls 1.4
它具有以下属性:
text: 这是在文本字段中显示的string。
displayText: 这是在文本字段中显示的文本的string。
echoMode: 这个enumeration设置文本的显示方式。可用的模式如下:
-
TextInput.Normal: 这用于普通文本。 -
TextInput.Password: 这用于密码文本。 -
TextInput.NoEcho: 这用于不显示的文本。 -
TextInput.PasswordEchoOnEdit: 这用于在编辑时显示为普通文本,否则字符将以星号形式显示。
placeholderText: 这是一个string,当文本字段为空时将显示此文本。
length: 这是一个整数,返回文本字段中纯文本字符的数量。
maximumLength: 这是一个整数,表示文本字段中文本的最大长度。
inputMask: 这是一个string,表示TextField上的输入掩码,并限制允许的文本输入。
inputMethodComposing: 这可以是true或false。文本字段将具有来自输入方法的文本输入。
inputMethodHints: 这个enumeration提供了可以使用文本字段实现的输入方法类型,例如密码的Qt.ImhHiddenText标志。
readOnly: 这可以是true或false。如果为true,则文本字段将是只读的。
selectByMouse: 这可以是true或false,如果为true,则允许我们使用鼠标选择文本(默认为true)。
selectedText: 这是当前选中文本的string。
selectionStart: 这是选中区域中第一个字符之前的光标位置的整数。
selectionEnd: 这是选中区域中最后一个字符之后的光标位置的整数。
canPaste: 这可以是true或false,如果剪贴板上的内容可以粘贴到文本字段中,则返回true。
canRedo: 这可以是true或false,如果文本已被编辑且可以重做,则返回true。
canUndo: 这可以是true或false,如果文本已被编辑且可以撤销,则返回true。
cursorPosition: 这是文本字段中光标位置的整数。
cursorRectangle: 这是文本字段中渲染文本光标的矩形。
activeFocusOnPress: 这可以是true或false,如果为true,则在按下时文本字段将被聚焦。
acceptableInput: 这可以是true或false,如果文本是可接受的则返回true。
hovered: 这可以是true或false,取决于文本字段是否被悬停。
effectiveHorizontalAlignment: 此枚举是文本的有效水平对齐方式。
horizontalAlignment: 此枚举设置文本的对齐方式,例如TextInput.AlignHCenter。
verticalAlignment: 此枚举设置文本的对齐方式,例如TextInput.AlignTop、TextInput.AlignVCenter(默认值)和TextInput.AlignBottom。
textColor: 这是文本区域中的文本颜色。
font: 这是文本的字体。
menu: 这是用于处理文本选择的编辑菜单组件。
validator: 这会在TextField上设置验证器。支持的验证器有IntValidator、DoubleValidator和RegExpValidator。
style: 此组件为文本字段提供样式,例如TextFieldStyle类型。在此类型中,有background、control、passwordCharacter、placeholderTextColor、renderType、font、selectedTextColor、selectionColor和textColor属性。
可用的信号有:
editingFinished(): 当字段失去焦点时发出此信号。处理程序是onEditingFinished。
accepted(): 当按下回车或Enter键时发出此信号。
以下方法可用:
copy(): 这会将选定的文本复制到剪贴板。
cut(): 这会将选定的文本剪切到剪贴板。
paste(): 这会将剪贴板中的选定文本插入到文本字段中。
deselect(): 这会移除文本选择。
getText(int start, int end): 这返回起始和结束位置之间的无格式文本。
insert(int position, string text): 这会在文本字段中指定的位置插入文本。
isRightToLeft(int start, int end): 如果起始/结束位置之间的文本方向是从右到左,则返回true。
undo(): 如果可用,则撤销文本的最后一个编辑操作。
redo(): 如果可用,则重做文本的最后一个编辑操作。
remove(int start, int end): 这会删除起始/结束位置之间的文本。
select(int start, int end): 这会选中起始/结束位置之间的文本。
selectAll(): 这会选中文本字段中的所有文本。
selectWord(): 这会选中距离当前光标位置最近的单词。
导航
QtQuick.Controls模块提供了一个用于在 GUI 应用程序内部构建导航工具的仪器。这些类型的import语句如下:
import QtQuick.Controls 1.4
它可以使用以下章节中提到的类型实现。
ScrollView
此类型提供在另一个项目内的滚动。如果项目的高度和宽度超过主窗口,它允许我们滚动该项目,并添加滚动条。ScrollView类型具有以下属性:
contentItem: 这是此滚动的项目。
flickableItem: 这是此滚动视图的可轻扫项目。
frameVisible: 这可以是 true 或 false。当为 true 时,滚动视图将渲染其内容周围的框架。
highlightOnFocus: 这可以是 true 或 false。如果为 true,则当它具有输入焦点时,将在框架周围突出显示。
horizontalScrollBarPolicy: 这是一个用于水平滚动条的 enumeration,例如 Qt.ScrollBarAsNeeded、Qt.ScrollBarAlwaysOff 和 Qt.ScrollBarAlwaysOn。
verticalScrollBarPolicy: 这是一个与水平滚动条相同模式的 enumeration。
viewport: 这是视口的大小,并告诉我们内容区域相对于窗口的可见程度。
style: 此组件为滚动提供样式,例如 ScrollViewStyle 类型。在此类型中,有 control、corner、decrementControl、frame、handle、handleOverlap、incrementControl、minimumHandleLength、scrollBarBackground、scrollToClickedPosition 和 transientScrollBars 属性。
SplitView
这是一个用于水平或垂直布局的可拖动分隔符的 QML 类型。此类型具有以下属性:
handleDelegate: 这是每个子项目之间的委托组件。它具有 styleData.index、styleData.hovered、styleData.pressed 和 styleData.resizing 等属性。
orientation: 这是一个整数,可以具有 Qt.Horizontal(默认)或 Qt.Vertical 的滚动视图方向。
resizing: 这可以是 true 或 false。如果通过将分隔符手柄拖动到滚动视图的项目上对其进行调整大小,它将返回 true。
它有以下方法:
addItem(Item item): 这会将项目添加到滚动视图的末尾。
removeItem(Item item): 这将从滚动视图中删除项目。
StackView
此类型构建了一个基于堆栈的导航模型。它具有以下属性:
busy: 这可以是 true 或 false。如果过渡正在运行,它将返回 true。
currentItem: 这获取堆栈中最顶部的项目。
delegate: StackViewDelegate 是用于使用此堆栈视图推送和弹出项目的过渡。
depth: 这是一个表示堆栈中项目数量的整数。
initialItem: 这是将显示在堆栈中的第一个项目。
它有以下方法:
clear(): 这将从堆栈中删除所有项目。
completeTransition(): 这立即完成正在运行的过渡。
find(function, bool onlySearchLoadedItems=false): 这在此堆栈中查找项目。
get(int index, bool dontLoad=false): 这将返回具有指定索引的堆栈项目。
pop(Item item=undefined): 这将从堆栈中弹出项目。
push(Item item): 这会将项目推送到堆栈。
TabView
此类型允许您从多个堆叠项中选择一个,并暗示基于标签的导航模型。它具有以下属性:
contentItem: 这是标签视图的内容项。
count: 这个整数表示当前标签的数量。
currentIndex: 这个整数表示当前标签的索引。
frameVisible: 这可以是true或false。如果是true,则内容周围的标签框架将可见。
tabPosition: 这个整数表示标签控件的位置,例如Qt.TopEdge(默认值)或Qt.BottomEdge。
tabsVisible: 这可以是true或false。如果是true,则标签栏将可见。
style: 该组件为标签视图提供样式,例如TabViewStyle类型。此类型提供了control、frame、frameOverlap、leftCorner、rightCorner、tab、tabBar、tabOverlap、tabsAlignment和tabsMovable属性。
它有以下方法:
addTab(string title, Component component): 这将添加一个新的标签。
getTab(int index): 这通过其索引返回标签。
insertTab(int index, string title, Component component): 这将在指定的索引处插入一个新的标签。
moveTab(int from, int to): 这将标签从一个索引移动到另一个索引。
removeTab(int index): 这将移除并销毁在提供的索引处的标签。
TableView
此类型在 GUI 应用程序中实现了一个表格。除了ListView、滚动条、标题部分和样式外,还有其他功能。此类型具有以下属性:
columnCount: 这个整数表示表格中的列数。
rowCount: 这个整数表示表格中的行数。
contentFooter: 该组件是表格页脚的内容。
contentHeader: 这是表格标题的内容组件。
currentRow: 这个整数表示表格中行的当前索引。
alternatingRowColors: 这可以是true或false。如果是true(默认值),则行的颜色将交替。
backgroundVisible: 这可以是true或false。如果是true(默认值),则背景将被填充。
frameVisible: 这可以是true或false。如果是true(默认值),它将在其内容周围渲染一个框架。
headerVisible: 这可以是true或false。如果是true(默认值),则标题将可见。
headerDelegate: 该组件定义了一个用于绘制标题的委托。
itemDelegate: 该组件定义了一个用于绘制单元格的委托。
rowDelegate: 该组件定义了一个用于绘制行的委托。
model: 这是表格的模型。
section.property: 这是一个表示属性名称的string,是每个部分的基础。
section.criteria: 这是一个枚举,表示形成每个部分的准则,例如ViewSection.FullString(默认值)或ViewSection.FirstCharacter。
section.delegate: 这是每个部分的委托组件。
section.labelPositioning: 这是一个枚举,用于设置节标签的位置,例如ViewSection.InlineLabels(默认)、ViewSection.CurrentLabelAtStart和ViewSection.NextLabelAtEnd。
sortIndicatorColumn: 这个整数是当前排序列的索引。
sortIndicatorOrder: 这个整数设置指示器的排序顺序,例如Qt.AscendingOrder(默认)和Qt.DescendingOrder。
sortIndicatorVisible: 这可以是true或false。如果为true,则排序指示器将可见。
selection: 这是表格当前行选择。
selectionMode: 这是一个整数,表示用户选择的模式,例如SelectionMode.NoSelection、SelectionMode.SingleSelection(默认)、SelectionMode.MultiSelection、SelectionMode.ExtendedSelection和SelectionMode.ContiguousSelection。
style: 此组件为表格提供样式,例如TableViewStyle类型。此类型提供activateItemOnSingleClick、alternateBackgroundColor、backgroundColor、highlightedTextColor和textColor属性。
它有以下信号:
activated(int row): 当鼠标或键盘激活一个项目时发出。处理程序是onActivated。
clicked(int row): 当点击行时发出。处理程序是onClicked。
doubleClicked(int row): 当双击行时发出。处理程序是onDoubleClicked。
pressAndHold(int row): 当按住行时发出。处理程序是onPressAndHold。
它有以下方法:
addColumn(object column): 将列添加。
getColumn(int index): 这返回指定索引的列。
insertColumn(int index, object column): 在表中插入一列。
moveColumn(int from, int to): 将列从指定的索引移动到另一个索引。
positionViewAtRow(int row, PositionMode mode): 这是根据模式在指定行中定义的视图位置,例如ListView.Beginning、ListView.Center、ListView.End、ListView.Visible或ListView.Contain。
removeColumn(int index): 通过索引删除并销毁表中的列。
resizeColumnsToContents(): 根据内容调整列的大小。
rowAt(int x, int y): 通过其x和y坐标返回行的索引。
其他工具
在QtQuick.Controls模块中,提供了可用于实现 GUI 应用程序的有用类型。所有这些类型都需要以下import语句:
import QtQuick.Controls 1.4
让我们详细地通过所有这些类型。
日历
此类型提供日历小部件,并具有以下属性:
dayOfWeekFormat: 这个整数是显示星期几的格式。
frameVisible: 这可以是true或false。如果为true,则围绕日历的框架将可见。
minimumDate: 这是日历将接受的最早日期。
maximumDate: 这是日历将接受的最新日期。
navigationBarVisible: 这可以是true或false。如果为true,则导航栏将可见。
selectedDate: 这是用户选择的日期。
visibleMonth: 这是一个整数,表示日历上显示的月份(从0到11)。
visibleYear: 这是一个整数,表示将显示的年份。
weekNumbersVisible: 这可以是true或false。如果为true,则周数将可见(默认为false)。
style: 此组件使用CalendarStyle类型为日历提供样式。使用CalendarStyle类型,background、control、dayDelegate、dayOfWeekDelegate、gridColor、gridVisible、navigationBar和weekNumberDelegate属性可用。
ProgressBar
这提供了一个可视化的元素,用于显示 GUI 中操作的进度。它具有以下属性:
value: 这是进度条当前值。
minimumValue: 这是进度条的最低值。
maximumValue: 这是进度条的最大值。
indeterminate: 这可以是true或false。如果为true,则进度将以忙碌状态动画显示(默认为false)。
orientation: 这是一个整数,表示进度条的水平和垂直方向(默认为Qt.Horizontal)。
hovered: 这可以是true或false。如果为true,则此进度条正在被悬停。
style: 此组件使用ProgressBarStyle类型为进度条提供样式。此类型具有background、control、currentProgress、panel和progress属性。
Switch
此类型实现了一个切换按钮,可以切换或具有选中或未选中的状态。其属性如下:
checked: 这可以是true或false。如果切换按钮被选中,则为true。
pressed: 这可以是true或false。如果切换按钮被按下,则为true。
activeFocusOnPress: 这可以是true或false。如果为true,则按下时切换将获得焦点。
exclusiveGroup: 这是切换按钮所属的组。
style: 此组件使用SwitchStyle类型为此按钮提供样式。在此类型中,groove和handle属性可用。groove可以实现一个项目,例如矩形。
Slider
这用于提供一个可以水平或垂直移动的滑动手柄。属性如下:
value: 这是滑块的当前值(默认为0.0)。
minimumValue: 这是滑块的最低值(默认为0.0)。
maximumValue: 这是滑块的最大值(默认为1.0)。
stepSize: 这是滑块的步长。默认值0.0表示连续范围。
tickmarksEnabled: 这可以是true或false。如果是true,则滑块将显示刻度。
updateValueWhileDragging: 这可以是true或false。如果是true,则通过移动滑块手柄更新当前值。否则,它将在释放时更新。
orientation: 这个整数是滑块的横向或纵向方向(默认为Qt.Horizontal)。
hovered: 这可以是true或false。如果true,则此滑块手柄正在被悬停。
pressed: 这可以是true或false。如果滑块手柄被按下,则返回true。
activeFocusOnPress: 这可以是true或false。如果true,则当按下时滑块将被聚焦。
style: 此组件使用SliderStyle类型为滑块设置样式。在此类型中,有control、groove、handle、panel和tickmarks属性可用。
SpinBox
此类型允许用户通过点击上下按钮或输入值来选择一个值。此类型的属性如下:
value: 这是微调框的当前值(默认为0.0)。
minimumValue: 这是微调框范围内最小值(默认为0.0)。
maximumValue: 这是微调框范围内最大值(默认为1.0)。
stepSize: 这是按下上下按钮时将增加或减少的步长。
prefix: 这是一个string,为该值添加前缀,例如$。
suffix: 这是一个string,为该值添加后缀,例如ms。
decimals: 这个整数是微调框的小数位数(默认为0)。
inputMethodComposing: 这可以是true或false。微调框可以部分输入来自输入法的内容。
cursorPosition: 这是微调框中光标的整数位置。
selectByMouse: 这可以是true或false。微调框的值可以通过鼠标选择(默认为true)。
hovered: 这可以是true或false,如果微调框正在被悬停,则为true。
horizontalAlignment: 这个整数值将使框与Qt.AlignLeft、Qt.AlignHCenter或Qt.AlignRight对齐。
font: 这为微调框的值设置字体。
activeFocusOnPress: 这可以是true或false,如果true,则当按下时微调框将被聚焦。
menu: 此组件使用菜单类型设置用于文本选择的菜单。
style: 此组件使用SpinBoxStyle类型提供微调框样式。此类型具有background、control、decrementControl、incrementControl、horizontalAlignment、font、renderType、selectedTextColor、selectionColor和textColor属性。
BusyIndicator
此类型提供了对操作进度的指示,例如加载、下载和安装。它用于通过图形元素通知用户操作进度。此类型有两个属性:
running: 这可以是true或false。该元素将指示活动正在进行(默认为true)。
style: 此组件通过使用control和indicator属性,使用BusyIndicatorStyle类型为此指示器提供样式。
控件实现
让我们在本章中描述的一些控件在我们的应用程序中实现。在qmls/目录下创建一个名为USplit.qml的文件,并写入以下行:
- 将
SplitView添加到父Item:
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 1.4
Item {
SplitView {
anchors.fill: parent;
orientation: Qt.Vertical;
resizing: true
...
...
...
这实现了文本和表格窗口的按钮分割视图。
- 将第一个矩形作为
SplitView元素添加:
...
...
...
Rectangle {
id: scr1; color: "#111F1F"
Layout.minimumHeight: parent.height / 2
Text {
id: tx1; anchors.centerIn: parent
text: "Texts"; color: "grey"
font: {
font.pixelSize=scr1.width / 8;
font.letterSpacing=5;
font.weight=Font.ExtraBold;
}
}
MouseArea {
id: ma1; anchors.fill: parent;
hoverEnabled: true
onEntered: scr1.color = "lightgrey";
onExited: scr1.color = "#111F1F";
onClicked: {
txs1.visible = true;
grid1.visible = false;
main_item = false;
tb1.visible = true;
}
}
}
...
...
如果单击此矩形,将显示包含各种文本字段的窗口。
- 将第二个矩形添加到
USplit.qml文件中:
...
...
...
Rectangle {
id: scr2; color: "#111F1F"
Layout.fillHeight: true
Text {
id: tx2; anchors.centerIn: parent
text: "Table"; color: "grey"
font: {
font.pixelSize=scr1.width / 8;
font.letterSpacing=5;
font.weight=Font.ExtraBold;
}
}
MouseArea {
id: ma2; anchors.fill: parent
hoverEnabled: true
onEntered: scr2.color = "lightgrey";
onExited: scr2.color = "#111F1F";
onClicked: {
tb1.visible = true;
grid1.visible = false;
main_item = false;
txs1.visible = false;
}
}
}
}
}
如果单击第二个矩形,应用程序中将显示包含表格的窗口。我们可以通过运行应用程序看到类似的结果。Texts和Table选项的分割视图显示在应用程序窗口的右下角:

现在,让我们在qmls/目录中创建一个UTexts.qml文件来演示文本字段和附加组件:
- 将
GridLayout添加到UTexts.qml文件中:
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
GridLayout {
...
...
对话框用于在应用程序中实现字体和颜色对话框窗口。元素将使用网格布局定位机制排列。
- 将
TextArea添加到GridLayout中:
...
...
TextArea {
id: ta1; Layout.column: 0
Layout.rowSpan: 5; Layout.columnSpan: 3
Layout.fillWidth: true; Layout.fillHeight: true
Layout.minimumWidth: parent.width / 2
font.pixelSize: sl1.value
textColor: "lightgrey"; textMargin: 10
}
...
这设置了文本区域的属性,例如font.pixelSize、textColor和textMargin。
- 在
TextArea类之后添加Calendar:
...
...
Calendar {
id: cd1; Layout.row: 0
Layout.column: 3
Layout.columnSpan: 2
Layout.fillWidth: true
Layout.fillHeight: true
}
...
日历将在应用程序窗口的右上角显示。
- 然后,添加
Slider组件:
...
...
Slider {
id: sl1
Layout.row: 1
Layout.column: 3
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: parent.height / 24
updateValueWhileDragging: true
minimumValue: 0
maximumValue: 100
value: 19
}
...
Slider将增加或减少文本区域的大小。
- 在
Slider之后添加ComboBox:
...
...
ComboBox {
id: cb1
Layout.row: 1
Layout.column: 4
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: parent.height / 24
model: ["Dialogs", "Change Font", "Change Color"]
currentIndex: 0
onCurrentIndexChanged: {
if (currentText=="Change Font") {
fontd1.open(); cb1.currentIndex = 0;};
if (currentText=="Change Color") {
colord1.open(); cb1.currentIndex = 0;};
}
FontDialog {
id: fontd1
onAccepted: {
ta1.font = fontd1.currentFont;
fontd1.visible = false;
}
onRejected: fontd1.visible = false;
}
ColorDialog {
id: colord1
onAccepted: {
ta1.textColor = colord1.currentColor
colord1.visible = false
}
onRejected: colord1.visible = false;
}
}
...
此组合框允许静态对话框窗口在文本区域中更改颜色和字体。
- 然后,添加单选按钮:
...
...
ExclusiveGroup { id: exgr }
GridLayout {
columns: 1
Layout.row: 2
Layout.column: 3
Layout.rowSpan: 2
Repeater {
id: rbrep1; model: ["1 line of the text",
"1000 lines of the text"]
RadioButton {
exclusiveGroup: exgr
Layout.fillWidth: true
Layout.fillHeight: true
style: RadioButtonStyle {
background: Rectangle {
color: "#000F1F"
}
label: Text {
text: modelData
color: "lightgray"
font.pixelSize: 14
font.letterSpacing: 2
}
}
}
Component.onCompleted: {
rbrep1.itemAt(0).checked = true;
}
}
}
...
ExclusiveGroup类型将这些单选按钮分组,并允许只进行一个选择。
- 将复选框添加到应用程序中,并使用
GridLayout排列:
...
...
GridLayout {
columns: 1
Layout.row: 2
Layout.column: 4
Layout.rowSpan: 2
Repeater {
id: rbrep2; model: ["Month number",
"Milliseconds",
"Scidate"]
CheckBox {
Layout.fillWidth: true
Layout.fillHeight: true
style: CheckBoxStyle {
background: Rectangle {
color: "#000F1F"
}
label: Text {
text: modelData
color: "lightgray"
font.pixelSize: 14
font.letterSpacing: 2
}
}
}
}
}
...
这些复选框允许在文本区域字段中选择各种日期实现。可以选择一个选项,或同时选择所有选项。
- 然后,添加单行
TextField:
...
...
TextField {
id: tf1
Layout.row: 4
Layout.column: 3
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: rx1.height
horizontalAlignment: TextInput.AlignHCenter
font.pixelSize: rx1.height / 2
style: TextFieldStyle {
background: Rectangle {radius: 7}
}
}
...
在此文本字段中,将显示文本区域中的字符总数。
- 添加代表此窗口主按钮的
Rectangle项:
...
...
Rectangle {
id: rx1; Layout.row: 4
Layout.column: 4
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: cb1.height * 2
radius: 14; color: Qt.rgba(0.2, 0.2, 0.2, 1);
Text {
id: rtxt1
anchors.centerIn: parent
visible: true
text: "Ok"; color: "green"
font.pixelSize: parent.width / 8
}
BusyIndicator {
id: bi1
anchors.centerIn: parent
running: false
}
Timer {
id: t1; interval: 300
running: false
repeat: false
onTriggered: rx1.txdate();
}
...
...
此自定义矩形使用Text类型为此按钮上的文本;BusyIndicator,它将指示进程正在进行;以及Timer,它设置interval。
- 现在我们需要向此
Rectangle项添加一个 JavaScript 函数:
...
...
...
function txdate() {
var sd = cd1.selectedDate;
var dateform = sd;
if (rbrep2.itemAt(0).checked==true) {
dateform = dateform + ",
month-" + (cd1.visibleMonth + 1);
} else {dateform = dateform};
if (rbrep2.itemAt(1).checked==true) {
dateform = dateform + ",
milliseconds: " + Date.parse(sd)
} else {dateform = dateform};
if (rbrep2.itemAt(2).checked==true) {
var sdy = sd.getFullYear().toString();
var sdmi = sd.getMonth() + 1;
var sdm = sdmi.toString();
var sdd = sd.getDate().toString();
var sdh = sd.getHours().toString();
var sdmt = sd.getMinutes().toString();
var sds = sd.getSeconds().toString();
var scid = sdy + sdm + sdd + sdh + sdmt + sds;
dateform = dateform + ", scidate: " + scid;
} else {dateform = dateform};
if (rbrep1.itemAt(0).checked==true) {
ta1.text = dateform; tf1.text = ta1.length;
bi1.running = false; rtxt1.text = "Ok"
};
if (rbrep1.itemAt(1).checked==true) {
for (var i = 0; i<1000; i++) {
ta1.append(dateform);
if (i==999) {
tf1.text = ta1.length; bi1.running = false;
rtxt1.text = "Ok";
};
}
};
}
...
...
此 JavaScript 函数将操作数据并将结果设置到文本区域。
- 最后,将
MouseArea类型添加到此矩形中:
...
...
...
MouseArea {
anchors.fill: parent;
hoverEnabled: true
onEntered: {
rx1.color = Qt.rgba(0.25, 0.25, 0.25, 1);
rtxt1.color = "lightgreen";
}
onExited: {rx1.color = Qt.rgba(0.2, 0.2, 0.2, 1);
rtxt1.color = "green";}
onClicked: {
rtxt1.text = "";
bi1.running = true;
t1.running = true;
}
}
}
}
这个鼠标区域将与矩形一起使用,以实现点击和悬停效果。现在我们可以启动应用程序。为此,请在右下角选择Texts选项,并看到类似以下的结果:

现在,我们可以在同一目录下创建一个UTable.qml文件,以便我们可以在 GUI 应用程序中实现一个简单的表格:
- 将表格视图添加到
UTable.qml文件中:
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
GridLayout {
TableView {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 50
TableViewColumn {
horizontalAlignment: Text.AlignHCenter
role: "num1"; title: "Title 1"
}
TableViewColumn {
horizontalAlignment: Text.AlignHCenter
role: "num2"; title: "Title 2"
}
TableViewColumn {
horizontalAlignment: Text.AlignHCenter
role: "num3"; title: "Title 3"
}
...
...
TableView QML 类型在应用程序中创建一个表格。TableViewColumn类型用于此表格的列,并具有标题和角色属性。
- 将
style和model属性添加到表格中:
...
...
...
style: TableViewStyle {
textColor: "red"
}
model: ListModel {
id: lm1
ListElement {
num1: "1_1"; num2: "1_2"; num3: "1_3"
}
ListElement {
num1: "2_1"; num2: "2_2"; num3: "2_3"
}
ListElement {
num1: "3_1"; num2: "3_2"; num3: "3_3"
}
}
}
}
此表格中的数据是通过TableView类型的model属性实现的。ListModel类型包含具有指定数据的ListElement类型,这些数据与每个单元格相关的标题相关。表格看起来如下所示:

我们有三个列,每个单元格都有数据。
布局
如果我们运行应用程序并尝试使用全屏按钮或鼠标等控件调整窗口大小,我们将得到一些不可调整大小的视图。这可能是由于不可调整大小的项目,或者因为某些项目的位置可能不适合应用程序。其中一个原因是项目和元素具有固定的位置和大小。QtQuick的Layouts子模块试图解决这些问题。此子模块用于在 UI 中排列项目。此外,Layouts QML 类型调整其项目的大小,这使得它们非常适合应用程序视图。借助Layouts子模块,所有项目都将根据窗口大小调整而重新排列。在本章末尾,我们将描述如何使用布局表示法排列 GUI 项目。Qt Quick 的Layouts子模块具有以下import语句:
import QtQuick.Layouts 1.3
让我们来看看可以用于为项目提供布局排列的类型。
布局
网格/行/列布局的基本 QML 类型具有以下属性,可用于布局构造:
column: 这是一个整数,用于指定项目在布局中的列位置。
row: 这是一个整数,用于指定项目在布局中的行位置。
columnSpan: 这个整数是项目占用的列数。
rowSpan: 这个整数是项目占用的行数。
fillWidth: 这可以是true或false。如果为true,则项目将具有布局中占用单元格的完整宽度。
fillHeight: 这可以是true或false。如果为true,则项目将具有布局中单元格的完整可用高度。
maximumWidth: 这设置了单元格中项目的最大可用宽度。
maximumHeight: 这设置了单元格中项目的最大可用高度。
minimumWidth: 这设置了布局单元格中项目可用的最小宽度。
minimumHeight: 这设置了项目可用的最小高度。
preferredWidth: 这是布局中项目首选的宽度。默认设置为-1或项目的implicitWidth。它与一些具有自然大小的项目相关,如图像和文本。
preferredHeight: 这是布局中项目首选的宽度(默认为-1)。
margins: 这设置了布局中项目外所有边的边距。
topMargin: 这设置了项目外的顶部边距。
leftMargin: 这设置了项目外的左边距。
bottomMargin: 这是布局中项目外的底部边距。
rightMargin: 这是项目外的右边距。
alignment: 布局单元格内项目的对齐方式。
这些属性在项目声明中使用,以下是一个示例语法:Layout.fillWidth: true。
列布局
此类型按列排列项。它有两个属性:
layoutDirection: 这个枚举是布局中项目的方向(默认是Qt.LeftToRight)。也可以使用Qt.RightToLeft。
spacing: 这是列中每个单元格之间的间距(默认为5)。
行布局
此 QML 类型将按行排列布局中的项。它有两个属性:
layoutDirection: 这个枚举是布局中项目的方向(默认是Qt.LeftToRight)。也可以使用Qt.RightToLeft。
spacing: 这是行中每个单元格之间的间距(默认为5)。
网格布局
这是最推荐的布局实现类型。它通过元素的行/列位置来排列网格中的项。此类型具有以下属性。请注意,这些属性不是附加的,可以直接在GridLayout声明中使用(而不是在布局项中使用):
columns: 这个整数是列限制。它指定了在布局中用于项目位置的列数。
rows: 这个整数是定位项的行限制。
columnSpacing: 这是布局中每列之间的间距。
rowSpacing: 这是每行之间的间距。
flow: 这个枚举是布局中未明确指定位置的项目流方向。默认是GridLayout.LeftToRight。也可以使用GridLayout.TopToBottom。
layoutDirection: 这个枚举是布局中项目的方向。默认是Qt.LeftToRight。也可以使用Qt.RightToLeft。
完成布局
为了展示与使用固定定位相比布局构造的优势,让我们重新构建u_qml.qml文件,该文件由固定大小的元素组成,并使用GridLayout实现:
- 将
GridLayout添加到u_qml.qml文件中:
...
import QtQuick.Layouts 1.3
...
UQml.Window {
...
GridLayout {
id: main_grid1
columns: 1
rows: 1
anchors.fill: parent
Uqmls.URect {
Layout.column: 0; Layout.row: 0
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: w1.height
id: rect1
...
}
}
...
这是应用中 rect1 排布的 GridLayout。
- 在第一个
GridLayout之后,添加第二个GridLayout:
...
...
GridLayout {
id: main_grid2
columns: 1
rows: 1
anchors.fill: parent
Uqmls.URect {
Layout.column: 0; Layout.row: 0
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignRight
Layout.maximumWidth: w1.width / 5
id: rect2
visible: false
color: "#000F1D"
...
...
...
这是应用中 rect2 排布的 GridLayout。
- 为第二个矩形的按钮添加
GridLayout:
...
...
...
...
GridLayout {
id: but_grid
columns: 1
rows: 4
anchors.fill: parent
Uqmls.UButton {
id: ubut1
Layout.column: 0
Layout.row: 0
Layout.maximumHeight: w1.height / 5
Layout.fillWidth: true
Layout.fillHeight: true
...
}
Uqmls.UButton {
id: ubut2
Layout.column: 0
Layout.row: 1
Layout.maximumHeight: w1.height / 5
Layout.fillWidth: true
Layout.fillHeight: true
...
}
Uqmls.UButton {
id: ubut3
Layout.column: 0
Layout.row: 2
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumHeight: w1.height / 5
...
}
...
...
...
...
...
右侧面板的按钮将使用 GridLayout 定位排列。
- 通过向
SplitView添加一些属性来完成此文件:
...
...
...
...
...
Uqmls.USplit {
id: spl1
visible: true
Layout.column: 0
Layout.row: 3
Layout.maximumHeight: w1.height / 5
Layout.fillWidth: true
Layout.fillHeight: true
}
}
}
}
}
此 SplitView 将排列在第二个矩形的按钮网格布局中。现在我们可以运行 u_app.py 文件并检查它是否正确。完整的示例可在本书的 GitHub 仓库中找到。
摘要
在本章中,我们介绍了 QtQuick 模块——在 Qt 框架中处理 QML 的基本库。我们学习了重要概念,如布局、控件和一些附加字段。对于详细信息,你必须查阅官方文档。
现在,我们将中断对 QML 的探索,进入下一阶段,并使用具有 Python 绑定的图形 Qt 库,这是本书的主要目标。
在下一章中,我们将学习与 Python 相关的库,如 PyQt 和 PySide。这将给我们带来 Python 的实践经验,我们将使用 Qt 中的所有最佳功能。
第四章:开始使用 PyQt 和 PySide
在本章中,我们将打下基础,以便我们可以使用 Python 绑定(如 PyQt 和 PySide)开始创建 GUI。这些绑定能够利用所有 Python 编程语言的功能和 Python 世界中可用的各种基于 Python 的工具,再加上强大的 Qt 框架,这反过来又允许我们在真实且功能广泛的 GUI 应用程序中可视化我们的想象和开发过程。
在本章中,我们将介绍以下内容:
-
PyQt 与 PySide 的比较
-
PyQt5
-
PySide2
PyQt 与 PySide 的比较
如我们所见,PyQt 和 PySide 代表了 Python 编程语言功能与 Qt 库的绑定。这些工具非常相似,仅提供了使用 C++实现 Python 语法的功能,因为 Qt 基本上是基于 C++语言的框架。这些绑定作为一组 Python 模块实现,包含实现 GUI 和基础设施的类。PySide 是由社区管理的 Qt 项目(qt-project.org),而 PyQt 是由英国公司 Riverbank Computing(riverbankcomputing.com)开发的绑定。在撰写本书时,这些绑定的最新版本都支持 Qt5.x 框架,包括 PySide2 和 PyQt5 版本。在本书中,我们将使用绑定的最新版本,即 PyQt5 和 PySide2。这些版本可以从官方来源下载和安装,使用pip或其他可用的包管理器。
下载和安装
要开始使用 Python 这些工具,你需要完成以下操作:
- 从
www.python.org/downloads/下载并安装了 Python
在 PyQt5 的情况下,你需要完成以下操作:
-
构建并安装了 SIP
-
从官方来源或使用
pip下载并安装了 PyQt5 包:
> pip3 install PyQt5
在 PySide2 的情况下,你需要完成以下操作:
-
安装了 libclang
-
从官方来源下载并安装了 PySide2 包:
> python -m pip install --index-url=http://download.qt.io/snapshots/ci/pyside/5.11/latest pyside2 --trusted-host download.qt.io
另一个最推荐的选项是下载并安装 Anaconda 工具集。Anaconda 默认已安装 PyQt5 并准备好使用。此外,可以使用 cmd/Terminal 中的命令安装 PySide2 绑定:
> conda config --add channels conda-forge
> conda install pyside2
最后,可以使用 Anaconda Navigator 安装 PySide2,这是默认提供的一个工具。
在本书中,将使用 Python 2.x 的 Anaconda 环境中的 PySide2 和 Python 3.x 的 PyQt5。这避免了众多版本冲突,并获得了关于 2.x/3.x 版本在实际中差异的必要知识。
PyQt5 与 PySide2 绑定的区别
假设 Python 和 Qt 绑定已安装,让我们描述一下 PyQt 和 PySide 之间的一些差异。这些差异在所讨论的时期内可能不是恒定的,并且将来可能会被排除。首先,有不同的 import 语句。
对于 PyQt5 绑定,import 的语法如下:
from PyQt5 import QtWidgets
对于 PySide2 绑定,使用以下 import 语句:
from PySide2 import QtWidgets
如我们所见,区别在于用于导入模块的绑定名称。导入某些模块或类的语句可能不同。
例如,PyQt5 导入 Qt 的 import 语句如下:
from PyQt5.Qt import Qt
但在 PySide2 中,情况不同:
from PySide2.QtCore import Qt
此外,其他类可能有不同的导入位置。建议学习 PyQt5 和 PySide2 绑定模块和类的导入位置,以及所使用的版本。
PySide2 绑定仅支持 API 2,这意味着包括 QStrings、QStringLists 和 QVariants 在内的类不可用。
信号和槽有一些不同的语法。
PyQt5 信号的语法如下:
from PyQt5.QtCore import pyqtSignal
sig = pyqtSignal()
对于 PySide2 绑定,我们需要修改此语法,使其类似于以下:
from PySide2.QtCore import Signal
sig = Signal()
以下是一些关于语法的要点:
-
PySide2 的信号装饰器是
@Signal,而不是 PyQt5 绑定中的@pyqtSignal。 -
PySide2 不会导出 Qt 弃用的 C++ 组件。
-
在属性声明方面也存在差异。如果在 PyQt5 中看起来像
QtCore.pyqtProperty,那么对于 PySide2,这将变为QtCore.Property。 -
绑定提供了不同的工具名称。例如,PyQt5 工具名称
pyuic5在 PySide2 中将是pyside2-uic,等等。 -
PySide 使用
event()和connect()与QObject类。这些属性名不能在代码中用于其他目的。 -
通过与
QThread类一起工作,在 PySide2 中,在调用stop()后,退出应用程序时需要使用wait()。 -
PySide2 的
sender()方法在槽是一个 Lambda 函数时返回None。 -
使用 PySide2 继承时,父类构造函数始终需要被调用。
让我们看看以下代码片段:
- PyQt5 类的构造类似于以下:
class UApp(QtWidgets.QWidget):
def __init__(self, parent=None):
super(QtWidgets.QWidget, self).__init__(parent)
...
...
- 在 PySide2 中,需要在
super()函数中添加类名:
class UApp(QtWidgets.QWidget):
def __init__(self, parent=None):
super(UApp, self).__init__(parent)
...
...
- PySide2 只支持新式类,这些类可以作为 PyQt5 继承的一部分使用:
class OldStyle():
...
- 使用 PySide2,我们需要通过添加
object来更改为新式:
class NewStyle(object):
...
- 旧式信号看起来如下:
self.emit(SIGNAL('text_changed_cb'), text)
- 使用 PySide2,旧式信号需要重写如下:
self.emit(SIGNAL('text_changed_cb(QString)'), text)
- 只有没有参数的信号才会自动连接到构造函数:
action = QtWidgets.QAction(None, triggered=handler)
在前面的代码中,triggered() 信号将被连接到槽处理程序,而不是 triggered(bool) 信号。
PySide2 与shiboken2相关,这是一个 Python 绑定生成器,用于创建 PySide2 模块,并且是 Qt C++ API 到 Python 的接口。Shiboken 是一个生成器运行插件,为 CPython 扩展提供 C++代码。PyQt5 使用 SIP 绑定生成器构建,这是创建 C 和 C++库 Python 绑定的工具。
如我们所见,PyQt5 和 PySide2 之间的差异并不是比较的核心点。所有这些问题都可以轻松预防。在本书中,我们将尝试避免与绑定版本、语言和框架功能相关的限制和限制。因此,正如我们之前提到的,我们将使用最新的 Anaconda 2 环境用于 PySide2,最新的 Anaconda 3 环境用于 PyQt5。此外,还将采用现代编程方法,包括使用新式类。
社区内经常出现关于 PyQt5 和 PySide2 之间差异的问题,这些问题与这些绑定软件的许可证有关。PySide2 采用 GNU 较宽松的通用公共许可证(LGPL)或 Qt 商业许可证,作为 PyQt5 的对抗,PyQt5 采用 Riverbank 商业许可证或 GPL v3。此外,PySide2 的一些第三方组件可能采用不是 LGPL 的许可证。如果您打算将软件用于商业目的,您需要仔细阅读这些许可证规则。
PyQt5
我们将通过探索 PyQt5 绑定到 Qt 框架来开始我们的 Python GUI 创建学习。正如我们之前提到的,PyQt5 是 Qt 公司提供并由 RiverBank Computing 开发的 Qt 应用程序框架的绑定。在撰写本文时,PyQt5 可以在 Windows、Linux、Unix 平台、macOS、Android 和 iOS 上使用。下载的 PyQt5 包不包含 Qt,到现在为止,您必须已经从官方来源下载并安装了正确的许可证版本的 Qt 框架。PyQt5 是双许可软件,许可协议为 Riverbank 商业许可证和 GPL v3。这意味着如果使用 GPL 许可证,则开发者提供的代码也必须使用兼容的许可证。PyQt5 模块包含以下内容:
-
基础:
Qt:这是模块的整合,如 Qt 库——所有类的基类。这是 Qt 库的基类。
-
带有 GUI 创建的基本:
-
QtCore:这些是 Qt 的核心类;它们提供核心功能,如信号/槽或元素对齐。 -
QtWidgets:这是用于创建桌面应用程序类(如创建窗口)的 GUI。 -
QtGui:这些是用于小部件和 GUI 的核心类,如添加图标、处理颜色和文本。 -
QtPrintSupport:这为应用程序提供了本地/远程打印功能集成,能够生成 PostScript 和 PDF 文件。 -
QtMultimedia:这些是多媒体内容类和用于访问相机和收音机的 API。它包含音频和视频类。 -
QtMultimediaWidgets:这些是多媒体小部件和控制的附加类,例如视频小部件。 -
QtSql:这提供了与 SQL 数据库的集成。这包括 SQL 数据库、驱动程序、字段、表模型和查询类。 -
QtSvg:这提供了对结构化矢量图形(SVG)内容的渲染支持。
-
-
QML:
-
QtQml:用于将 QML 语言基础设施与 PyQt5 应用程序集成的类。 -
QtQuick:为 QML 用户界面提供扩展。 -
QtQuickWidgets:用于在传统小部件中渲染 QML 场景。
-
-
Devices, networking, and the web:
-
QtBluetooth:这些是用于连接蓝牙设备的类,例如扫描设备、收集信息和交换数据。 -
QtNfc:这提供了连接 NFC 设备(设备使用的近场通信协议)的类。 -
QtNetwork:这些是核心网络类。这有助于创建 UDP 和 TCP 客户端和服务器,并包括实现 HTTP 客户端和支持 DNS 查询的类。提供了与套接字、网络配置和 SSL 证书一起工作的选项。 -
QtNetworkAuth:这些是用于网络授权(OAuth)的类。 -
QtWebChannel:这是用于启用服务器、Python/QML 应用程序和客户端、HTML/JavaScript 或 QML 应用程序之间的点对点通信的类。 -
QtWebEngine:这些是用于将 QML WebEngine 对象与 Python 集成的类。 -
QtWebEngineCore:这些是核心网络引擎类。 -
QtWebEngineWidgets:这提供了一个基于 Chromium 的网络浏览器。 -
QtWebSockets:这是 WebSocket 协议的实现。 -
QtPurchasing:这提供了应用内购买、App Store 和 Google Play 支持。
-
-
3D:
-
Qt3DAnimation:用于在模拟中应用于对象属性的动画的类。 -
Qt3DCore:用于近实时模拟系统的核心类,具有 2D 和 3D 渲染。 -
Qt3DExtras:提供预构建元素(如几何形状、网格和材质以及相机控制器)的类。 -
Qt3DInput:用于处理 Qt3D 用户输入的类。 -
Qt3DLogic:与 Qt3D 后端同步帧。 -
Qt3DRender:用于 Qt3D 的 2D 和 3D 渲染类。 -
QtDataVisualization:包含将数据以表面图、条形图和散点图的形式可视化的类。
-
-
XML:
-
QtXml:提供简单 API 的类,用于 XML(SAX)和文档对象模型(DOM)接口,用于 Qt 框架的 XML 解析器。 -
QtXmlPatterns:用于额外 XML 技术的类,如 XPath 和 XQuery、可扩展样式表语言转换(XSLT)和 XML 架构验证。
-
-
Utilities:
-
QtLocation: 这提供了创建具有来自流行位置服务(提供导航信息和地理编码)的数据的映射应用程序的类,包括地点搜索。 -
QtPositioning: 此模块提供了用于处理来自卫星、Wi-Fi 等定位信息的类,可用于在地图上确定位置。 -
QtSensors: 这提供了用于处理系统硬件传感器的类,例如陀螺仪和加速度计、高度计、环境光和温度传感器,以及磁力计。 -
QtSerialPort: 此模块提供了用于处理系统串行端口的类,以及配置、I/O 操作、获取和设置 RS-232 引脚的控制信号的类。 -
QtDBus: 这提供了用于处理 D-Bus 协议的类——进程间通信(IPC)和远程过程调用(RPC)机制。它被设计为允许系统级进程(如打印机硬件驱动服务)与其他用户进程之间的交互。 -
QAxContainer: 这提供了提供对 ActiveX(互联网启用组件)控件和 COM 对象访问的类。 -
QtChart: 这提供了创建 2D 图表的类。这些包括线形和样条图、面积和散点图、条形图、饼图、箱线图、蜡烛图和极坐标图。 -
QtDesigner: 一个模块,其中包含提供使用 Python 扩展 Qt Designer 的类的扩展。 -
QtHelp: 允许在应用程序中创建/查看可搜索的帮助和文档的类。 -
uic: 用户界面编译器(uic)处理使用 Qt Designer 图形界面工具创建的文件,并从创建的gui.ui文件生成 Python 代码。 -
QtTest: 这为应用程序提供单元测试。它包括QSignalSpy类,该类提供了对信号和槽的反射。
-
-
附加内容:
-
QtAndroidExtras: 专门针对 Android 平台的类。 -
QtMacExtras: 专门针对 macOS 和 iOS 平台的类。 -
QtWinExtras: 专门针对 Windows 的类,例如任务栏按钮上的进度指示器和缩略图工具栏。 -
QtX11Extras: 专门针对 X11 窗口系统的类。
-
此外,PyQt5 框架还提供了一些实用程序:
-
pyuic5: 一个实用工具,可以将使用 Qt Designer 图形工具创建的gui.ui文件转换为标准 Python 代码。 -
pyrcc5: 一个实用工具,可以将图标、图像、翻译文件等嵌入到任何 Python 模块中,如资源收集文件所述。 -
pylupdate5: 一个实用工具,用于从 Python 代码中提取可翻译的字符串并创建/更新翻译文件。
PySide2
如我们之前提到的,PySide2 库是将提供这些类耦合在一起,以便可以使用 Python 使用 Qt。它由 Qt 项目社区开发。这些库(PyQt 和 PySide)非常相似,并且使用主 Qt 功能来创建 Python 的 GUI。在这方面,PySide2 便于在 Python 应用程序中使用 Qt5 API。这为软件开发者提供了使用 Qt 全部潜力的能力。PySide2 模块提供了对 Qt 各个模块的访问,例如 Qt Widgets、Qt Core 和 Qt GUI。其中一些将重复前面的内容,但为了比较目的,有必要在这里描述这些模块:
-
GUI 创建:
-
QtCore: 这是提供核心非 GUI 功能的类,它提供核心功能信号/槽或组件校准,类似于 PyQt5 库。 -
QtWidgets: 这实现了 C++ 类以扩展 Qt GUI 小部件功能,并提供图形组件,如按钮、窗口和小部件。 -
QtGui: 这在 Qt 库中具有用于窗口系统和图形的类,例如事件、OpenGL、OpenGL ES 和 Vulkan 集成;2D 图形;图像处理;字体排印字体;和颜色。 -
QtPrintSupport: 这是 Qt 库的跨平台打印功能。 -
QtMultimedia: 这为音频、视频、广播、摄像头等提供了低级多媒体功能。 -
QtMultimediaWidgets: 这些类用于从 Qt Multimedia Widgets 模块创建多媒体小部件。 -
QtSql: 这是应用程序中数据库实现的模块。这包括驱动程序、SQL API 和 SQL 数据库的用户界面层。 -
QtSvg: 这提供了显示 SVG 文件的类,例如渲染(QSvgRenderer)和绘图(QSvgWidget)。 -
QtConcurrent: 这提供了用于代码并发执行的 API 功能。它可以用于编写不需要使用低级线程原语(如互斥锁、读写锁、等待条件或信号量)的多线程应用程序结构。
-
-
QML:
-
QtQml: 这是为 Qt QML 基础设施提供的 Python API。 -
QtQuick: 这是在 Qt/C++ 应用程序中用于 Qt Quick 的类。 -
QtQuickWidgets: 这是在基于小部件的应用程序中用于 Qt Quick 的QQuickWidget类。
-
-
网络和网页:
-
QtNetwork: 这是一个网络编程类,允许创建 UDP 和 TCP 客户端和服务器,并包括实现 HTTP 客户端和支持 DNS 查询的类。提供了与套接字、网络配置和 SSL 证书一起工作的选项。 -
QtWebChannel: 这是一个用于服务器和客户端 HTML/JavaScript 或 QML 应用程序之间点对点通信的类。 -
QtWebEngineCore: 核心功能是将网页内容、由QtWebEngine共享的公共 API 以及QtWebEnginEWidgets类融合在一起。 -
QtWebEngineWidgets: 这提供了一个带有常见 C++ 类的网页浏览器引擎,用于提供和协作网页内容。 -
QtWebSockets: 为 Qt 应用程序提供接口,可以作为服务器/客户端处理 WebSocket 请求或从服务器接收数据。这还包括启用基于套接字通信的 C++ 类。
-
-
3D:
-
Qt3DAnimation: 这是一个提供用于在 Qt 框架中动画化 3D 对象的基本元素的模块。 -
Qt3DCore: 这是 Qt3D 模块,包含用于近实时模拟的核心类型类,基于 Qt3D 框架构建。 -
Qt3DExtras: 这提供了与 Qt3D 一起工作的预构建元素。 -
Qt3DInput: 这是一个提供用于处理 Qt3D 用户输入的类的模块。 -
Qt3DLogic: 这提供了与 Qt3D 后端同步帧的类。 -
Qt3DRender: 这是一个包含用于 Qt3D 的 2D/3D 渲染类别的模块。 -
QtDataVisualization: 这提供了将数据以表面图、条形图和散点图的形式可视化的类。
-
-
XML:
-
QtXml: Qt 应用程序中简单 API(SAX)和 DOM 接口的 C++ 实现。 -
QtXmlPatterns: XQuery、XPath、XSLT 和 XML 架构验证。 -
QtScxml: 用于从 SCXML 文件创建状态机类。
-
-
实用工具:
-
QtLocation: 这提供了用于位置和导航信息的 C++ 接口。 -
QtPositioning: 这通过 QML 和 Python 接口提供对卫星和区域监控数据的定位访问。 -
QtSensors: 这通过 QML 和 Python 接口提供了读取系统传感器硬件的类。它还提供了一个运动手势识别 API。 -
QAxContainer: 这提供了QAxObject对象和QAxWidget小部件,它们用作 ActiveX 控件和 COM 对象的容器。 -
QtCharts: 这是最常用的图表组件。 -
QtTextToSpeech: 这是一个 API,可以通过QTextToSpeechEngine、QTextToSpeech和QVoice类访问文本到语音引擎。 -
QtHelp: 这提供了在应用程序中包含在线帮助和文档的类。 -
QtUiTools: 这提供了处理 Qt Designer 表单的类。 -
QtTest: 这提供了用于 Qt 应用程序和库单元测试的类。
-
-
附加内容:
-
QtWindowsExtras: 使您能够使用许多 Windows API 与 Qt 一起使用。 -
QtMacExtras: 专门针对 macOS 和 iOS 操作系统的类。 -
QtX11Extras: 关于 X11 配置的信息。
-
应用程序构建
两个与 Qt 库绑定的 Python 模块(PyQt5 和 PySide2)在本质上相似。最常用的模块与 GUI 创建相关。这些包括 Qt Core、Qt Widgets 和 Qt GUI。正如我们所见,这些模块在 PyQt5 和 PySide2 中都是可用的。正是这些模块将在本书中详细探讨。本书中将要使用的编程方法意味着在 Python 文件中编写 Python 代码,并声明类、函数、变量等。在我们开始这个激动人心的过程之前,我们想考虑一种在设计部分创建 GUI 应用程序的不同方式——涉及 Qt Designer 的创建。
Qt Designer
这个用于使用 Qt 创建 GUI 应用的图形用户工具几乎包含在 Anaconda 工具集提供的 PyQt 和 PySide 库的所有变体中,包括 PyQt5 独立版本,或者可以下载并安装 Qt。让我们尝试使用 Qt Designer 做些事情。为此,我们只需点击图标打开 Designer,或者我们通过 cmd/Terminal 来做这件事:
for Windows
> designer.exe
or for Linux
> designer-qt5
现在,我们可以看到设计师窗口,以及创建表单、按钮、标签等选项。创建一个简单的小部件,并向其中添加一些元素,包括框架和不同的按钮,如下面的截图所示:

然后,我们需要将此文件保存为一个名称,例如 design_app。需要注意的是,Qt Designer 使用 XML *.ui 文件来存储设计,并且本身不会生成任何代码。选择“保存”选项,然后将文件保存为 design_app.ui 到 App/ 目录下。因此,我们将有一个具有 UI 扩展名和 XML 内容的文件。然而,最好将此文件作为一个包含 Python 代码的 Python 文件。为此,我们需要使用一个额外的实用工具——pyuic5(PyQt5)或 pyside2-uic(PySide2)将此代码转换为 Python。在 cmd/Terminal 中输入以下命令:
> cd /Path/to/the/App
PySide2
> pyside2-uic -o design_app.py design_app.ui
PyQt5
> pyuic5 -o design_app.py design_app.ui
现在,我们可以看到位于 App/ 目录下的 design_app.py 文件,其中包含 Python 代码。
本书将不会描述使用 Qt Designer 进行 GUI 开发。这个关于这个工具的简要介绍足以让开发者了解如何使用 Qt Designer。
开始使用 GUI
在对 Qt Designer 进行简要介绍之后,让我们继续本书的主要目标,即正确选择构建和编写具有 GUI 的应用程序的定性 Python 代码。大多数编程实践需要理解未来应用程序的功能和形式,以便欣赏应用程序中的一切是如何工作的。但我们将不会这样做。我们将使用 Python——一种实时动态编程语言,它给我们提供了在图形窗口中实现世界上几乎所有事情的机会。我们需要从低到高逐步进行。
首先,我们需要以正确的方式组织包含应用程序文件的目录。尽管本书将演示两种绑定的示例,但建议你在App/目录内创建如App/App_PySide2和App/App_PyQt5之类的目录。但如果你已经选择了某种 Python 绑定,这并不是强制性的。然后,我们需要执行我们之前章节中描述的文件重写,并添加一些更多文件。创建 GUI 应用程序有许多不同的方法。如果将要创建的 GUI 应用程序体积小、规模小或仅提供有限的功能,例如仅执行几个功能,将代码放在单个文件中是有意义的。
然而,这是一个坏主意,因为每个应用程序都可以被重建、更新、升级或通过添加额外代码来扩展。将小型应用程序拆分为多个文件对性能和生产力几乎没有任何影响,或者几乎没有影响。另一方面,将大规模应用程序代码放入单个文件会导致编辑器阅读此文件时出现问题,以及维护问题和一般性的困惑。在重建和更改功能方面也可能出现问题。例如,如果需要更改某些样式属性,将需要找到这些参数,而且总会有一些东西被忽略。GUI 应用程序通常有大量的代码行,而某些特殊操作的函数行数则较少。换句话说,以某种方式在不同文件中拆分应用程序是一个好主意,并将这些文件中的类和函数导入到具有主要 GUI 应用程序的文件中。这是编程的艺术——在正确的位置创建具有文件、类和函数的应用程序。我们需要理解,其中一些需要位于允许的空间中,以排除与命名空间相关的问题。我们将利用面向对象编程(OOP)方法,这意味着我们希望在多个地方多次使用代码,有时在未来在其他应用程序中使用。此外,GUI 应用程序的样式代码通常需要很多行。
基于此,我们将应用程序拆分为三个文件,就像它们被创建时那样:u_app.py、u_tools.py以及我们现在要添加的u_style.py文件。然后,将它们放入App/App_PySide2和App/App_PyQt5目录中。u_app.py文件将包含 GUI 应用程序的主类,以及运行它的说明。按照以下方式更改代码。
关于u_app.py文件,以下代码使用 PyQt5 创建类:
# -*- coding: utf-8 -*-
from u_tools import UTools
from u_style import UWid
class UApp(UWid, UTools):
def __init__(self, parent=None):
super(UApp, self).__init__(parent)
UTools.__init__(self)
print(self.us1)
if __name__ == "__main__":
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
print(sys.argv)
app = QtWidgets.QApplication(sys.argv)
uap = UApp()
uap.show()
sys.exit(app.exec_())
在此文件中,我们正在创建 GUI 应用程序的主类。此类将结合来自其他模块(第三方包)的所有功能,并创建应用程序。
在 PySide2 的u_app.py文件中,我们有以下内容:
# -*- coding: utf-8 -*-
from u_tools import UTools
from u_style import UWid
class UApp(UWid, UTools):
def __init__(self, parent=None):
super(UApp, self).__init__(parent)
UTools.__init__(self)
print self.us1
if __name__ == "__main__":
import sys
from PySide2 import QtWidgets, QtCore, QtGui
print sys.argv
app = QtWidgets.QApplication(sys.argv)
uap = UApp()
uap.show()
sys.exit(app.exec_())
这是与 PySide2 绑定一起用于 Qt 的主类文件。u_tools.py 文件将包含为 GUI 应用程序提供一些功能或额外功能的类和函数。
在 PyQt5 的 u_tools.py 文件的情况下,将此文件的内容更改为以下内容:
# -*- coding: utf-8 -*-
class UTools(object):
def __init__(self):
self.us1 = "Application with Python."
if __name__ == "__main__":
ut = UTools()
这是包含类的文件。我们将在这里使用一些方便的函数,这些函数与应用程序的 GUI 表示无关。
在 PySide2 的 u_tools.py 文件中,我们有以下内容:
# -*- coding: utf-8 -*-
class UTools(object):
def __init__(self):
self.us1 = "Application with Python."
if __name__ == "__main__":
ut = UTools()
在可能的情况下,我们将避免在 Python 版本和 Qt 库(PySide2/PyQt5)的 Python 绑定之间的语法、使用的模块和类之间的差异。
u_style.py 文件将包含为 GUI 应用程序提供样式的类和函数,包括小部件、按钮、标签、框架、颜色和字体。
在 PyQt5 的 u_style.py 文件中,我们有以下内容:
# -*- coding: utf-8 -*-
from PyQt5 import QtWidgets, QtCore, QtGui
color = ["rgba(0,41,59,140)",
"rgba(0,41,59,255)"]
class UWid(QtWidgets.QWidget):
def __init__(self, parent=None):
super(UWid, self).__init__(parent)
self.setWindowTitle("U App")
self.setStyleSheet("background-color: %s;" % (
color[0],))
这些样式文件将只包含与图形相关的对象和图形属性。
在 PySide2 的 u_style.py 文件中,我们有以下内容:
# -*- coding: utf-8 -*-
from PySide2 import QtWidgets, QtCore, QtGui
color = ["rgba(0,41,59,140)",
"rgba(0,41,59,255)"]
class UWid(QtWidgets.QWidget):
def __init__(self, parent=None):
super(UWid, self).__init__(parent)
self.setWindowTitle("U App")
self.setStyleSheet(
"background-color: %s;" % (
color[0],))
如我们所见,PySide2 和 PyQt5 绑定之间的唯一区别在于名称导入语句以及在打印 string 变量时的不同,这取决于不同的 Python 版本。在整个书中,随着我们添加新的元素、小部件和功能,这些文件中的代码将会被增强或更改。
目前,这些应用程序可以通过 cmd/Terminal 命令运行:
### PySide2 ###
> cd Path/to/App/App_PySide2
> Path/to/Python2/python u_app.py
### PyQt5 ###
> cd Path/to/App/App_PyQt5
> Path/to/Python3/python u_app.py
我们将得到相同的结果,换句话说,一个空的小部件:

在 cmd/Terminal 中,我们有与当通过 QApplication 传递系统参数时相同的输出,即包含应用程序名称的列表和 UTools 类的 string 变量。
应用程序功能
让我们考虑当应用程序创建并运行带有脚本的 u_app.py 文件时将执行的过程。让我们逐行查看发生了什么:
-
在
u_app.py文件中,导入部分导入UTools类,该类将提供一些功能,包括函数,或者像在这个例子中一样,包含文本的string变量。实现Qwidget(将作为图形元素显示的小部件)的UWid类也将被导入。 -
创建了
UApp类。这是应用程序的主要类,将包含工具、函数、元素以及这些元素的布局,以及额外的功能。这个类将继承UTools和UWid类以实现其功能。 -
如
if __name__ == "__main__"之类的指令指定了此文件是否将从 cmd/Terminal 或以其他方式(例如可执行脚本)运行。__name__变量将包含"__main__"值,if语句的指令将被实现。在其他情况下,如果此文件中的类、函数或变量被导入到另一个应用程序或代码中,这些指令将不会实现,导入的代码将作为另一个构造中的元素使用,这暗示了面向对象的方法。这些指令如下:-
import sys——这是从标准 Python 库中导入sys模块的方法。sys模块提供了访问用于、维护或与 Python 解释器交互的变量和函数。 -
导入
QtWidgets、QtGui和QtCore——这些是最常用的模块,用于创建应用程序、添加图形元素、处理图像、颜色和字体等特性,以及提供功能的核心函数,如事件、信号和槽以及配置。 -
从
QtWidgets模块声明QApplication类的对象:这个类的继承方案是QtCore.QObject—QtCore.QCoreApplication—QtGui.QGuiApplication—QtWidgets.QApplication。这个类为 GUI 应用程序提供了主要的设置和控制流程。对于任何 Qt GUI 应用程序,恰好有一个QApplication对象。qApp属性提供了从应用程序的任何位置访问QApplication对象的方法。此对象接受sys.argv参数,这是传递给 Python 脚本的命令行参数列表。正如我们在 cmd/Terminal 输出中看到的那样,此参数具有包含脚本的文件名(u_app.py)。 -
使用小部件创建主应用程序类的实例并调用
show()方法来可视化小部件:在另一种情况下,如果我们不实现实例且不调用show()方法,应用程序将被创建但不会在 GUI 性能中可视化,因为我们将没有可视元素(在这种情况下是Qwidget)。sys.exit(app.exec_())是执行应用程序的行;所有随后的代码行将不会执行。sys.exit()是sys模块的exit()方法,将退出 Python。这意味着如果发生错误或应用程序窗口关闭,程序将退出。app.exec_()启动应用程序的主循环,并返回状态码(成功为0),例如应用程序退出或出现某些错误,这些状态码将与sys.exit()一起使用。
-
如果我们从 cmd/Terminal 或其他方式运行该文件,并且包含应用程序定义,这将导致应用程序进入无限循环,并且将持续到应用程序关闭或出现另一个退出事件。为了演示这些功能,让我们暂时向u_app.py文件中添加一些内容,包括运行指令和一些信息性语句。
在 PyQt5 的u_app.py文件的情况下,我们有以下内容:
...
if __name__ == "__main__":
...
print(" sys list of arguments: ", sys.argv)
print("qApp list of arguments: ", QtWidgets.qApp.arguments())
print("Application Process ID: ", QtWidgets.qApp.applicationPid())
print(" Application instance: ", QtWidgets.qApp.instance())
print(" Application state: ", QtWidgets.qApp.applicationState())
print(" Application platform: ", QtWidgets.qApp.platformName())
print(" List of the widgets: ", QtWidgets.qApp.allWidgets())
sys.exit(app.exec_())
在 PySide2 的u_app.py文件的情况下,我们有以下内容:
...
if __name__ == "__main__":
...
print " sys list of arguments: ", sys.argv
print "qApp list of arguments: ", QtWidgets.qApp.arguments()
print "Application Process ID: ", QtWidgets.qApp.applicationPid()
print " Application instance: ", QtWidgets.qApp.instance()
print " Application state: ", QtWidgets.qApp.applicationState()
print " Application platform: ", QtWidgets.qApp.platformName()
print " List of the widgets: ", QtWidgets.qApp.allWidgets()
sys.exit(app.exec_())
在 cmd/Terminal 中运行这些文件:
### PyQt5 ###
> cd Path/to/App/App_PyQt5
> Path/to/Python3/python u_app.py
### PySide2 ###
> cd Path/to/App/App_PySide2
> Path/to/Python2/python u_app.py
在 PyQt5 的u_app.py文件的情况下,结果如下:

在 PySide2 的u_app.py文件的情况下,结果如下:

通过实施前面的步骤,我们已经构建了我们的应用程序!
摘要
这本书的最后一章也是第一部分的最后一章。在这一章中,我们介绍了使用 PyQt5 和 PySide2 Python 绑定创建 GUI 应用程序。接下来的所有章节都将继续这一主题。强烈建议您回顾有关不同 Python 绑定与 Qt 库比较的各种示例的代码。本章简要介绍了 PyQt5 和 PySide,这可能在选择这些框架之一时有所帮助。这两个绑定都有许多优点,也有一些缺点。
下一章将考虑QWidget和QMainWindow类,它们为显示 GUI 应用程序提供主窗口和小部件窗口。
第二部分:深入 PyQt
在本节中,我们将深入介绍 PyQt。我们将探讨我们可以用于我们的 GUI 应用程序的各种 PyQt 元素,并了解如何正确使用它们。
本节包括以下章节:
-
第五章,使用 QWidget 和主窗口
-
第六章,使用框架、标签和文本字段
-
第七章,使用组合框和列表视图
-
第八章,实现按钮
-
第九章,图形基础
-
第十章,图形表示
-
第十一章,图形效果和多媒体
-
第十二章,文件、打印机和其他对话框
-
第十三章,创建布局
-
第十四章,实现数据库
第五章:使用 QWidget 和主窗口
从本章开始,我们将探讨 GUI 应用程序的图形元素。将考虑与这些视觉对象和其他功能相关的这些方法。当开发者开始构建 GUI 时,他们需要用不同的图形对象填充此应用程序,包括框架、标签、字段、按钮以及许多其他控制元素。在本章中,我们将介绍图形组件的基本字段或它们可以可视化的地方。在 Qt/C++中,QtWidgets类通常提供此功能,并且通过 PyQt5 和 PySide2 Python 绑定可用。
本章将涵盖以下主题:
-
QWidget -
QMainWindow
QWidget
这个类是QtWidgets模块提供的所有用户界面对象的基类。正如 PySide2 文档(doc.qt.io/qtforpython/PySide2/QtWidgets/QWidget.html)中解释的那样,这是用户界面的原子。此类具有以下继承方案:

它几乎也是几乎所有图形元素、附加小部件等的父元素。声明语法如下:
widget = QtWidgets.QWidget()
QWidget 的功能
QWidget继承自QObject和QPaintDevice,并通过以下函数增强了功能。
set
这些是与小部件相关的设置参数/属性的功能,包括设置样式、宽度或功能:
widget.setAcceptDrops(bool): 如果设置为True,则小部件将接受拖放事件。
widget.setAccessibleDescription("description"): 这为该小部件提供可访问的描述。
widget.setAccessibleName("Name"): 这为该小部件提供可访问的名称。
widget.setAttribute(QtCore.Qt.WidgetAttribute, bool): 如果第二个参数为True,则在此小部件上设置属性;否则,清除属性。
widget.setAutoFillBackground(bool): 如果参数为True,则小部件的背景将自动填充。
widget.setBackgroundRole(QtGui.QPalette.ColorRole): 这将设置小部件的背景角色为QtGui.QPalette.ColorRole类型的参数角色。
widget.setBaseSize(QtCore.QSize): 这将小部件的基本大小设置为QtCore.QSize类型的参数。
widget.setBaseSize(basew, baseh): 这将小部件的基本大小设置为参数,其中basew(基本宽度)和baseh(基本高度)是整数值。
widget.setContentsMargins(QtCore.QMargins): 这将设置围绕小部件内容的QtCore.QMargins类型的边距。
widget.setContentsMargins(left, top, right, bottom): 这将设置围绕小部件内容的边距为每一边的整数值。
widget.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy): 这将设置此小部件的上下文菜单策略,即此小部件如何显示上下文菜单。
widget.setCursor(QtGui.QCursor): 这将为 QtGui.QCursor 类型的当前光标设置小部件的光标。
widget.setDisabled(bool): 如果参数为 True,则禁用小部件输入事件;否则,输入事件被启用。
widget.setEnabled(bool): 如果参数为 True,则启用已禁用的小部件输入事件。
widget.setFixedHeight(h): 这将使用整数值 h(小部件的高度)设置固定高度;小部件的高度在布局系统中不会改变。
widget.setFixedWidth(w): 这将使用整数值 w(小部件的宽度)设置固定宽度;小部件的宽度在布局系统中不会改变。
widget.setFixedSize(QtCore.QSize): 这将为小部件设置 QtCore.QSize 类型的固定大小;小部件的大小在布局系统中不会改变。
widget.setFixedSize(w, h): 这将使用整数值 w(宽度)和 h(高度)设置小部件的固定大小;小部件的大小在布局系统中不会改变。
widget.setFocus(): 如果此小部件或其父级之一是活动窗口,则将键盘输入焦点设置到此小部件。
widget.setFocus(QtCore.Qt.FocusReason): 如果此小部件或其父级之一是活动窗口,则将键盘输入焦点设置到此小部件。使用 QtCore.Qt.FocusReason 类型的原因是提供有关导致小部件获得焦点的解释。
widget.setFocusPolicy(QtCore.Qt.FocusPolicy): 这将为小部件设置焦点策略;即小部件接受键盘焦点的方式。
widget.setFocusProxy(QtWidgets.QWidget): 这将为小部件设置 QtWidgets.QWidget 类型的焦点代理。
widget.setFont(QtGui.QFont): 这将为小部件设置字体。
widget.setForegroundRole(QtGui.QPalette.ColorRole): 这将为小部件设置前景角色为参数中的角色。
widget.setGeometry(QtCore.QRect): 这将为小部件设置相对于其父级的位置,不包括窗口框架。
widget.setGeometry(x, y, w, h): 这将为小部件设置相对于其父级的位置,不包括窗口框架,参数为 x(x 轴),y(y 轴),w(宽度)和 h(高度)。
widget.setGraphicsEffect(QtWidgets.QGraphicsEffect): 这将为小部件设置图形效果。
widget.setHidden(bool): 如果此参数为 True,则将小部件设置为隐藏。
widget.setInputMethodHints(QtCore.Qt.InputMethodHints): 这将设置小部件将拥有的输入法提示。
widget.setLayout(QtWidgets.QLayout): 这将为该小部件设置布局管理器。小部件只能有一个布局管理器。如果设置新的,则需要删除之前的版本。
widget.setLayoutDirection(QtCore.Qt.LayoutDirection): 这将为该小部件设置布局方向。
widget.setLocale(QtCore.QLocale): 这将为该小部件设置区域设置。
widget.setMask(QtGui.QBitmap): 这仅设置小部件的像素,对于具有位图参数的位图,相应的位为 1,设置为可见。
widget.setMask(QtGui.QRegion): 这仅设置与区域参数重叠的小部件部分为可见。
widget.setMaximumHeight(maxh): 这使用整数值 maxh(最大高度)为此小部件设置最大高度。
widget.setMaximumWidth(maxw): 这使用整数值 maxw(最大宽度)为此小部件设置最大宽度。
widget.setMaximumSize(QtCore.QSize): 这将小部件的最大尺寸设置为 QtCore.QSize 类型的参数。
widget.setMaximumSize(maxw, maxh): 这使用整数值作为 maxw,即最大宽度,和 maxh——最大高度——参数设置小部件的最大尺寸。
widget.setMinimumHeight(minh): 这使用整数值 minh 设置小部件的最小高度,即最小高度。
widget.setMinimumWidth(minw): 这使用整数值 minw(最小宽度)为此小部件设置最小宽度。
widget.setMinimumSize(QtCore.QSize): 这将小部件的最小尺寸设置为 QtCore.QSize 类型的参数。
widget.setMinimumSize(minw, minh): 这使用整数值作为 minw,即最小宽度,和 minh——最小高度——参数设置小部件的最小尺寸。
widget.setMouseTracking(bool): 如果此参数为 True,则为此小部件设置可用的鼠标跟踪。
widget.setPalette(QtGui.QPalette): 这为此小部件设置在渲染标准组件时使用的调色板。
widget.setParent(QtWidgets.QWidget): 这将为此小部件设置 QtWidgets.QWidget 类型的参数作为父级。
widget.setParent(QtWidgets.QWidget, QtCore.Qt.WindowFlags): 这为此小部件设置父级,使用 QtWidgets.QWidget 类型的第一个参数,并使用标志作为第二个参数。
widget.setShortcutAutoRepeat(id, bool): 如果第二个参数为 True,则启用具有给定 id 的快捷键的自动重复;否则,将其禁用。
widget.setShortcutEnabled(id, bool): 如果第二个参数为 True,则启用具有给定 id 的快捷键;否则,将其禁用。
widget.setSizeIncrement(QtCore.QSize): 这为此小部件设置 QtCore.QSize 类型的尺寸增量,或用户调整窗口大小时尺寸变化的步长。
widget.setSizeIncrement(w, h): 这使用 w,即宽度,和 h,即高度,参数为此小部件设置尺寸增量,或用户调整窗口大小时尺寸变化的步长。
widget.setSizePolicy(QtWidgets.QSizePolicy): 这为此小部件设置 QtWidgets.QSizePolicy 类型的尺寸策略。
widget.setSizePolicy(horizontal, vertical): 这将为该小部件设置 horizontal,为 QtWidgets.QSizePolicy.Policy 类型的 vertical,以及 QtWidgets.QSizePolicy.Policy 类型的 vertical。
widget.setStatusTip("Status tip"): 这将为小部件设置状态提示。
widget.setStyle(QtWidgets.QStyle): 这将为小部件的 GUI 风格设置 QtWidgets.QStyle 类型的样式。
widget.setStyleSheet("{property: value;}"): 这将为小部件设置样式表,其中包含对小部件样式的自定义描述。
widget.setTabletTracking(bool): 如果此参数为 True,则启用平板电脑跟踪,或者即使在小部件附近悬停时,小部件也会接收平板电脑移动事件;否则,它为 False。
widget.setTabOrder(QtWidgets.QWidget, QtWidgets.QWidget): 这将在第一个参数的小部件之后将第二个参数的小部件纳入焦点顺序。
widget.setToolTip("Tool tip"): 这将为该小部件设置工具提示。
widget.setToolTipDuration(msec): 这将为工具提示设置持续时间——当工具提示可见时的时间以 msec(毫秒)的整数值表示。
widget.setUpdatesEnabled(bool): 如果此参数为 True,则启用小部件的更新,小部件接收绘图事件,并具有系统背景。默认情况下,更新是启用的。
widget.setVisible(bool): 如果此参数为 True,则小部件将可见,如果它之前是不可见的;否则,小部件将不可见。
widget.setWhatsThis("What's this"): 这将为小部件设置 这是什么 帮助文本。
widget.setWindowFilePath("File/path/to/the/widget"): 这将为该小部件设置关联的文件路径。
widget.setWindowFlag(QtCore.Qt.WindowType, bool): 如果第二个参数为 True,则在此小部件上设置 QtCore.Qt.WindowType 类型的窗口标志;否则,清除标志。
widget.setWindowFlags(QtCore.Qt.WindowFlags): 这将为小部件设置窗口标志。
widget.setWindowIcon(QtGui.QIcon): 这将为该小部件的窗口设置图标。
widget.setWindowIconText("Icon text"): 这将为该小部件窗口的图标设置文本。
widget.setWindowModality(QtCore.Qt.WindowModality): 这将设置模态窗口的行为,或者哪些窗口被模态小部件阻塞。
widget.setWindowModified(bool): 如果此参数为 True,则将窗口设置为已修改。
widget.setWindowOpacity(float): 这将设置与窗口相关的不透明度,其中 0.0 是完全透明的窗口,而 1.0 是完全不透明的窗口。
widget.setWindowRole(unicode): 这将为窗口设置 Unicode 字符串作为角色;这对于在 X11 上运行的 Windows 有意义。
widget.setWindowState(QtCore.Qt.WindowStates): 这将设置窗口状态,例如 QtCore.Qt.WindowMinimized、QtCore.Qt.WindowMaximized、QtCore.Qt.WindowFullScreen 或 QtCore.Qt.WindowActive。
widget.setWindowTitle("Window Title"): 这为小部件的窗口设置标题。
is/has
这些是返回与小部件状态相关的布尔值(bool)的函数,例如,检查当前状态:
widget.isActiveWindow(): 这返回True,如果小部件的窗口是活动窗口。
widget.isAncestorOf(QtWidgets.QWidget): 这返回True,如果小部件是子参数的父级。
widget.isEnabled(): 这返回True,如果小部件被启用。
widget.isEnabledTo(QtWidgets.QWidget): 这返回True,如果此小部件将变为启用状态,如果同一窗口内父小部件的参数被启用。
widget.isFullScreen(): 这返回True,如果小部件以全屏模式显示;否则,返回False。
widget.isHidden(): 这返回True,如果小部件被隐藏;否则,返回False。
widget.isLeftToRight(): 这返回True,如果小部件具有从左到右的方向。
widget.isMaximized(): 这返回True,如果小部件的窗口已最大化。
widget.isMinimized(): 这返回True,如果小部件的窗口已最小化。
widget.isModal(): 这返回True,如果小部件的窗口是模态小部件。
widget.isRightToLeft(): 这返回True,如果小部件具有从右到左的方向。
widget.isTopLevel(): 这返回True,如果小部件是顶级窗口。
widget.isVisible(): 这返回True,如果小部件是可见的。
widget.isVisibleTo(QtWidgets.QWidget): 这返回True,如果小部件将变为可见的,如果同一窗口内父小部件的参数将被显示。
widget.isWindow(): 这返回True,如果小部件是独立窗口;否则,返回False。
widget.isWindowModified(): 这返回True,如果窗口内容有未保存的更改。
widget.hasFocus(): 这根据小部件键盘是否有输入焦点返回True或False。
widget.hasHeightForWidth(): 如果小部件的首选高度取决于其宽度,它将返回True;否则,返回False。
widget.hasMouseTracking(): 这返回True,如果为小部件启用了鼠标跟踪;否则,返回False。
widget.hasTabletTracking(): 这返回True,如果启用了平板电脑跟踪或小部件接收平板电脑移动事件,即使悬停在附近;否则,返回False。
window
这些是更改当前小部件可视化的函数,例如关闭和隐藏:
widget.close(): 这将关闭小部件并返回True。
widget.hide(): 这隐藏小部件。
widget.show(): 这显示小部件及其子小部件。
widget.showFullScreen(): 这以全屏模式显示小部件。
widget.showMaximized(): 这以最大化模式显示小部件。
widget.showMinimized(): 这以最小化模式显示小部件。
widget.showNormal(): 这以正常模式显示小部件。
widget.move(QtCore.QPoint): 这会将小部件移动到 QtCore.QPoint 类型的位置。
widget.move(x, y): 这会将小部件移动到 x (X 轴) 或 y (Y 轴) 参数的位置。
widget.resize(QtCore.QSize): 这会使用 QtCore.QSize 类型的参数调整小部件的大小。
widget.resize(w, h): 这会使用 w(宽度)和 h(高度)参数作为整数值调整小部件的大小。
widget.scroll(dx, dy): 这会滚动小部件及其子部件,向右移动 dx 像素,向下移动 dy 像素。dx 和 dy 可以为负值。
widget.scroll(dx, dy, QtCore.QRect): 这会滚动小部件的矩形,不包括其子部件,向右移动 dx 像素,向下移动 dy 像素。dx 和 dy 可以为负值。
功能性
这些是与小部件当前值返回、功能变化等相关函数:
widget.acceptDrops(): 这返回 True 或 False;如果为 True,则小部件接受拖放事件。
widget.accessibleDescription(): 这返回一个 Unicode 字符串——小部件的描述。
widget.accessibleName(): 这返回一个 Unicode 字符串——小部件的名称。
widget.actions(): 这返回一个列表,其中包含作为 QtWidgets.QAction 类型的 QtCore.QList 类型的操作——小部件的操作。
widget.activateWindow(): 这会将包含此小部件的最顶层小部件设置为活动窗口。
widget.addAction(QtWidgets.QAction): 这会将操作添加到小部件的操作列表中。
widget.addActions([QtWidgets.QAction]): 这会将操作添加到小部件的操作列表中。
widget.adjustSize(): 这会调整小部件的大小以适应其内容。
widget.autoFillBackground(): 这返回 True 或 False;如果为 True,则背景会自动填充。
widget.backgroundRole(): 这返回 QtGui.QPalette.ColorRole 类型的颜色角色——小部件的背景角色。
widget.baseSize(): 这返回 QtCore.QSize 类型的基本大小——小部件的基本大小。
widget.childAt(QtCore.QPoint): 这返回小部件在点位置上的子小部件。
widget.childAt(x, y): 这返回小部件在坐标系中由 x (X 轴) 或 y 轴的位置的子小部件。
widget.childrenRect(): 这返回一个 QtCore.QRect 类型的矩形——小部件子部件的边界矩形。
widget.childrenRegion(): 这返回一个 QtGui.QRegion 类型的区域——小部件子部件占用的合并区域。
widget.clearFocus(): 这会移除小部件的键盘输入焦点。
widget.clearMask(): 这会移除由 QtWidgets.QWidget.setMask() 设置的掩码。
widget.contentsMargins(): 这返回 QtCore.QMargins 类型的边距——小部件的内容边距。
widget.contentsRect(): 这返回一个 QtCore.QRect 类型的区域——小部件边距内的区域。
widget.contextMenuPolicy(): 这返回QtCore.Qt.ContextMenuPolicy类型的小部件上下文菜单策略;换句话说,小部件如何显示上下文菜单。
widget.create(0, True, True): 这使用第一个参数窗口(类型QtGui.WId),第二个参数initializeWindow(类型QtCore.bool)和第三个参数destroyOldWindow(类型QtCore.bool)创建一个新窗口。
widget.create(0, True, True): 这使用第一个参数窗口(类型sip.voidptr),第二个参数initializeWindow(类型bool)和第三个参数destroyOldWindow(类型bool)创建一个新窗口。
widget.createWinId(): 这是窗口系统标识符,这意味着它为窗口系统所知。
widget.createWindowContainer(QtGui.QWindow, None, QtCore.Qt.WindowFlags): 这使用第一个参数窗口(类型QtGui.QWindow),第二个参数父元素(类型QtWidgets.QWidget)和第三个参数标志(类型QtCore.Qt.WindowFlags)创建窗口容器。
widget.cursor(): 这返回当前QtGui.QCursor类型的光标,即小部件的光标。
widget.destroy(True, True): 这将释放窗口系统资源,并使用第一个参数destroyWindow和第二个参数destroySubWindows销毁小部件窗口。
widget.effectiveWinId(): 这返回QtGui.WId类型的标识符或 PyQt5 的sip.voidptr——小部件的有效窗口系统标识符。
widget.ensurePolished(): 小部件及其子小部件已被抛光;它们将具有适当的字体和调色板。
widget.find(QtGui.WId): 这返回指向具有窗口 ID 的QtWidgets.QWidget类型小部件的指针。
widget.focusNextChild(): 如果它能找到一个新的小部件来提供键盘焦点,则返回True。
widget.focusNextPrevChild(bool): 如果它能找到一个新的小部件来提供键盘焦点,则返回True。如果参数为True,则向前搜索;如果为False,则向后搜索。
widget.focusPolicy(): 这返回小部件的QtCore.Qt.FocusPolicy类型焦点策略,即小部件接受键盘焦点的方式。
widget.focusPreviousChild(): 如果它能找到一个新的小部件来提供键盘焦点,则返回True。
widget.focusProxy(): 这返回焦点代理,如果焦点代理不存在,则返回0。
widget.focusWidget(): 这返回了使用widget.setFocus()函数调用的QtWidgets.QWidget类型的最后一个子小部件。
widget.font(): 这返回当前设置在相关小部件中的QtGui.QFont类型的字体。
widget.fontInfo(): 这返回小部件当前字体类型的QtGui.QFontInfo字体信息。
widget.fontMetrics(): 这返回小部件当前字体类型的QtGui.QFontMetrics字体度量。
widget.foregroundRole(): 这返回小部件的前景角色,类型为QtGui.QPalette.ColorRole——小部件的前景角色。
widget.frameGeometry(): 这返回了 QtCore.QRect 类型的几何形状——小部件相对于其父级的几何形状,包括窗口框架。
widget.frameSize(): 这返回 QtCore.QSize 类型的尺寸——小部件的尺寸,包括窗口框架。
widget.geometry(): 这返回 QtCore.QRect 类型的几何形状——小部件相对于其父级的几何形状,不包括窗口框架。
widget.getContentsMargins(): 这返回四个整数值,用于小部件的内容边距的左侧、顶部、右侧和底部。
widget.grab(QtCore.QRect(QtCore.QPoint(0,0), QtCore.QSize(-1,-1))): 这将小部件渲染为 QtGui.QPixmap 类型的位图,受矩形参数限制。
widget.grabGesture(QtCore.Qt.GestureType, QtCore.Qt.GestureFlags): 这将小部件订阅到具有标志(第二个参数)的第一个参数的手势。
widget.grabKeyboard(): 这捕获键盘输入。小部件将接收所有键盘事件。
widget.grabMouse(): 这捕获鼠标输入。小部件将接收所有鼠标事件。
widget.grabMouse(QtGui.QCursor): 这捕获鼠标输入并更改光标形状。小部件将接收所有鼠标事件。
widget.grabShortcut(QtGui.QKeySequence, QtCore.Qt.ShortcutContext): 这向 Qt 的快捷键系统添加了一个快捷键,该快捷键在给定上下文(第二个参数)中监视给定的键序列(第一个参数)。
widget.graphicsEffect(): 这返回 QtWidgets.QGraphicsEffect 类型的指针——小部件的图形效果。
widget.graphicsProxyWidget(): 这返回对应于图形视图中嵌入小部件的 QtWidgets.QGraphicsProxyWidget 类型代理小部件。
widget.height(): 这返回小部件的高度,不包括窗口框架。
widget.heightForWidth(width): 这在给定 width 的情况下返回此小部件的首选高度。
widget.inputMethodHints(): 这返回了小部件的 QtCore.Qt.InputMethodHints 类型的输入方法提示。
widget.inputMethodQuery(QtCore.Qt.InputMethodQuery): 关于输入,小部件用于查询要支持复杂输入方法操作的小部件的属性集,以便支持周围文本和重新转换。
widget.insertAction(QtWidgets.QAction, QtWidgets.QAction): 这在小部件动作列表中在另一个动作(第一个参数)之前插入一个动作(第二个参数)。
widget.insertActions(QtWidgets.QAction, [QtWidgets.QAction]): 这在小部件动作列表中在另一个动作(第一个参数)之前插入动作(第二个参数)。
widget.internalWinId(): 这返回窗口系统标识符。
widget.keyboardGrabber(): 这返回当前捕获键盘输入的 QtWidgets.QWidget 类型的小部件。
widget.layout(): 这返回此小部件的布局管理器。
widget.layoutDirection(): 这返回了此widget布局管理器的方向。
widget.locale(): 这返回了widget的QtCore.QLocale类型的区域设置。
widget.lower(): 这将widget降低到父widget堆栈的底部。
widget.mapFrom(QtWidgets.QWidget, QtCore.QPoint): 这表示将坐标pos(第二个参数)从父坐标系统转换为widget的坐标系统。
widget.mapFromGlobal(QtCore.QPoint): 这表示将全局屏幕坐标pos(参数)转换为widget的坐标系统。
widget.mapFromParent(QtCore.QPoint): 这表示将父坐标pos(参数)转换为widget的坐标系统。
widget.mapTo(QtWidgets.QWidget, QtCore.QPoint): 这表示将widget的坐标pos(第二个参数)转换为父坐标系统。
widget.mapToGlobal(QtCore.QPoint): 这表示将widget的坐标pos(参数)转换为全局屏幕坐标。
widget.mapToParent(QPoint): 这表示将widget的坐标pos(参数)转换为父widget中的坐标。
widget.mask(): 这返回了当前设置在widget上的QtGui.QRegion类型的区域作为掩码。
widget.maximumHeight(): 这返回了此widget可用的整数类型的最大高度。
widget.maximumSize(): 这返回了此widget可用的QtCore.QSize类型的最大尺寸。
widget.maximumWidth(): 这返回了此widget可用的整数类型的最大宽度。
widget.minimumHeight(): 这返回了此widget可用的整数类型的最小高度。
widget.minimumSize(): 这返回了此widget可用的QtCore.QSize类型的最小尺寸。
widget.minimumSizeHint(): 这返回了此widget可用的QtCore.QSize类型的最小尺寸提示。
widget.minimumWidth(): 这返回了此widget可用的整数类型的最小宽度。
widget.metric(QtGui.QPaintDevice.PaintDeviceMetric): 这返回了带有绘图设备度量参数的度量信息。
widget.mouseGrabber(): 这返回了当前正在抓取鼠标输入的QtWidgets.QWidget类型的widget。
widget.nativeParentWidget(): 这返回了此widget的QtWidgets.QWidget类型的本地父级。
widget.nextInFocusChain(): 这返回了在此widget的焦点链中的下一个QtWidgets.QWidget类型的widget。
widget.normalGeometry(): 这返回了widget的QtCore.QRect类型的几何形状,当作为normal(非maximized或fullscreen)顶级widget显示时将出现。
widget.overrideWindowFlags(QtCore.Qt.WindowFlags): 这更改了widget的窗口标志,而不通知窗口系统。
widget.overrideWindowState(QtCore.Qt.WindowStates): 这会更改子小部件的窗口状态。
widget.palette(): 这返回小部件的调色板,该调色板在小部件绘制标准组件时由小部件的样式使用。
widget.parentWidget(): 这返回此小部件的 QtWidgets.QWidget 类型的父小部件。
widget.pos(): 这返回小部件在父小部件内的 QtCore.QPoint 类型的位置。
widget.previousInFocusChain(): 这返回在此小部件焦点链中的 QtWidgets.QWidget 类型的上一个小部件。
widget.raise_(): 这会将小部件提升到父小部件堆栈的顶部。
widget.rect(): 这返回内部小部件的 QtCore.QRect 类型的几何形状,不包括任何窗口框架。
widget.releaseKeyboard(): 这将释放键盘捕获。
widget.releaseMouse(): 这将释放鼠标捕获。
widget.releaseShortcut(id): 这将从快捷方式系统中移除具有给定 id 作为整数值的快捷方式。
widget.removeAction(QtWidgets.QAction): 这将从小部件的动作列表中移除通过参数传入的动作。
widget.render(QtGui.QPaintDevice, QtCore.QPoint, QtGui.QRegion, QtWidgets.QWidget.RenderFlags): 这将在目标(第一个参数)中使用 RenderFlags(第四个参数)渲染此小部件的 sourceRegion(第三个参数),并在目标中的 targetOffset(第二个参数)开始。
widget.render(QtGui.QPainter, QtCore.QPoint, QtGui.QRegion, QtWidgets.QWidget.RenderFlags): 这将在画家设备 (QtGui.QPainter.device()) 中使用 sourceRegion(此小部件的第三个参数)和 renderFlags(第四个参数)渲染小部件,并从 targetOffset(第二个参数)开始。
widget.repaint(): 这将使用 QtWidgets.QWidget.paintEvent() 方法重新绘制小部件。
widget.repaint(QtCore.QRect): 这将在小部件内部重新绘制矩形。
widget.repaint(QtGui.QRegion): 这将在小部件内部重新绘制区域。
widget.repaint(x, y, w, h): 这将在小部件内部重新绘制具有 x(x 轴)或 y(y 轴)和 w(宽度)以及 h(高度)整数值的矩形。
widget.restoreGeometry(QtCore.QByteArray): 这将恢复存储在字节数组几何形状中的顶级小部件的几何形状和状态,如果成功则返回 True,否则返回 False。
widget.saveGeometry(): 这将保存顶级小部件的当前几何形状和状态。
widget.size(): 这返回 QtCore.QSize 类型的尺寸——小部件的尺寸,不包括窗口框架。
widget.sizeHint(): 这返回 QtCore.QSize 类型的尺寸——小部件的推荐大小。
widget.sizeIncrement(): 这返回 QtCore.QSize 类型的尺寸——小部件的增量大小,或者通过这些增量来改变当用户调整窗口大小时的大小。
widget.sizePolicy(): 这返回 QtWidgets.QSizePolicy 类型的尺寸策略——小部件的尺寸策略。
widget.stackUnder(QtWidgets.QWidget): 这将小部件放置在父小部件堆栈中的参数下。
widget.statusTip(): 这返回小部件的状态提示作为 Unicode 字符串。
widget.style(): 这返回小部件的QtWidgets.QStyle类型的 GUI 样式。
widget.styleSheet(): 这返回表示小部件样式表的 Unicode 字符串。
widget.testAttribute(QtCore.Qt.WidgetAttribute): 如果参数中的属性在此小部件上设置,则返回True;否则,返回False。
widget.toolTip(): 这返回此小部件的工具提示作为 Unicode 字符串。
widget.toolTipDuration(): 这返回小部件工具提示的持续时间,并以毫秒为单位的整数值表示工具提示何时可见。
widget.topLevelWidget(): 这返回此小部件的最高级小部件。
widget.underMouse(): 如果小部件位于鼠标光标下,则返回True;否则,返回False。
widget.ungrabGesture(QtCore.Qt.GestureType): 这将取消订阅小部件给定的手势参数。
widget.unsetCursor(): 这将取消设置小部件的光标。
widget.unsetLayoutDirection(): 这将取消设置小部件的布局方向。
widget.unsetLocale(): 这将取消设置小部件的区域设置。
widget.update(): 这将更新小部件,除非更新被禁用或小部件被隐藏。
widget.update(QtGui.QRegion): 当小部件内部指定参数的区域被重绘时,这将更新小部件。
widget.update(QtCore.QRect): 这将更新小部件作为参数内部的小部件中的矩形。
widget.update(x, y, w, h): 这将更新一个矩形,参数为x(x轴)和y(y轴)以及w(宽度)和h(高度)在小部件内部。
widget.updateGeometry(): 布局系统将通知小部件已更改,可能需要更改几何形状。
widget.updateMicroFocus(): 这将更新小部件的微焦点。
widget.updatesEnabled(): 如果此小部件的更新被启用,则返回True。
widget.visibleRegion(): 这返回未遮挡的QtGui.QRegion类型区域,其中可以发生绘制事件。
widget.whatsThis(): 这返回小部件的“这是什么”帮助文本作为 Unicode 字符串。
widget.winId(): 这返回小部件的QtGui.WId类型窗口系统标识符。
widget.width(): 这返回小部件的宽度,不包括窗口框架。
widget.window(): 这返回此小部件的窗口。
widget.windowFilePath(): 这返回与该小部件关联的文件路径作为 Unicode 字符串。
widget.windowFlags(): 这返回此小部件使用的QtCore.Qt.WindowFlags类型窗口标志。
widget.windowHandle(): 如果这是一个本地小部件,则返回关联的QtGui.QWindow类型窗口。
widget.windowIcon(): 这返回小部件的QtGui.QIcon类型窗口图标。
widget.windowIconText(): 这返回部件的窗口图标文本,作为 Unicode 字符串。
widget.windowModality(): 这返回哪些窗口被模态部件阻塞。
widget.windowOpacity(): 这返回窗口的不透明度,以浮点值表示,从0.0(完全透明)到1.0(完全不透明)。
widget.windowRole(): 这返回窗口的角色,作为 Unicode 字符串。
widget.windowState(): 这返回当前窗口状态,为QtCore.Qt.WindowStates类型。
widget.windowTitle(): 这返回部件的窗口标题,作为 Unicode 字符串。
widget.windowType(): 这返回部件的窗口类型,为QtCore.Qt.WindowType类型。
widget.x(): 这返回部件相对于其父级的x轴坐标,包括窗口框架。
widget.y(): 这返回部件相对于其父级的y轴坐标,包括窗口框架。
事件
这些是与事件处理程序等事件相关的函数:
widget.actionEvent(QtGui.QActionEvent): 当部件的动作发生变化时,这个事件处理器会使用事件参数被调用。
widget.closeEvent(QtGui.QCloseEvent): 当窗口系统收到顶级部件的窗口关闭请求时,这个事件处理器会使用事件参数被调用。
widget.changeEvent(QtCore.QEvent): 这处理部件的状态变化。
widget.contextMenuEvent(QtGui.QContextMenuEvent): 这是一个设计用来接收部件上下文菜单事件的处理器。
widget.dragEnterEvent(QtGui.QDragEnterEvent): 当鼠标进入部件并且有拖动操作进行时,这个事件处理器会使用事件参数被调用。
widget.dragLeaveEvent(QtGui.QDragLeaveEvent): 当鼠标离开部件并且有拖动操作进行时,这个事件处理器会使用事件参数被调用。
widget.dragMoveEvent(QtGui.QDragMoveEvent): 当某些条件发生时,例如光标进入或移动到部件内,在部件有焦点时按下修改键,以及拖动操作正在进行时,这个事件处理器会使用事件参数被调用。
widget.dropEvent(QtGui.QDropEvent): 当拖动操作在部件上释放时,事件处理程序会使用事件参数被调用。
widget.enterEvent(QtCore.QEvent): 这是一个设计用来接收部件进入事件的处理器,这些事件通过事件参数传递,并且当鼠标光标进入部件时发送给部件。
widget.event(QtCore.QEvent): 这接收对象的事件,并且如果事件被识别并处理,则应返回True。
widget.focusOutEvent(QtGui.QFocusEvent): 这是一个设计用来接收部件键盘焦点事件的处理器,当焦点丢失时,会通过事件参数传递。
widget.focusInEvent(QtGui.QFocusEvent): 这是一个设计用来接收小部件键盘焦点事件的处理器,当焦点被接收时,事件参数会随事件传入。
widget.hideEvent(QtGui.QHideEvent): 这是一个设计用来接收小部件隐藏事件的处理器,隐藏事件通过参数传入。
widget.inputMethodEvent(QtGui.QInputMethodEvent): 这是一个设计用来接收输入法组合事件的处理器,输入法事件通过参数传入。
widget.keyPressEvent(QtGui.QKeyEvent): 这是一个设计用来接收小部件按键事件的处理器,按键事件通过参数传入。
widget.keyReleaseEvent(QtGui.QKeyEvent): 这是一个设计用来接收小部件按键释放事件的处理器,按键事件通过参数传入。
widget.leaveEvent(QtCore.QEvent): 这是一个设计用来接收小部件离开事件的处理器,事件通过参数传入。
widget.moveEvent(QtGui.QMoveEvent): 这是一个设计用来接收小部件移动事件的处理器,鼠标事件通过参数传入。
widget.mouseMoveEvent(QtGui.QMouseEvent): 这是一个设计用来接收小部件鼠标移动事件的处理器,鼠标事件通过参数传入。
widget.mousePressEvent(QtGui.QMouseEvent): 这是一个设计用来接收小部件鼠标按下事件的处理器,鼠标事件通过参数传入。
widget.mouseReleaseEvent(QtGui.QMouseEvent): 这是一个设计用来接收小部件鼠标释放事件的处理器,鼠标事件通过参数传入。
widget.mouseDoubleClickEvent(QtGui.QMouseEvent): 这是一个设计用来接收小部件双击鼠标事件的处理器,鼠标事件通过参数传入。
widget.paintEvent(QtGui.QPaintEvent): 这是一个设计用来接收小部件绘制事件的处理器,绘制事件通过参数传入。
widget.resizeEvent(QtGui.QResizeEvent): 这是一个设计用来接收小部件尺寸变化事件的处理器,尺寸变化事件通过参数传入。
widget.showEvent(QtGui.QShowEvent): 这是一个设计用来接收小部件显示事件的处理器,显示事件通过参数传入。
widget.tabletEvent(QtGui.QTabletEvent): 这是一个设计用来接收小部件平板事件处理的处理器,平板事件通过参数传入。
widget.wheelEvent(QtGui.QWheelEvent): 这是一个设计用来接收小部件鼠标滚轮事件的处理器,滚轮事件通过参数传入。
信号
QWidget 类可用的信号如下:
widget.customContextMenuRequested(QtCore.QPoint): 当用户在控件上请求上下文菜单时,会发出此信号。
widget.windowIconChanged(QtGui.QIcon): 当窗口的图标更改时,会发出此信号,新图标作为参数。
widget.windowIconTextChanged("Icon text"): 当窗口的图标文本更改时,会发出此信号,新图标文本作为参数。
widget.windowTitleChanged("Window Title"): 当窗口的标题文本更改时,会发出此信号,新窗口标题作为参数。
QWidget 示例
理解 QWidget 类的这些方法非常重要,因为这些方法非常实用且在几乎所有的由 GUI 开发者使用 PySide2 和 PyQt5 绑定实现的元素中都被广泛使用。这个类被所有图形组件继承,包括按钮、标签、框架和文本字段。我们不会将之前描述的所有方法都添加到应用程序中,因为这只会部分实现并在本书中解释。现在,让我们仅为了演示目的,从u_style.py文件中将其中一些添加到控件类中。首先,将图标设置为控件窗口。为此,在App/App_PySide2和App/App_PyQt5目录中创建一个名为Icons/的文件夹,并将你喜欢的图片插入此文件夹。然后,将以下行添加到 PyQt5 和 PySide2 的u_style.py文件中以提高控件:
...
class UWid(QtWidgets.QWidget):
def __init__(self, parent=None):
...
win_icon = QtGui.QIcon("Icons/python1.png")
self.setWindowIcon(win_icon)
self.setWindowOpacity(0.95)
self.setAcceptDrops(True)
self.setMouseTracking(True)
self.setUpdatesEnabled(True)
self.setAutoFillBackground(True)
...
...
...
现在,窗口的控件已有一个图标并且略微透明。
QMainWindow
此类提供了可以用于 GUI 应用程序的主窗口。QMainWindow 具有单文档界面(SDI)或多文档界面(MDI),可以通过添加QMdiArea作为中央控件来创建。MDI 应用程序中最受欢迎的例子是GNU 图像处理程序(GIMP)和 Photoshop,它们代表类似显示的文档(窗口)而不是一个(SDI)。在 SDI 和 MDI 类型的应用程序中,都需要添加中央控件。应用程序中主窗口的声明语法如下:
main_window = QtWidgets.QMainWindow()
QMainWindow 类的函数
QMainWindow类继承自QWidget,并通过以下函数增强了功能。
添加
这些是与向主窗口添加元素相关的函数,例如添加一个停靠小部件或工具栏:
main_window.addDockWidget(QtCore.Qt.DockWidgetArea, QtWidgets.QDockWidget, QtCore.Qt.Orientation): 这会将第二个参数的停靠小部件添加到第一个参数指定的区域,并按照第三个方向参数指定的方向添加。
main_window.addDockWidget(QtCore.Qt.DockWidgetArea, QtWidgets.QDockWidget): 这会将第二个参数的停靠小部件添加到第一个参数指定的区域。
main_window.addToolBar("Title"): 此方法创建一个QtWidgets.QToolBar对象,设置标题,并将其插入到顶部工具栏区域。
main_window.addToolBar(QtWidgets.QToolBar): 这将在主窗口中添加一个工具栏。
main_window.addToolBar(QtCore.Qt.ToolBarArea, QtWidgets.QToolBar): 这将在主窗口的指定区域(第一个参数)中添加工具栏(第二个参数)。
main_window.addToolBarBreak(QtCore.Qt.ToolBarArea): 这将在现有对象之后将工具栏分隔符添加到指定区域。
set
这些是与主窗口参数/属性设置相关的函数,包括设置样式、大小或功能:
main_window.setAnimated(bool): 如果参数为True,则设置主窗口为动画。
main_window.setCentralWidget(QtWidgets.QWidget): 这将为该主窗口设置参数中指定的中央小部件。
main_window.setCorner(QtCore.Qt.Corner, QtCore.Qt.DockWidgetArea): 这将设置停靠小部件区域(第二个参数)以占据角落(第一个参数)。
main_window.setDockNestingEnabled(bool): 如果参数为True,则规定停靠可以嵌套。
main_window.setDockOptions(QtWidgets.QMainWindow.DockOptions): 这将设置此主窗口的停靠行为。
main_window.setDocumentMode(bool): 如果参数为True,则将文档模式设置为该主窗口的选项卡栏(用于选项卡停靠小部件)。
main_window.setIconSize(QtCore.QSize): 这将为该主窗口的工具栏图标设置图标大小。
main_window.setMenuBar(QtWidgets.QMenuBar): 这将为该主窗口设置参数中指定的菜单栏。
main_window.setMenuWidget(QtWidgets.QWidget): 这将为该主窗口设置QtWidgets.QWidget类型的菜单栏。
main_window.setStatusBar(QtWidgets.QStatusBar): 这将设置此主窗口的状态栏。
main_window.setTabPosition(QtCore.Qt.DockWidgetAreas, QtWidgets.QTabWidget.TabPosition): 这将为停靠小部件区域(第一个参数)设置选项卡位置(第二个参数)。
main_window.setTabShape(QtWidgets.QTabWidget.TabShape): 这将为该主窗口的选项卡停靠小部件设置将使用的选项卡形状。
main_window.setToolButtonStyle(QtCore.Qt.ToolButtonStyle): 这将为该主窗口设置工具栏按钮的样式。
main_window.setUnifiedTitleAndToolBarOnMac(bool): 这将为 macOS 设置统一的标题和工具栏外观。
is
这些函数返回一个布尔值(bool),与主窗口状态相关,例如,检查当前状态:
main_window.isAnimated(): 如果停靠小部件和工具栏是动画的,则返回True。
main_window.isDockNestingEnabled(): 如果停靠可以嵌套,则返回True。
functional
这些是与主窗口当前值返回、功能变化等相关联的函数:
main_window.centralWidget(): 这返回此主窗口的QtWidgets.QWidget类型的中央小部件。
main_window.corner(QtCore.Qt.Corner): 这返回由QtCore.Qt.Corner类型的参数corner指定的区域所占据的停靠小部件区域。
main_window.createPopupMenu(): 这返回此主窗口的QtWidgets.QMenu类型的弹出菜单。
main_window.dockOptions(): 这返回此主窗口的QtWidgets.QMainWindow.DockOptions类型的停靠行为。
main_window.dockWidgetArea(QtWidgets.QDockWidget): 这返回主窗口停靠小部件的QtCore.Qt.DockWidgetArea类型的停靠小部件区域。
main_window.documentMode(): 这返回True,如果选项卡式停靠小部件的标签栏设置为文档模式。
main_window.iconSize(): 这返回此主窗口工具栏图标的QtCore.QSize类型的大小。
main_window.insertToolBar(QtWidgets.QToolBar, QtWidgets.QToolBar): 这在第一个参数指定的工具栏之前插入第二个参数指定的工具栏。
main_window.insertToolBarBreak(QtWidgets.QToolBar): 这在参数指定的工具栏之前插入工具栏分隔符。
main_window.menuBar(): 这返回主窗口的QtWidgets.QMenuBar类型的菜单栏。
main_window.menuWidget(): 这返回主窗口的QtWidgets.QWidget类型的菜单栏。
main_window.removeDockWidget(QtWidgets.QDockWidget): 这从主窗口布局中移除停靠小部件并隐藏它。
main_window.removeToolBar(QtWidgets.QToolBar): 这从主窗口布局中移除工具栏并隐藏它。
main_window.removeToolBarBreak(QtWidgets.QToolBar): 这移除参数指定的工具栏之前的工具栏分隔符。
main_window.resizeDocks([QtWidgets.QDockWidget], [int], QtCore.Qt.Orientation): 这根据第二个参数中的像素大小和第三个方向参数调整第一个参数指定的停靠小部件的大小。
main_window.restoreDockWidget(QtWidgets.QDockWidget): 这使用QtWidgets.QMainWindow.restoreState()函数恢复停靠小部件的状态,如果状态已恢复则返回True,否则返回False。
main_window.restoreState(QtCore.QByteArray,0): 这使用作为整数类型第二个参数的版本与存储在状态中的数字进行比较来恢复此主窗口的工具栏和停靠小部件的状态。如果不匹配,函数返回False,否则返回True。
main_window.saveState(0): 这保存此主窗口的工具栏和停靠小部件的当前状态。参数的版本号作为整数值将作为数据的一部分存储。
main_window.splitDockWidget(QtWidgets.QDockWidget, QtWidgets.QDockWidget, QtCore.Qt.Orientation): 这将部件(第一个参数)覆盖的空间分成两部分,将第一个停靠部件移动到第一部分,并将第二个停靠部件(第二个参数)移动到第二部分,第三参数指定了空间如何分割的方向。
main_window.statusBar(): 这返回了此主窗口的 QtWidgets.QStatusBar 状态栏。
main_window.tabifiedDockWidgets(QtWidgets.QDockWidget): 这返回与参数中的停靠部件一起选项卡化的停靠部件。
main_window.tabifyDockWidget(QtWidgets.QDockWidget, QtWidgets.QDockWidget): 这会将第二个参数中的停靠部件移动到第一个参数中的停靠部件之上,并在主窗口中创建一个选项卡式停靠区域。
main_window.tabPosition(QtCore.Qt.DockWidgetArea): 这返回了参数中指定的区域的选项卡位置。
main_window.tabShape(): 这返回了与选项卡式停靠部件一起使用的 QtWidgets.QTabWidget.TabShape 类型的选项卡形状。
main_window.takeCentralWidget(): 这会移除主窗口的中心部件。
main_window.toolBarArea(QtWidgets.QToolBar): 这返回指定参数的 QtCore.Qt.ToolBarArea 类型的工具栏区域。
main_window.toolBarBreak(QtWidgets.QToolBar): 如果工具栏在指定的参数之前有一个断点,则返回 True。
main_window.toolButtonStyle(): 这返回 QtCore.Qt.ToolButtonStyle 类型的工具按钮样式。
main_window.unifiedTitleAndToolBarOnMac(): 如果主窗口在 macOS 上使用统一的标题和工具栏外观,则返回 True。
事件
这些是与事件相关的函数,例如事件处理程序:
main_window.contextMenuEvent(QtGui.QContextMenuEvent): 这是 QWidget 事件处理程序,它被设计用来接收主窗口的上下文菜单事件。
main_window.event(QtCore.QEvent): 这是 QtCore.QObject 函数,它接收对象的事件,如果事件被识别并处理,则应返回 True。
信号
QMainWindow 类的可用的信号如下:
main_window.iconSizeChanged(QtCore.QSize): 当窗口的图标大小发生变化时,会发出此信号,并传递了新的图标大小作为参数。
main_window.tabifiedDockWidgetActivated(QtWidgets.QDockWidget): 当通过选择选项卡激活选项卡化的停靠部件时,会发出此信号,并传递了选项卡化的停靠部件作为参数。
main_window.toolButtonStyleChanged(QtCore.Qt.ToolButtonStyle): 当窗口中工具按钮使用的样式发生变化时,会发出此信号,并将新的工具按钮样式作为参数传递。
QMainWindow 示例
QMainWindow类提供了一种更全面实现应用程序的方法。这样,我们将使用主窗口而不是之前描述的小部件来重新组织创建的应用程序中的类。为了演示这一点,让我们在App/App_PySide2和App/App_PyQt5目录中创建一个名为u_window.py的文件,并向这些行添加import语句:
- 将以下代码添加到 PyQt5 的
u_window.py文件中:
...
from PyQt5 import QtWidgets, QtCore, QtGui
from u_style import UWin, UWid, UMBar, USBar, UMenu, UTWid
...
- 将以下代码添加到 PySide2 的
u_window.py文件中:
...
from PySide2 import QtWidgets, QtCore, QtGui
from u_style import UWin, UWid, UMBar, USBar, UMenu, UTWid
...
- 在 PySide2 和 PyQt5 的情况下,将主窗口类
UWindow添加到u_window.py文件中:
...
class UWindow(UWin):
def __init__(self, parent=None):
super(UWindow, self).__init__(parent)
在这里,我们添加了从QWin类继承的UWindow类,而QWin类又实现了QtWidgets模块的QMainWindow类。
- 将菜单栏添加到
UWindow类中:
...
def __init__(self, parent=None):
...
self.menubar = UMBar()
self.mb1 = UMenu(self.menubar)
self.mb1.addAction("Open")
self.mb1.addAction("Save")
self.mb1.setTitle("&File")
self.mb2 = UMenu(self.menubar)
self.mb2.addAction("Cut")
self.mb2.addAction("Copy")
self.mb2.addAction("Paste")
self.mb2.setTitle("&Edit")
self.mb3 = UMenu(self.menubar)
self.mb3.addAction("Settings")
self.mb3.addAction("Run")
self.mb3.addAction("Configuration")
self.mb3.setTitle("&Options")
self.mb4 = UMenu(self.menubar)
self.mb4.addAction("Online Help")
self.mb4.addAction("Documentation")
self.mb4.setTitle("&Help")
self.menubar.addMenu(self.mb1)
self.menubar.addMenu(self.mb2)
self.menubar.addMenu(self.mb3)
self.menubar.addMenu(self.mb4)
self.setMenuBar(self.menubar)
这个菜单栏包含包含操作的菜单项(选择点)。
- 将主应用程序窗口的标签控件添加到
UWindow类中,设置中心小部件和状态栏,并完成文件:
...
...
...
self.tabwid = UTWid()
self.twid1 = UWid()
self.twid2 = UWid()
self.twid3 = UWid()
self.tabwid.addTab(self.twid1, "Applications")
self.tabwid.addTab(self.twid2, "Visualization")
self.tabwid.addTab(self.twid3, "Documents")
self.setCentralWidget(self.tabwid)
self.stat_bar = USBar()
self.setStatusBar(self.stat_bar)
...
主窗口的中心小部件是一个包含每个标签三个小部件的标签控件。在应用程序窗口的底部是状态栏。
现在,我们需要向u_style.py文件中添加一些行:
- 在
u_style.py文件(适用于 PySide2 和 PyQt5)中,在UWid类之前插入新类,然后向文件中添加新的颜色:
...
color = ["rgba(0,41,59,140)", "rgba(0,41,59,255)",
"rgba(1,255,217,140)", "rgba(1,255,217,255)"]
...
这是一个包含将在应用程序中使用的新的 RGBA 颜色的列表。
- 然后,添加主窗口样式类:
...
class UWin(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(UWin, self).__init__(parent)
self.setWindowTitle("U App")
win_icon = QtGui.QIcon("Icons/python1.png")
self.setWindowIcon(win_icon)
self.setWindowOpacity(0.95)
self.setAnimated(True)
self.setAcceptDrops(True)
self.setMouseTracking(True)
self.setUpdatesEnabled(True)
self.setAutoFillBackground(True)
self.setStyleSheet("background-color: %s;" % (color[0],))
...
这将为主窗口添加常用属性。
- 现在,添加菜单栏样式类:
...
class UMBar(QtWidgets.QMenuBar):
def __init__(self, parent=None):
super(UMBar, self).__init__(parent)
self.setStyleSheet("background-color: %s;" % (color[2],))
...
菜单栏位于主应用程序窗口的顶部面板中。
- 向菜单栏中的菜单添加样式类:
...
class UMenu(QtWidgets.QMenu):
def __init__(self, parent=None):
super(UMenu, self).__init__(parent)
self.setStyleSheet("background-color: %s;" % (color[2],))
...
菜单是在点击菜单栏选项时出现的弹出列表。
- 现在,添加标签控件样式类:
...
class UTWid(QtWidgets.QTabWidget):
def __init__(self, parent=None, twbdr=3, twbdw=0.5,
twbbg=color[1], tbpad=7, tbsize=140,
tbbg=color[0], tbc=color[2], tbcs=color[3]):
super(UTWid, self).__init__(parent)
self.font1 = QtGui.QFont()
self.font1.setLetterSpacing(
QtGui.QFont.AbsoluteSpacing, 2.0)
self.font1.setWordSpacing(2.0)
self.font1.setFamily("Verdana")
self.font1.setPixelSize(12)
self.font1.setWeight(34)
self.setFont(self.font1)
self.twbdr, self.twbdw, self.twbbg = twbdr, twbdw, twbbg
self.tbsize, self.tbpad, self.tbbg = tbsize, tbpad, tbbg
self.tbc, self.tbcs = tbc, tbcs
self.setStyleSheet(
"""QTabWidget::pane {border-style: solid;
border-radius: %spx; border-width: %spx;
border-color: %s;}
QTabBar::tab {width: %spx; margin: 0px;
padding: %spx; background-color: %s;
color: %s; border-style: solid;
border-top-right-radius: 10px;
border-width: %spx;
border-bottom-width: 0px; border-color: %s;}
QTabBar::tab:selected {background-color: %s;
color: %s;}
QTabBar::tab:!selected {margin-top: 5px;}
QTabBar QToolButton {color: %s;}"""
% (self.twbdr, self.twbdw, self.twbbg, self.tbsize,
self.tbpad, self.tbbg, self.tbc, self.twbdw,
self.tbbg, self.twbbg, self.tbcs, self.tbcs))
...
标签控件是应用程序窗口的中心小部件。setStyleSheet()方法实现了此标签控件各个元素的风格。
- 添加状态栏样式类:
...
class USBar(QtWidgets.QStatusBar):
def __init__(self, parent=None):
super(USBar, self).__init__(parent)
self.setStyleSheet("background-color: %s;" % (color[2],))
这个状态栏将完成应用程序窗口底部的布局。我们需要将这个主窗口添加到u_app.py文件中。
- 修改
import语句和UApp类的行:
...
from u_window import UWindow
class UApp(UWindow, UTools)
...
...
UApp应用程序的主类继承自UWindow类。现在,我们可以在 GUI 表示中看到应用程序主窗口的基础。在 PySide2 和 PyQt5 应用程序中,结果将是相同的:

前面的截图显示了应用程序的主窗口。
摘要
本章详细考虑了 PySide2 和 PyQt5 库的两个主要类:QWidget和QMainWindow。这些类的描述非常重要,因为这构成了创建 GUI 应用程序图形组件的基础。几乎开发者在构建应用程序时将使用的所有类,只要是由 PySide2 和 PyQt5 框架提供的,都是继承自QWidget类的。另一方面,QMainWindow类提供了一种更全面的方式来创建现代 GUI。
下一章将继续探讨继承自QWidget类的图形元素。
第六章:使用框架、标签和文本字段
本章将涵盖的内容是用于在开发第一阶段组织应用程序的图形组件。这些组件提供了实现一些用于可视化应用程序的窗口、带有文本的标签以通知用户应用程序的功能,以及各种文本字段以输入文本和操作文本的能力。我们将首先描述这些方法,然后在章节末尾在应用程序中实现它们。没有现代应用程序可以没有这些组件。用户可能希望有一个完美的可视化效果,解释事物是什么或需要做什么,或者可能发生某些事件。文本字段具有与各种文本一起工作的功能,例如短文本、长描述、可视化文本、从文件加载文本、复制/粘贴文本、对文本的其他附加操作,以及从文本字段保存文本到文件。所有这些都可以通过不同的选项获得。
在本章中,我们将涵盖以下主题:
-
框架
-
标签
-
行编辑字段
-
文本编辑字段
QFrame
来自 QtWidgets 模块的此类是具有框架的窗口的基类。QFrame 继承了 QWidget 类。框架可以用于通过相似性组合一些元素,并且/或者用作框架内组件的父元素。第二个断言在您需要隐藏某些元素时很有用,您只需隐藏父框架,而不是逐个隐藏它们。创建框架的语法如下:
frame = QtWidgets.QFrame()
QFrame 的功能
QFrame 扩展了 QWidget 类并提供以下功能。
设置
这些函数设置框架的参数/属性,例如样式和宽度:
frame.setFrameRect(QtCore.QRect): 这为此框架绘制的矩形设置。
frame.setFrameShadow(QtWidgets.QFrame.Shadow): 这为此框架设置阴影。
frame.setFrameShape(QtWidgets.QFrame.Shape): 这为此框架设置形状。
frame.setFrameStyle(int): 这设置框架的样式。可用的值如下:
-
0: 无框架 -
1: 盒子 -
2: 面板 -
3: 窗口面板 -
4/5: 水平线/垂直线和样式面板
frame.setLineWidth(int): 这为此框架设置线宽。
frame.setMidLineWidth(int): 这为此框架设置中间线宽。
功能
这些函数返回框架的当前值或更改功能:
frame.frameRect(): 这返回框架绘制的 QtCore.QRect 类型的矩形。
frame.frameShadow(): 这返回框架样式中的框架阴影值,类型为 QtWidgets.QFrame.Shadow。
frame.frameShape(): 这返回框架样式中的框架形状值,类型为 QtWidgets.QFrame.Shape。
frame.frameStyle(): 这返回框架样式为整数值。
frame.frameWidth(): 这返回绘制的框架的宽度为整数值。
frame.initStyleOption(QtWidgets.QStyleOptionFrame): 这使用参数中的值初始化样式选项。
frame.lineWidth(): 这以整数值返回框架的线宽。
frame.midLineWidth(): 这以整数值返回此框架中间线的宽度。
事件
这些函数与事件相关,例如事件处理器:
frame.changeEvent(QtCore.QEvent): 这处理框架的状态变化。
frame.event(QtCore.QEvent): 这接收发送到框架对象的的事件,如果事件被识别并处理,则应返回true。
QFrame 示例
让我们在应用程序中创建简单的框架。通过在u_style.py文件中添加以下行,将两个框架放入主窗口的“文档”标签页:
- 将继承自
QtWidgets.QFrame的UFrame类添加到u_style.py文件中:
...
class UFrame(QtWidgets.QFrame):
def __init__(self, parent=None):
super(UFrame, self).__init__(parent)
self.setStyleSheet("background-color: %s;" % (color[2],))
...
在这个类中,我们使用setStyleSheet()方法设置框架的背景颜色。现在,我们需要在u_app.py文件中添加一些行。
- 将新的导入添加到
u_app.py文件的导入部分:
...
from u_style import UWid, UFrame
...
当我们在未来使用某些组件时,我们需要将u_style.py文件中创建的类添加到主应用程序文件的导入部分。
- 现在,在
u_app.py文件中的UApp类中添加框架及其布局:
...
def __init__(self, parent=None):
...
self.frame1 = UFrame(self.twid3)
self.frame1.setLineWidth(3)
self.frame1.setFrameStyle(6)
self.frame2 = UFrame(self.twid3)
self.frame2.setLineWidth(3)
self.frame2.setFrameStyle(0)
self.lay1 = QtWidgets.QGridLayout()
self.lay1.addWidget(self.frame1, 0, 0, 1, 1)
self.lay1.addWidget(self.frame2, 0, 1, 1, 1)
self.twid3.setLayout(self.lay1)
...
...
两个框架已经创建并按照网格布局排列。现在我们可以在主应用程序的“文档”标签页中看到两个不同的框架:

现在,让我们继续介绍QLabel类。
QLabel
标签是一个提供文本或图像显示的 GUI 应用程序中的小部件。QLabel继承自QFrame类。标签在 GUI 应用程序中演示或可视化一些信息。可以在标签上显示图像或电影,或以文本形式向用户显示信息。在应用程序代码中创建标签的语法如下:
label = QtWidgets.QLabel()
QLabel 的功能
QLabel扩展了QWidget和QFrame类,并提供以下功能。
设置
这些函数设置标签的参数/属性,例如文本和对齐方式:
label.setAlignment(QtCore.Qt.Alignment): 这设置标签中内容的对齐方式。
label.setBuddy(QtWidgets.QWidget): 这将标签的伙伴设置为参数中指定的。伙伴机制是当用户按下标签的快捷键时,键盘焦点将转移到标签的伙伴小部件。
label.setIndent(int): 这设置标签文本的缩进(以像素为单位)。
label.setMargin(int): 这设置框架最内层像素和标签内容最外层像素之间的距离。
label.setMovie(QtGui.QMovie): 这设置将在标签上显示的电影。
label.setNum(float**): 这设置浮点数的文本表示。
label.setNum(int): 这设置整数的文本表示。
label.setOpenExternalLinks(bool): 如果设置为True,则标签将自动打开外部链接。
label.setPicture(QtGui.QPicture): 这设置将在标签上显示的图片。
label.setPixmap(QtGui.QPixmap): 这设置标签的位图。
label.setScaledContents(bool): 如果设置为True,则此标签将缩放内容以填充所有可用空间。
label.setSelection(start, length): 这将设置文本的起始位置(第一个参数,一个整数)和长度(第二个参数,也是一个整数)。
label.setText(str): 这以 Unicode 字符串类型为此标签设置文本。
label.setTextFormat(QtCore.Qt.TextFormat): 这根据指定的参数设置标签的文本格式。
label.setTextInteractionFlags(QtCore.Qt.TextInteractionFlags): 这将设置标签如何与用户输入交互,如果它显示文本的话。
label.setWordWrap(bool): 如果设置为True,则文本将换行到标签的宽度。
有
以下是与标签状态相关的返回布尔值(bool)的函数:
label.hasScaledContents(): 如果标签允许我们缩放内容以填充所有可用空间,则返回True。
label.hasSelectedText(): 如果标签的某些或全部文本已被选中,则返回True。
功能性
这些是与标签当前值的返回或功能更改相关的函数:
label.alignment(): 这返回标签中元素的QtCore.Qt.Alignment类型的对齐方式。
label.buddy(): 这返回标签的QtWidgets.QWidget类型的伙伴。
label.clear(): 这清除标签的内容。
label.focusNextPrevChild(bool): 如果它可以找到一个新标签来提供键盘焦点,则返回True。如果参数为True,则向前搜索,如果为False,则向后搜索。
label.heightForWidth(width): 这返回给定整数参数width的此标签的首选高度。
label.indent(): 这返回标签的文本缩进(以像素为单位)。
label.margin(): 这返回此标签的框架最内层像素与内容最外层像素之间的距离。
label.minimumSizeHint(): 这返回可用于此标签的QtCore.QSize类型的最小尺寸提示。
label.movie(): 这返回指向标签的QtGui.QMovie类型的电影的指针。
label.openExternalLinks(): 如果标签应该自动打开链接,则返回True。
label.picture(): 这返回标签的QtGui.QPicture类型的图片。
label.pixmap(): 这返回标签的QtGui.QPixmap类型的位图。
label.selectedText(): 这返回作为此标签选中文本的 Unicode 字符串。
label.selectionStart(): 这返回此标签第一个选中字符的索引,如果没有文本被选中,则返回-1。
label.text(): 这返回标签的文本作为 Unicode 字符串。
label.textFormat(): 这个函数返回标签文本的 QtCore.Qt.TextFormat 类型的格式。
label.textInteractionFlags(): 这个函数返回此标签的 QtCore.Qt.TextInteractionFlags 类型的文本交互标志。
label.wordWrap(): 如果标签中的文本被换行到标签的宽度,则此函数返回 True。
事件
这些函数与事件相关,包括事件处理程序:
label.changeEvent(QtCore.QEvent): 这个函数处理标签的状态变化。
label.contextMenuEvent(QtGui.QContextMenuEvent): 这个事件处理程序接收上下文菜单事件。
label.event(QtCore.QEvent): 这个函数接收发送给对象的事件,如果事件被识别并处理,则应返回 True。
label.keyPressEvent(QtGui.QKeyEvent): 这个事件处理程序接收传递给参数的按键事件,用于此标签。
label.focusOutEvent(QtGui.QFocusEvent): 这个事件处理程序接收标签的键盘焦点事件,当失去焦点时,作为 event 参数传递。
label.focusInEvent(QtGui.QFocusEvent): 这个事件处理程序接收标签的键盘焦点事件,当获得焦点时,作为事件参数传递。
label.mouseMoveEvent(QtGui.QMouseEvent): 这个事件处理程序接收传递给参数的鼠标移动事件,用于此标签。
label.mousePressEvent(QtGui.QMouseEvent): 这个事件处理程序接收传递给参数的鼠标按下事件,用于此标签。
label.mouseReleaseEvent(QtGui.QMouseEvent): 这个事件处理程序接收传递给参数的鼠标释放事件,用于此标签。
label.paintEvent(QtGui.QPaintEvent): 这个事件处理程序接收传递给参数的绘制事件,用于此标签。
信号
这些是 QLabel 类的可用信号:
label.linkActivated(str): 当用户点击链接时,会发出此信号,URL 由传递给参数的锚点引用。
label.linkHovered(str): 当用户将鼠标悬停在链接上时,会发出此信号,URL 通过参数传递。
QLabel 示例
标签将在应用程序中使用多次。这只是一个简短的演示。现在我们有一个理由在 u_style.py 文件中创建一个带有字体的类。这些字体将用于后续的组件:
- 在
u_style.py文件的开始处插入UFonts类:
...
class UFonts(object):
def __init__(self, parent=None, ls=2.0, ws=2.0,
family="Verdana", size=12, weight=34):
self.font1 = QtGui.QFont()
self.font1.setLetterSpacing(QtGui.QFont.AbsoluteSpacing, ls)
self.font1.setWordSpacing(ws)
self.font1.setFamily(family)
self.font1.setPixelSize(size)
self.font1.setWeight(weight)
...
此类将用于更改小部件或图形元素的文本字体。
- 将
ULabel类添加到u_style.py文件中:
...
class ULabel(QtWidgets.QLabel):
def __init__(self, parent=None):
super(ULabel, self).__init__(parent)
font = UFonts(ls=3.0, size=14, weight=59)
self.setFont(font.font1)
self.setStyleSheet("""background-color: %s;
color: %s;"""
% (color[0], color[3]))
...
setFont() 方法使用 UFonts 类设置标签的字体。现在,我们需要在 u_app.py 文件中添加一些行。
- 将创建的
ULabel类添加到u_app.py文件的import部分:
...
from u_style import UWid, UFrame, ULabel
...
- 在
UApp类内部添加包含标签的行:
...
def __init__(self, parent=None):
...
...
self.label1 = ULabel(self.frame2)
self.label1.setText("User Information")
self.label1.setAlignment(QtCore.Qt.AlignCenter)
...
self.layfr2 = QtWidgets.QGridLayout()
self.layfr2.addWidget(self.label1, 0, 0, 1, 1)
self.frame2.setLayout(self.layfr2)
...
...
我们已经设置了带有文本和对齐方式的标签实例。将此标签添加到第二个框架的网格布局中。现在,我们可以运行 u_app.py 文件,结果如下(标签位于右侧):

现在,让我们继续介绍 QLineEdit 类。
QLineEdit
行编辑字段提供了一行文本编辑器。QLineEdit 类可用于创建一行用户输入字段,用于输入纯文本,例如用户名、电子邮件和密码。此外,一些其他类型的文本输入字段提供的信息更便于单独使用,并且具有一些特殊用途。行编辑字段通常与应用程序中的用户表单一起使用。在应用程序中,行编辑字段的声明语法如下:
line_edit = QtWidgets.QLineEdit()
QLineEdit 的功能
QLineEdit 类继承自 QWidget 类,并通过以下功能增强了功能。
add
这些函数向行 edit_field 添加元素或操作:
line_edit.addAction(QtWidgets.QAction, QtWidgets.QLineEdit.ActionPosition): 这将在特定位置(第二个参数)将操作(第一个参数)添加到操作列表中。
line_edit.addAction(QtGui.QIcon, QtWidgets.QLineEdit.ActionPosition): 这将在特定位置(第二个参数)添加带有图标(第一个参数)的新操作。
set
这些函数设置行编辑字段的参数/属性,例如文本、对齐方式和功能:
line_edit.setAlignment(QtCore.Qt.Alignment): 这将设置行编辑字段内容的对齐方式。
line_edit.setClearButtonEnabled(bool): 如果此参数为 True,则将行编辑字段设置为在非空时显示清除按钮。如果参数为 False,则行编辑字段中不会显示清除按钮。
line_edit.setCompleter(QtWidgets.QCompleter): 这将行编辑字段设置为从传递给参数的补全器自动完成。
line_edit.setCursorMoveStyle(QtCore.Qt.CursorMoveStyle): 这将设置此行编辑字段的光标移动样式。
line_edit.setCursorPosition(int): 这将为该行编辑字段设置光标位置。
line_edit.setDragEnabled(bool): 如果此参数为 True,则为此字段启用拖动。
line_edit.setEchoMode(QtWidgets.QLineEdit.EchoMode): 这将为行编辑字段设置回显模式。可用参数如下:
-
QtWidgets.QLineEdit.Normal:0 -
QtWidgets.QLineEdit.NoEcho:1 -
QtWidgets.QLineEdit.Password:2 -
QtWidgets.QLineEdit.PasswordEchoOnEdit:3
line_edit.setFrame(bool): 如果此参数为 True,则将行编辑字段的边框设置为。
line_edit.setInputMask(str): 这将为该行编辑字段设置输入掩码。
line_edit.setMaxLength(int): 这将设置此字段的字符最大长度。
line_edit.setModified(bool): 如果此参数为True,则将行编辑内容设置为已修改或更改/编辑。
line_edit.setPlaceholderText("Placeholder text"): 这将设置行编辑字段的占位符文本,即如果字段为空时将显示的文本。
line_edit.setReadOnly(bool): 如果参数为True,则将行编辑字段设置为只读模式,以便用户无法编辑其中的内容。
line_edit.setSelection(start, length): 这根据start参数(第一个参数)和length参数(第二个参数)在行编辑字段中选择文本。
line_edit.setText("Text in this field"): 这将设置与该行编辑字段一起显示的文本。
line_edit.setTextMargins(QtCore.QMargins): 这将设置围绕行编辑字段框架内部文本的边距。
line_edit.setTextMargins(left, top, right, bottom): 这将设置围绕行编辑字段内部文本的边距。每个参数都是一个整数值。
line_edit.setValidator(QtGui.QValidator): 这将设置参数中指定的QtGui.QValidator类型的验证器,这意味着此行编辑字段将只接受验证器接受的输入。
edit
这些函数对当前行编辑字段的内容进行一些更改,例如清除、撤销和重做:
line_edit.clear(): 这将清除行编辑字段的内容。
line_edit.copy(): 这将复制行编辑字段中选定的文本到剪贴板。
line_edit.cut(): 这将复制行编辑字段中选定的文本到剪贴板,并从字段中删除它。
line_edit.paste(): 这将在行编辑的光标位置插入剪贴板中的文本,并删除所有选定的文本。
line_edit.redo(): 如果可用,则重做最后一个操作。
line_edit.undo(): 如果可用,则撤销最后一个操作。
line_edit.selectAll(): 这将选择行编辑字段中的所有文本,并将光标移动到末尾。
has/is
这些函数返回与行编辑状态相关的布尔值(bool),例如,检查撤销功能是否可用:
line_edit.hasAcceptableInput(): 如果输入满足inputMask和验证器,则返回True。
line_edit.hasFrame(): 如果行编辑字段周围有框架,则返回True。
line_edit.hasSelectedText(): 如果行编辑有选定的文本,则返回True。
line_edit.isClearButtonEnabled(): 如果行编辑字段在非空时显示清除按钮,则返回True。
line_edit.isModified(): 如果行编辑的内容已被修改,则返回True。
line_edit.isReadOnly(): 如果行编辑处于只读模式,则此函数返回True,因此用户无法编辑其中的内容。
line_edit.isRedoAvailable(): 如果行编辑字段的内容具有重做功能,或者内容之前已被撤销,则返回 True。
line_edit.isUndoAvailable(): 如果行编辑字段的内容具有撤销功能,或者内容之前已被编辑/更改,则返回 True。
functional
这些函数返回行编辑字段的当前值,并将其更改为以下功能:
line_edit.alignment(): 这返回了行编辑字段中文本的对齐方式,为 QtCore.Qt.Alignment 类型。
line_edit.backspace(): 如果行编辑字段中没有选择文本,则将删除光标左侧的字符,并将光标向左移动一个位置。如果选择了任何文本,则将删除所选文本,并将光标移动到所选文本的开头。
line_edit.completer(): 这返回了行编辑字段中文本的当前补全器,为 QtWidgets.QCompleter 类型。
line_edit.createStandardContextMenu(): 这创建了一个标准上下文菜单,当用户在行编辑字段上右键单击时将显示。
line_edit.cursorBackward(bool,steps): 这通过字符(第二个参数)向后移动光标。如果第一个参数为 True,则每个字符都将被选择;否则,选择将被清除。
line_edit.cursorForward(bool, steps): 这通过字符(第二个参数)移动光标。如果第一个参数为 True,则每个字符都将被选择;否则,选择将被清除。
line_edit.cursorMoveStyle(): 这返回了此行编辑字段光标的移动方式,为 QtCore.Qt.CursorMoveStyle 类型。
line_edit.cursorPosition(): 这返回了行编辑字段中当前光标位置的整数值。
line_edit.cursorPositionAt(QtCore.QPoint): 这返回了参数中指定的点的光标位置。
line_edit.cursorRect(): 这返回了行编辑字段光标放置的 QtCore.QRect 类型的矩形。
line_edit.cursorWordBackward(bool): 这通过一个单词移动光标。如果参数为 True,则单词将被选择。
line_edit.cursorWordForward(bool): 这通过一个单词移动光标。如果参数为 True,则单词将被选择。
line_edit.del_(): 如果行编辑字段没有选择文本,它将删除光标右侧的字符。如果选择了文本,光标将移动到选择的开头,并删除所选文本。
line_edit.deselect(): 这取消选择了所选文本。
line_edit.displayText(): 这返回了显示的文本。
line_edit.dragEnabled(): 如果为此行编辑字段启用了拖动,则返回 True。
line_edit.echoMode(): 这返回了此行编辑字段的 QtWidgets.QLineEdit.EchoMode 类型的回显模式。
line_edit.end(bool): 这会将文本光标移动到行编辑字段的末尾。
line_edit.getTextMargins(): 这返回行编辑文本的左、上、右和下边距。
line_edit.home(bool): 这会将光标移动到行编辑字段的开始处。如果参数为 True,则选择文本;否则,取消选择任何选定的文本。
line_edit.inputMask(): 这返回行编辑字段的验证输入掩码。
line_edit.inputMethodQuery(QtCore.Qt.InputMethodQuery, object): 这用于查询行编辑字段的属性集,以支持复杂的输入法操作。
line_edit.insert("Text will be inserted"): 这在行编辑字段中插入新文本。它还会删除任何选定的文本并验证结果。
line_edit.maxLength(): 这返回此行编辑字段文本的最大长度。
line_edit.minimumSizeHint(): 这返回此行编辑字段的 QtCore.QSize 类型的最小大小提示。
line_edit.placeholderText(): 这返回行编辑字段的占位文本。只要字段为空,就会显示此文本。
line_edit.selectedText(): 这返回行编辑字段中选定的文本。
line_edit.selectionStart(): 这返回字段中选中文本中第一个字符的索引,如果没有文本被选中,则返回 -1。
line_edit.selectionEnd(): 这返回字段中选中文本的最后一个字符的索引,如果没有文本被选中,则返回 -1。
line_edit.selectionLength(): 这返回行编辑字段中选定的字符的长度。
line_edit.text(): 这返回行编辑字段的内容作为 Unicode 字符串。
line_edit.textMargins(): 这返回此字段文本的边距。
line_edit.validator(): 这返回此行编辑字段的验证器。
events
这些函数与事件相关,包括事件处理程序:
line_edit.changeEvent(QtCore.QEvent): 这处理行编辑字段的州变化。
line_edit.contextMenuEvent(QtGui.QContextMenuEvent): 此事件处理程序接收行编辑上下文菜单事件。
line_edit.dragEnterEvent(QtGui.QDragEnterEvent): 当鼠标进入行编辑字段并且正在拖动时,此事件处理程序会使用事件参数被调用。
line_edit.dragLeaveEvent(QtGui.QDragLeaveEvent): 当鼠标离开行编辑字段并且正在拖动时,此事件处理程序会使用事件参数被调用。
line_edit.dragMoveEvent(QtGui.QDragMoveEvent): 当发生某些条件时,例如光标进入字段;光标在字段内移动;或者在行编辑字段具有焦点的同时按下键盘上的修改键,并且正在拖动时,此事件处理程序会使用事件参数被调用。
line_edit.dropEvent(QtGui.QDropEvent): 当拖动到行编辑字段时,此事件处理程序会使用事件参数被调用。
line_edit.event(QtCore.QEvent): 此接收发送到对象的事件,如果事件被识别并已处理,则应返回True。
line_edit.focusOutEvent(QtGui.QFocusEvent): 此事件处理程序接收行编辑键盘焦点事件,当焦点丢失时,这些事件会通过事件参数传递。
line_edit.focusInEvent(QtGui.QFocusEvent): 此事件处理程序接收当接收到焦点时通过事件参数传递的行编辑键盘焦点事件。
line_edit.inputMethodEvent(QtGui.QInputMethodEvent): 此事件处理程序接收传递给参数的事件的输入法组合事件。
line_edit.keyPressEvent(QtGui.QKeyEvent): 此事件处理程序接收传递给参数的事件的行编辑字段的按键事件。
line_edit.mouseMoveEvent(QtGui.QMouseEvent): 此事件处理程序接收传递给参数的事件的此行编辑字段的鼠标移动事件。
line_edit.mousePressEvent(QtGui.QMouseEvent): 此事件处理程序接收传递给参数的事件的此行编辑字段的鼠标按下事件。
line_edit.mouseReleaseEvent(QtGui.QMouseEvent): 此事件处理程序接收传递给参数的事件的此行编辑字段的鼠标释放事件。
line_edit.mouseDoubleClickEvent(QtGui.QMouseEvent): 此事件处理程序接收传递给参数的事件的此行编辑字段的鼠标双击事件。
line_edit.paintEvent(QtGui.QPaintEvent): 此事件处理程序接收传递给参数的事件的此行编辑字段的绘制事件。
信号
QLineEdit类有以下信号可用:
line_edit.cursorPositionChanged(int, int): 当光标在行编辑字段内部移动时,会发出此信号。旧的和新的位置作为参数传递。
line_edit.editingFinished(): 当按下Enter键或字段失去焦点时,会发出此信号。
line_edit.returnPressed(): 当按下Enter键时,会发出此信号。
line_edit.selectionChanged(): 当行编辑文本选择发生变化时,会发出此信号。
line_edit.textChanged(str): 当字段中的文本发生变化时,会发出此信号;这也可以通过setText()方法以编程方式完成。
line_edit.textEdited(str): 当字段中的文本被编辑时,会发出此信号。它与使用setText()方法更改文本无关。
QLineEdit 示例
为了演示行编辑字段的函数,让我们将此字段放入应用程序中:
- 将
ULineEd类添加到u_style.py文件中:
...
class ULineEd(QtWidgets.QLineEdit):
def __init__(self, parent=None, tmrgl=10,
tmrgt=10, tmrgr=10, tmrgb=10,
drg=True, bdr=5, bdw=1, bdc=color[3]):
super(ULineEd, self).__init__(parent)
self.setClearButtonEnabled(True)
self.setDragEnabled(drg)
self.setTextMargins(tmrgl, tmrgt, tmrgr, tmrgb)
self.bdr = bdr
self.bdw = bdw
self.bdc = bdc
font = UFonts(size=14, weight=59)
self.setFont(font.font1)
self.setStyleSheet(
"""background-color: %s; color: %s;
border-radius: %spx; border-width: %spx;
border-color: %s;""" % (color[0],
color[3], self.bdr, self.bdw, self.bdc))
...
我们向此类添加了各种属性,例如文本边距和行编辑字段边框的颜色。现在,我们需要在u_app.py文件中实现此字段。
- 将以下内容添加到
u_app.py文件的import部分:
...
from u_style import ULineEd
...
- 将以下内容添加到
u_app.py文件的__init__()函数中:
...
def __init__(self, parent=None):
...
self.line_ed1 = ULineEd(self.frame2)
self.line_ed1.setPlaceholderText("Full Name...")
self.line_ed2 = ULineEd(self.frame2)
self.line_ed2.setPlaceholderText("Email...")
self.line_ed3 = ULineEd(self.frame2)
self.line_ed3.setPlaceholderText("Password...")
self.line_ed3.setEchoMode(QtWidgets.QLineEdit.Password)
self.layfr2 = QtWidgets.QGridLayout()
self.layfr2.addWidget(self.label1, 0, 0, 1, 1)
self.layfr2.addWidget(self.line_ed1, 1, 0, 1, 1)
self.layfr2.addWidget(self.line_ed2, 2, 0, 1, 1)
self.layfr2.addWidget(self.line_ed3, 3, 0, 1, 1)
...
...
我们添加了三个行编辑字段来输入用户名、电子邮件和密码。我们还添加到了第二个框架的布局中。
- 现在,运行应用程序以查看行编辑字段:

现在,让我们继续介绍 QTextEdit 类。
QTextEdit
QTextEdit 类用于多行文本表示。此字段支持文本的富格式和平格式。通常,富文本格式化用于在字段中插入 HTML 样式的标签,并具有显示和编辑它们的能力。多行字段是编辑模式下处理文本的最流行工具,用于创建文本编辑器、可视化并编辑文本文件。此类字段用于编写文本消息、创建文本文件、将信息保存到数据库以及许多其他事情。使用 QTextEdit 类创建的文本字段允许我们显示文本、图像、列表、表格和其他元素。为了在 GUI 应用程序中实现多行文本编辑器,我们需要了解文本表示的基础知识。根据操作系统(OS)的不同,使用行结束特殊字符,例如 \n 用于换行和 \r 用于回车,例如,Unix-like 系统中使用 \n 和 Windows(磁盘操作系统(DOS))中使用 \r\n。还有其他特殊字符,例如 \t 用于制表符和 \v 用于垂直制表符。默认情况下,QTextEdit 字段使用 \n 作为行结束的符号,但您需要记住,这些特殊符号对于文本字段中使用的外部文本可能会有所不同。QTextEdit 类的继承方案如下:

在应用程序中声明此类的方式如下:
text_edit = QtWidgets.QTextEdit()
QTextEdit 的功能
QTextEdit 类通过以下功能增强了继承类的功能。
set
这些函数将参数/属性设置到文本编辑字段中,例如文本、对齐方式和功能:
text_edit.setAcceptRichText(bool): 如果参数为 True,则文本字段将接受富文本。
text_edit.setAlignment(QtCore.Qt.Alignment): 这将设置当前段落的对齐方式。可用的参数包括 QtCore.Qt.AlignLeft,它将文本对齐到左边(默认);QtCore.Qt.AlignRight,它将文本对齐到右边;QtCore.Qt.AlignCenter,它将文本对齐到中间;以及 QtCore.Qt.AlignJustify,它使文本两端对齐。
text_edit.setAutoFormatting(QtWidgets.QTextEdit.AutoFormatting): 这将设置此文本字段的自动格式化功能。
text_edit.setCurrentCharFormat(QtGui.QTextCharFormat): 这将设置插入新文本时使用的字符格式。
text_edit.setCurrentFont(QtGui.QFont): 这将设置当前字符格式的字体。
text_edit.setCursorWidth(int): 这将设置与该文本字段一起可见的光标宽度。
text_edit.setDocument(QtGui.QTextDocument): 这将设置此文本字段的底层文档。
text_edit.setDocumentTitle("Document Title"): 这将设置底层文档的标题。
text_edit.setExtraSelections(selections): 这允许使用在selections参数中指定的颜色临时标记文本中的某些区域。
text_edit.setFontFamily("Font Family"): 这将设置当前格式的字体家族。
text_edit.setFontItalic(bool): 如果此参数为True,则当前格式的字体将被斜体。
text_edit.setFontPointSize(float): 这将设置当前格式的字体点大小。
text_edit.setFontUnderline(bool): 如果此参数为True,则当前格式的字体将被下划线。
text_edit.setFontWeight(int): 这将设置当前格式的字体粗细。
text_edit.setHtml("<p>Html tags</p>"): 这将使用 HTML 样式格式设置文本。所有之前的文本将被删除。
text_edit.setLineWrapColumnOrWidth(int): 这将设置文本将在此位置(以像素或列为单位,取决于换行模式)换行。
text_edit.setLineWrapMode(QtWidgets.QTextEdit.LineWrapMode): 这将为文本字段设置参数中指定的换行模式。
text_edit.setOverwriteMode(bool): 如果此参数为True,则输入的文本将覆盖现有文本。
text_edit.setPlaceholderText("Placeholder text"): 这将设置当此文本字段为空时使用的文本。
text_edit.setPlainText("Text"): 这将向文本字段添加纯文本。所有之前的文本将被删除。如果文本具有 HTML 样式标签,则这些标签将按原样(不带 HTML 样式格式)显示在文本中。
text_edit.setReadOnly(bool): 如果此参数为True,则将此文本字段的只读模式设置为用户无法编辑其中的内容。
text_edit.setTabChangesFocus(bool): 如果此参数为True,则允许Tab键更改焦点;否则,Tab键被视为输入。
text_edit.setTabStopDistance(float): 这将设置Tab停止距离(默认为80.0像素)。
text_edit.setTabStopWidth(int): 这将设置Tab停止宽度。
text_edit.setText("Text"): 这将设置文本字段中的文本。所有之前的文本将被删除。文本可以具有 HTML 样式格式或纯文本。HTML 将被格式化。
text_edit.setTextBackgroundColor(QtGui.QColor): 这将设置文本的背景颜色。
text_edit.setTextColor(QtGui.QColor): 这将设置文本颜色。
text_edit.setTextCursor(QtGui.QTextCursor): 这将设置与此文本字段一起可见的光标。
text_edit.setTextInteractionFlags(QtCore.Qt.TextInteractionFlags): 这将设置标志,以指定文本字段如何与用户输入交互。
text_edit.setUndoRedoEnabled(bool): 如果此参数为True,则允许我们在文本字段中执行撤销/重做操作。
text_edit.setWordWrapMode(QtGui.QTextOption.WrapMode): 这设置在文本编辑中用于换行的模式。
编辑
这些函数对文本编辑字段的内容进行一些更改,例如清除、撤销和重做:
text_edit.clear(): 这清除文本编辑字段的内容,并清除撤销/重做历史记录。
text_edit.copy(): 这将文本编辑字段中选定的文本复制到剪贴板。
text_edit.cut(): 这将文本字段中选定的文本复制到剪贴板,并从文本编辑字段中删除它。
text_edit.paste(): 这将在文本字段的光标位置粘贴剪贴板中的文本。
text_edit.redo(): 如果对于此文本字段可用,则重做最后一个操作。
text_edit.undo(): 如果对于此文本字段可用,则撤销最后一个操作。
text_edit.selectAll(): 这选择文本编辑字段中的所有文本,并将光标移动到文本的末尾。
text_edit.zoomIn(int): 这通过在参数指定的范围内增大字体大小来放大文本,并重新计算所有字体大小。它不会改变图像的大小。
text_edit.zoomInF(float): 这通过在参数指定的范围(float)内增大字体大小来放大文本,并重新计算所有字体大小。它不会改变图像的大小。
text_edit.zoomOut(int): 这通过在参数指定的范围内减小字体大小来缩小文本,并重新计算所有字体大小。它不会改变图像的大小。
是
这些函数返回与文本编辑状态相关的布尔值(bool),例如检查撤销功能的可用性:
text_edit.isReadOnly(): 如果文本字段处于只读模式,则返回True,因此用户无法编辑其中的内容。
text_edit.isUndoRedoEnabled(): 如果撤销和重做操作对此文本编辑字段可用,则返回True。
功能性
这些函数返回文本编辑字段的当前值和功能更改:
text_edit.acceptRichText(): 如果文本字段接受允许 HTML 样式标签的富文本插入,则返回True。如果返回False,则文本字段仅接受纯文本输入。
text_edit.alignment(): 这返回当前段落的文本对齐方式。
text_edit.anchorAt(QtCore.QPoint): 这返回在参数指定的位置上的锚点的 Unicode 字符串引用。
text_edit.append("Text to append"): 这将新的文本段落追加到文本字段中,作为字段中最后一行的下一行。
text_edit.autoFormatting(): 这返回为该文本字段启用的QtWidgets.QTextEdit.AutoFormatting类型的自动格式化功能。
text_edit.canInsertFromMimeData(QtCore.QMimeData): 如果在参数中指定的 MIME 数据对象的内 容可以被解码并插入到文本字段中,则返回True。
text_edit.canPaste(): 如果可以从剪贴板粘贴文本到这个文本字段,则返回True。
text_edit.createMimeDataFromSelection(): 这返回一个新的QtCore.QMimeData类型的 MIME 数据对象,用于表示此文本编辑字段选择的内容。
text_edit.createStandardContextMenu(): 这创建一个标准上下文菜单,当用户用鼠标右键单击文本编辑字段时显示。
text_edit.createStandardContextMenu(QtCore.QPoint): 这创建一个标准上下文菜单,当用户在文本编辑字段上右击时显示,并出现在鼠标点击发生的位置,由参数指定。
text_edit.currentCharFormat(): 这返回当插入新文本时将使用的当前字符格式。
text_edit.currentFont(): 这返回文本格式的当前字体。
text_edit.cursorForPosition(QtCore.QPoint): 这返回在参数中指定的位置(在视口坐标中)的QtGui.QTextCursor类型的光标。
text_edit.cursorRect(): 这返回包含此文本字段光标的QtCore.QRect类型(在视口坐标中)的矩形。
text_edit.cursorRect(QtGui.QTextCursor): 这返回一个包含在参数中指定的光标的QtCore.QRect类型(在视口坐标中)的矩形。
text_edit.cursorWidth(): 这返回光标在像素中的宽度(默认为1)。
text_edit.document(): 这返回表示为QtGui.QTextDocument类型底层文档的文本编辑字段的内容。
text_edit.documentTitle(): 这返回从文本解析出的底层文档的标题。
text_edit.ensureCursorVisible(): 这确保文本光标可见,并在必要时滚动文本编辑字段。
text_edit.extraSelections(): 这返回之前设置的额外选择。
text_edit.find("Text to find", QtGui.QTextDocument.FindFlags): 使用指定的搜索规则(第二个参数)查找文本(第一个参数)的下一个出现,如果找到文本,则返回True并选择此文本。
text_edit.find(QtCore.QRegExp, QtGui.QTextDocument.FindFlags): 使用指定的搜索规则(第二个参数)查找与正则表达式(第一个参数)匹配的下一个出现,如果找到文本,则返回True并在字段中选择此文本。
text_edit.fontFamily(): 这返回当前文本格式的字体族。
text_edit.fontItalic(): 如果当前文本格式是斜体,则返回True。
text_edit.fontPointSize(): 这返回当前文本格式的字体点大小。
text_edit.fontUnderline(): 如果当前文本格式是下划线,则返回True。
text_edit.fontWeight(): 这返回当前文本格式的字体粗细。
text_edit.inputMethodQuery(QtCore.Qt.InputMethodQuery, object): 这用于查询文本编辑字段的一组属性,以支持复杂的输入法操作,例如支持周围文本和重新转换。
text_edit.insertFromMimeData(QtCore.QMimeData): 这将参数中指定的 MIME 数据对象的内 容插入到文本编辑字段当前光标位置。
text_edit.insertHtml("<p>Html tags</p>"): 这将在当前光标位置插入带有 HTML 格式的文本(如果文本是 HTML 样式)。
text_edit.insertPlainText("Text"): 这将在当前光标位置插入文本。如果文本有 HTML 格式,则标签将不会被格式化,文本将按原样表示。
text_edit.lineWrapColumnOrWidth(): 这返回文本将换行的像素位置或列数(取决于换行模式)。
text_edit.lineWrapMode(): 这返回此文本字段的QtWidgets.QTextEdit.LineWrapMode类型的行换行模式。
text_edit.loadResource(int, QtCore.QUrl): 这使用类型(第一个参数)和 URL(第二个参数)指定的类型加载资源。
text_edit.mergeCurrentCharFormat(QtGui.QTextCharFormat): 这将参数中指定的属性合并到当前字符的格式中。
text_edit.moveCursor(QtGui.QTextCursor.MoveOperation, QtGui.QTextCursor.MoveMode): 这根据参数移动光标。如果第二个参数是QtGui.QTextCursor.KeepAnchor,则光标在移动时会选择文本。可用的移动操作如下:
-
QtGui.QTextCursor.NoMove–0: 光标保持在当前位置。 -
QtGui.QTextCursor.Start–1: 光标移动到文本的开始。 -
QtGui.QTextCursor.StartOfLine–3: 光标移动到当前行的开始。 -
QtGui.QTextCursor.StartOfBlock–4: 光标移动到当前块(段落)的开始。 -
QtGui.QTextCursor.StartOfWord–5: 光标移动到当前单词的开始。 -
QtGui.QTextCursor.PreviousBlock–6: 光标移动到前一个块的开始。 -
QtGui.QTextCursor.PreviousCharacter–7: 光标移动到前一个字符的开始。 -
QtGui.QTextCursor.PreviousWord–8: 光标移动到前一个单词的开始。 -
QtGui.QTextCursor.Up–2: 光标向上移动一行。 -
QtGui.QTextCursor.Left–9: 光标向左移动一个字符。 -
QtGui.QTextCursor.WordLeft–10: 光标向左移动一个单词。 -
QtGui.QTextCursor.End–11: 光标移动到文本的末尾。 -
QtGui.QTextCursor.EndOfLine–13: 光标移动到当前行的末尾。 -
QtGui.QTextCursor.EndOfWord–14: 光标移动到当前单词的末尾。 -
QtGui.QTextCursor.EndOfBlock–15: 光标移动到当前块的末尾。 -
QtGui.QTextCursor.NextBlock–16: 光标移动到下一个块的开始。 -
QtGui.QTextCursor.NextCharacter–17: 光标移动到下一个字符。 -
QtGui.QTextCursor.NextWord–18: 光标移动到下一个单词。 -
QtGui.QTextCursor.Down–12: 光标向下移动一行。 -
QtGui.QTextCursor.Right–19: 光标向右移动一个字符。 -
QtGui.QTextCursor.WordRight–20: 光标向右移动一个单词。 -
QtGui.QTextCursor.NextCell–21: 光标移动到当前表格内的下一个单元格。 -
QtGui.QTextCursor.PreviousCell–22: 光标移动到当前表格内的上一个单元格。 -
QtGui.QTextCursor.NextRow–23: 光标移动到当前表格内的下一行。 -
QtGui.QTextCursor.PreviousRow–24: 光标移动到当前表格内的上一行。
text_edit.overwriteMode(): 如果输入的文本将覆盖现有文本,则返回 True。
text_edit.placeholderText(): 这返回当此文本字段为空时将使用的占位文本。
text_edit.print(QtGui.QPagedPaintDevice): 这是一个便利函数,用于使用打印机设备打印文本字段中的文本。
text_edit.print_(QtGui.QPagedPaintDevice): 这使用打印机设备打印文本字段的文本。
text_edit.scrollToAnchor(str): 这将文本编辑字段滚动,以便参数中的字符串的锚点可见。
text_edit.tabChangesFocus(): 如果 Tab 键改变焦点,则返回 True。
text_edit.tabStopDistance(): 这返回 Tab 停止距离。
text_edit.tabStopWidth(): 这返回 Tab 停止宽度。
text_edit.textBackgroundColor(): 这返回 QtGui.QColor 类型的文本背景颜色。
text_edit.textColor(): 这返回 QtGui.QColor 类型的文本颜色。
text_edit.textCursor(): 这返回 QtGui.QTextCursor 类型的光标副本,显示当前可见的光标。
text_edit.textInteractionFlags(): 这返回指定用户输入交互的 QtCore.Qt.TextInteractionFlags 类型的标志。
text_edit.toHtml(): 这返回具有 HTML 样式的格式化文本。
text_edit.toPlainText(): 这返回文本字段的纯文本。
text_edit.wordWrapMode(): 这返回用于在文本编辑字段中换行时使用的 QtGui.QTextOption.WrapMode 类型的模式。
events
这些函数与事件相关,例如事件处理程序:
text_edit.changeEvent(QtCore.QEvent): 这处理此文本编辑字段的状态变化。
text_edit.contextMenuEvent(QtGui.QContextMenuEvent): 此事件处理程序接收文本编辑上下文菜单事件。
text_edit.dragEnterEvent(QtGui.QDragEnterEvent): 当鼠标进入文本编辑字段且正在拖动时,此事件处理程序会使用事件参数调用。
text_edit.dragLeaveEvent(QtGui.QDragLeaveEvent): 当鼠标离开文本编辑字段且正在拖动时,此事件处理程序会使用事件参数调用。
text_edit.dragMoveEvent(QtGui.QDragMoveEvent): 当发生某些条件时,例如光标进入字段、光标在字段内移动、在文本编辑字段获得焦点时按下修改键,或者拖动正在进行时,此事件处理程序会使用事件参数被调用。
text_edit.dropEvent(QtGui.QDropEvent): 此事件处理程序在拖动被放置在文本编辑字段上时,使用事件参数被调用。
text_edit.event(QtCore.QEvent): 此接收发送到对象的信号,如果事件被识别并处理,则应返回True。
text_edit.focusOutEvent(QtGui.QFocusEvent): 此事件处理程序接收文本编辑字段键盘焦点事件,当焦点丢失时,这些事件通过事件参数传入。
text_edit.focusInEvent(QtGui.QFocusEvent): 此事件处理程序接收文本字段键盘焦点事件,当接收到焦点时,这些事件通过事件参数传入。
text_edit.inputMethodEvent(QtGui.QInputMethodEvent): 此事件处理程序接收通过参数传入的输入法组合事件。
text_edit.keyPressEvent(QtGui.QKeyEvent): 此事件处理程序接收此文本编辑字段的按键事件,事件通过参数传入。
text_edit.keyReleaseEvent(QtGui.QKeyEvent): 此事件处理程序接收此文本字段的按键释放事件,事件通过参数传入。
text_edit.mouseMoveEvent(QtGui.QMouseEvent): 此事件处理程序接收此文本编辑字段的鼠标移动事件,事件通过参数传入。
text_edit.mousePressEvent(QtGui.QMouseEvent): 此事件处理程序接收此文本字段的鼠标按下事件,事件通过参数传入。
text_edit.mouseReleaseEvent(QtGui.QMouseEvent): 此事件处理程序接收此文本字段的鼠标释放事件,事件通过参数传入。
text_edit.mouseDoubleClickEvent(QtGui.QMouseEvent): 此事件处理程序接收此文本编辑字段的鼠标双击事件,事件通过参数传入。
text_edit.paintEvent(QtGui.QPaintEvent): 此事件处理程序接收此文本字段的绘制事件,事件通过参数传入。
text_edit.resizeEvent(QtGui.QResizeEvent): 此事件处理程序接收此文本字段的调整大小事件,事件通过参数传入。
text_edit.showEvent(QtGui.QShowEvent): 此事件处理程序接收文本字段的显示事件,事件通过参数传入。
text_edit.timerEvent(QtCore.QTimerEvent): 此事件处理程序接收文本字段的定时器事件,事件通过参数传入。
text_edit.wheelEvent(QtGui.QWheelEvent): 此事件处理程序接收此字段的鼠标滚轮事件,事件通过参数传入。
信号
QTextEdit类可用的信号如下:
text_edit.copyAvailable(bool):当在文本字段中选择或取消选择文本时,会发出此信号。如果文本被选中,则参数将为True。
text_edit.currentCharFormatChanged(QtGui.QTextCharFormat):当当前字符格式发生变化时,会发出此信号。新格式在参数中。
text_edit.cursorPositionChanged():当光标在文本字段内移动时,会发出此信号。
text_edit.redoAvailable(bool):当重做操作可用(参数为True)或不可用(参数为False)时,会发出此信号。
text_edit.undoAvailable(bool):当撤销操作可用(参数为True)或不可用(参数为False)时,会发出此信号。
text_edit.selectionChanged():当文本编辑的文本选择发生变化时,会发出此信号。
text_edit.textChanged(str):当字段内容发生变化时,会发出此信号。
QTextEdit 示例
让我们在 GUI 应用程序中演示一个多行文本字段。请按照以下章节中描述的步骤进行操作:
- 在
u_style.py文件中创建UTextEd类:
...
class UTextEd(QtWidgets.QTextEdit):
def __init__(self, parent=None, bgcolor=color[0], sbh=7,
sbv=7, sbc=color[1], tepad=7, tebgcolor=color[1],
tetxc=color[3], lh=14, bdr=5, bdw=1, bdc=color[3]):
super(UTextEd, self).__init__(parent)
self.setAcceptRichText(True)
self.setUndoRedoEnabled(True)
self.bgcolor, self.tebgcolor = bgcolor, tebgcolor
self.sbh, self.sbv, self.sbc = sbh, sbv, sbc
self.tepad, self.tetxc, self.lh = tepad, tetxc, lh
self.bdr, self.bdw, self.bdc = bdr, bdw, bdc
font = UFonts(size=14, weight=59)
self.setFont(font.font1)
self.setStyleSheet(
"""QWidget {background-color: %s;}
QScrollBar:horizontal {width: %spx;
height: %spx; background-color: %s;}
QScrollBar:vertical {width: %spx;
height: %spx; background-color: %s;}
QTextEdit {padding: %spx;
background-color: %s; color: %s;
line-height: %spx; border-style: solid;
border-radius: %spx; border-width: %spx;
border-color: %s;}"""
% (self.bgcolor, self.sbh, self.sbv, self.sbc,
self.sbh, self.sbv, self.sbc, self.tepad,
self.tebgcolor, self.tetxc, self.lh,
self.bdr, self.bdw, self.bdc))
...
此类可用的属性包括滚动条属性、文本字段的行高、边框属性等。现在,我们需要将此文本编辑字段添加到u_app.py文件中。
- 将
UTextEd添加到u_app.py文件的import部分:
...
from u_style import ULineEd, UTextEd
...
- 将文本字段行添加到
u_app.py文件的__init__()函数中:
...
def __init__(self, parent=None):
...
self.text_edit = UTextEd(self.frame1)
self.layfr1 = QtWidgets.QGridLayout()
self.layfr1.addWidget(self.text_edit, 0, 0, 1, 1)
...
...
文本编辑实例添加到第一个框架的网格布局中。现在,我们可以在该字段中输入不同的文本,并进行剪切、复制、粘贴等操作。
其他提示
在 GUI 应用程序中,最常见的文本字段实现是创建各种编辑器。这可能是文本编辑器或代码编辑器,用于处理文本或输入代码。因此,拼写检查和与各种语言的语法工作函数非常受欢迎。让我们描述一下在 GUI 应用程序的文本编辑字段中拼写检查的实现。示例是一个在文本编辑字段中提供拼写检查功能的类。首先,我们需要安装额外的包。对此最有用的包是pyenchant。要在 cmd/Terminal 中安装此包,请输入以下内容:
> pip install pyenchant
然后,在App/App_PySide2和App/App_PyQt5目录中创建两个名为u_adds.py的文件(如果没有,请选择其中一个)并执行以下步骤:
- 将以下内容添加到 PyQt5 的
u_adds.py文件import部分:
...
import re
from PyQt5.Qt import QSyntaxHighlighter
from PyQt5.Qt import QTextCharFormat
from PyQt5.Qt import Qt
...
- 将以下内容添加到 PySide2 的
u_adds.py文件import部分:
...
import re
from PySide2.QtGui import QSyntaxHighlighter
from PySide2.QtGui import QTextCharFormat
from PySide2.QtCore import Qt
...
- 在两个
u_adds.py文件中添加UHighLight类:
...
class UHighLight(QSyntaxHighlighter):
words = u"(?iu)[\\w\']+"
def __init__(self, *args):
super(UHighLight, self).__init__(*args)
self.dicts = None
def setDict(self, dicts):
self.dict = dicts
def highlightBlock(self, text):
if not self.dict:
return
formats = QTextCharFormat()
formats.setUnderlineColor(Qt.red)
formats.setUnderlineStyle(
QTextCharFormat.SpellCheckUnderline)
for w in re.finditer(self.words, text):
if not self.dict.check(w.group()):
self.setFormat(w.start(),
w.end() - w.start(), formats)
...
这个类用于在文本字段中通过enchant库突出显示不正确的文本。要在应用程序的文本字段中使用此工具,我们需要在u_app.py文件中添加一些行。
- 将以下行添加到
u_app.py文件的import部分:
...
import enchant
from u_adds import UHighLight
...
- 将
UHighLight类添加到u_app.py文件的__init__()函数中:
...
def __init__(self, parent=None):
...
self.dicts = enchant.Dict("en_US")
self.highlighter = UHighLight(self.text_edit.document())
self.highlighter.setDict(self.dicts)
...
我们现在需要创建字典。将UHighLight类实例与文本编辑字段的文档作为参数添加,并设置字典。结果将看起来像这样:

这只是一个示例,并且是可选的。此外,在使用这个拼写检查功能时必须小心,因为这些工具可能会导致内存成本问题,如果构造不是以正确的方式线程化,应用程序的性能将受到影响。还有其他提供额外字典的包,这些字典支持各种语言。
摘要
本章探讨的元素是 GUI 应用程序的基本组件。框架提供了一个方便的方式来组合图形组件,标签提高了信息可视化。单行和多行文本字段在用户通信中最受欢迎。此外,PyQt5 和 PySide2 还有其他你可以用来处理文本的类,例如QTextBrowser,它通过额外的功能改进了QTextEdit。还有,QtGui类的QTextDocument代表文本编辑字段中的文档化文本,而QTextCursor类提供了对光标的操作。
在下一章中,我们将继续介绍图形元素,并将探讨混合组件,例如组合框和列表视图,这些组件具有文本和控制功能。
第七章:使用 Combobox 和列表视图
本章将要讨论的 GUI 组件在性质上有些混合。它们是文本字段,可以用来控制应用程序中的元素。换句话说,用户可以在这些字段中输入文本,然后通过提供额外功能的下拉菜单进行选择。使用这些组件有助于使 GUI 应用程序更加紧凑和富有信息量。
本章中的组件代表了 Qt 框架中的模型-视图范式。简而言之,行编辑字段也可以使用列表视图实现。
本章将涵盖以下主题:
-
模型-视图架构
-
Combobox
-
简单列表视图
-
表格
模型-视图架构
Qt 框架有一组类,它们利用模型-视图范式来调节数据与其表示之间的关系,称为模型-视图-控制器(MVC)范式。MVC 是一种在建立用户界面时经常使用的模式。MVC 有三个类型的对象:
-
模型(应用程序对象)
-
视图(屏幕展示)
-
控制器(定义用户界面上的用户输入动作)
以下图表展示了模型、视图和控制器之间的交互:

在 Qt 框架中,当视图和控制器结合时,这创建了模型-视图架构。要使用 Qt 创建模型,框架使用QtCore模块的类,如基类QAbstractItemModel及其继承此类的类,如QAbstractListModel和QAbstractTableModel。表示视图的类使用QtWidgets模块中的视图,如QListView、QTableView和QTreeView,并继承基类QAbstractItemView。在这里,我们将仅描述其中的一些,包括使用应用程序实现模型-视图架构的基本知识。有关更深入的了解,请参阅文档(doc.qt.io/qt-5/model-view-programming.html)。
QAbstractItemModel
此类实现了模型类的抽象接口。模型-视图架构中用于操作模型部分的函数的完整列表可在文档中找到。此类的构造语法如下:
class Model(QtCore.QAbstractItemModel):
def __init__(self, parent=None):
super(Model, self).__init__(parent)
def rowCount(self, parent):
return ...
def columnCount(self, parent):
return ...
def index(self, row, column, parent):
return ...
def data(self, index, role):
return ...
需要重写的函数如下:
columnCount(QtCore.QModelIndex): 这返回参数中指定的父项下的列数。
data(QtCore.QModelIndex, int): 这返回第一个参数指定的项在角色(第二个参数)下存储的数据。
index(int, int, QtCore.QModelIndex): 这返回由行(第一个参数)、列(第二个参数)和父项(第三个参数)指定的模型中项的索引。
rowCount(QtCore.QModelIndex): 这返回参数中指定的父项下的行数。
最有用的函数如下:
insertColumn(int, QtCore.QModelIndex): 这在父项(第二个参数)的子项中指定为第一个参数的列之前插入列。
insertColumns(int, int, QtCore.QModelIndex): 这将在由父模型索引(第三个参数)表示的项目相关列(第一个参数)之前插入指定数量的新列(第二个参数)。
insertRow(int, QtCore.QModelIndex): 这在父项(第二个参数)的子项中指定为第一个参数的行之前插入行。
insertRows(int, int, QtCore.QModelIndex): 这将在由父模型索引(第三个参数)表示的项目相关行(第一个参数)之前插入指定数量的新行(第二个参数)。
moveColumn(QtCore.QModelIndex, int, QtCore.QModelIndex, int): 这将源列(第二个参数)从源父项(第一个参数)移动到目标父项(第三个参数)下的目标子项(第四个参数)。
moveColumns(QtCore.QModelIndex, int, int, QtCore.QModelIndex, int): 这将根据第三个参数指定的列数,从源列(第二个参数)开始,从源父项(第一个参数)移动到目标父项(第四个参数)下的目标子项(第五个参数)。
moveRow(QtCore.QModelIndex, int, QtCore.QModelIndex, int): 这将源行(第二个参数)从源父项(第一个参数)移动到目标父项(第三个参数)下的目标子项(第四个参数)。
moveRows(QtCore.QModelIndex, int, int, QtCore.QModelIndex, int): 这将根据第三个参数指定的行数,从源行(第二个参数)开始,从源父项(第一个参数)移动到目标父项(第四个参数)下的目标子项(第五个参数)。
removeColumn(int, QtCore.QModelIndex): 这将移除父项(第二个参数)的列(第一个参数)。
removeColumns(int, int, QtCore.QModelIndex): 这将根据第二个参数指定的列数,从父项(第三个参数)的列(第一个参数)开始移除。
removeRow(int, QtCore.QModelIndex): 这将移除父项(第二个参数)的行(第一个参数)。
removeRows(int, int, QtCore.QModelIndex): 这将根据第二个参数指定的行数,从父项(第三个参数)的行(第一个参数)开始移除。
sort(int, QtCore.Qt.SortOrder): 这根据第二个参数指定的顺序对模型按列(第一个参数)进行排序。
setData(QtCore.QModelIndex, object, int): 这将使用指定的角色(第三个参数)和索引(第一个参数)将项目的数据设置为一个指定的值(第二个参数)。
setHeaderData(int, QtCore.Qt.Orientation, object, int): 这将使用指定的角色(第四个参数)、部分(第一个参数)和方向(第二个参数)将头部数据设置为一个指定的值(第三个参数)。
QAbstractTableModel
此类提供了一个标准接口,将数据作为二维数组在模型中表示。QAbstractTableModel类继承自QAbstractItemModel类。此类的构造语法如下:
class Model(QtCore.QAbstractTableModel):
def __init__(self, parent=None):
super(Model, self).__init__(parent)
def rowCount(self, parent):
return ...
def columnCount(self, parent):
return ...
def data(self, row, column):
return ...
QAbstractItemView
这是一个提供 Qt 框架中视图类基本功能的基类。通常,这个类在 GUI 应用程序构建中会通过QListView、QTreeView和QTableView类进行重实现。这个类的继承方案如下:

与 GUI 应用程序一起常用的函数包括以下(完整列表可在文档中找到):
setDragEnabled(bool): 如果参数为True,视图将支持项目的拖动。
setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode): 这将设置拖放模式;默认情况下,视图不支持拖放。可用的模式如下:
-
QtWidgets.QAbstractItemView.NoDragDrop—0:此视图不支持拖放。 -
QtWidgets.QAbstractItemView.DragOnly—1:此视图支持拖动。 -
QtWidgets.QAbstractItemView.DropOnly—2:此视图支持放下。 -
QtWidgets.QAbstractItemView.DragDrop—3:此视图支持拖放。 -
QtWidgets.QAbstractItemView.InternalMove—4:此视图将接受移动操作,不包括复制。
setDropIndicatorShown(bool): 如果参数为True,这将设置放下指示器,如在使用拖放项目时所示。
setModel(QtCore.QAbstractItemModel): 这将设置视图将表示的模型。
setRootIndex(QtCore.QModelIndex): 这将根据参数中指定的索引设置根项。
setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior): 这将设置视图将使用的选择行为。可用的行为如下:
-
QtWidgets.QAbstractItemView.SelectItems—0:单个项目。 -
QtWidgets.QAbstractItemView.SelectRows—1:仅行。 -
QtWidgets.QAbstractItemView.SelectColumns—2:仅列。
setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode): 这将设置视图对选择如何响应。可用的选择模式如下:
-
QtWidgets.QAbstractItemView.NoSelection—0:项目未被选中。 -
QtWidgets.QAbstractItemView.SingleSelection—1: 已选中的项目将被取消选中。 -
QtWidgets.QAbstractItemView.MultiSelection—2: 选中的项目将被切换,其他项目保持不变。可以通过拖动鼠标在它们上方来切换多个项目。 -
QtWidgets.QAbstractItemView.ExtendedSelection—3: 已选中的项目将被选中并取消选中,使用 Shift 键或 Ctrl 键,点击的项目将被切换,而其他项目保持不变。 -
QtWidgets.QAbstractItemView.ContiguousSelection—4: 已选中的项目将被取消选中,且使用 Shift 键不会取消选中。
setSelectionModel(QtCore.QItemSelectionModel): 设置参数中指定的选择模型。
setState(QtWidgets.QAbstractItemView.State): 设置参数中指定的项目视图状态。状态如下:
-
QtWidgets.QAbstractItemView.NoState—0: 默认状态。 -
QtWidgets.QAbstractItemView.DraggingState—1: 用户正在拖动项目。 -
QtWidgets.QAbstractItemView.DragSelectingState—2: 用户正在选择项目。 -
QtWidgets.QAbstractItemView.EditingState—3: 用户正在编辑项目。 -
QtWidgets.QAbstractItemView.ExpandingState—4: 用户通过分支打开项目。 -
QtWidgets.QAbstractItemView.CollapsingState—5: 用户关闭了项目分支。 -
QtWidgets.QAbstractItemView.AnimatingState—6: 这是执行动画的视图。
edit(QtCore.QModelIndex): 根据参数中指定的索引开始编辑项目。
model(): 返回在视图中表示的 QtCore.QAbstractItemModel 类型的模型。
selectAll(): 选择视图中表示的所有项目。
startDrag(QtCore.Qt.DropActions): 通过调用带有 exec() 的拖动操作来启动拖动过程,这与参数中指定的放置动作相关。
update(QtCore.QModelIndex): 更新参数中指定的索引所占据的区域。
QComboBox
使用 QComboBox 类构建的组合框小部件提供了组合按钮和弹出列表。此小部件包含显示当前文本的字段(或可以编辑),包含一些值的弹出列表,以及进行选择和选择多个控件选项的选项。这可以在需要用选项表示多个值以从弹出窗口中选择某物,并且可能意味着其他功能的 GUI 中使用。开发者在图形窗口内部空间有限且需要显示许多值的地方创建组合框。QComboBox 类在应用程序中的声明语法如下:
combo_box = QtWidgets.QComboBox()
QComboBox 函数
QComboBox 继承了 QWidget 类,并通过以下函数增强了功能。
添加
这些是与向组合框添加元素或动作相关的函数:
combo_box.addItem("item", object): 这将在组合框弹出列表的末尾添加项目(第一个参数)为 Unicode 字符串类型和可选的用户数据(第二个参数,默认为None)。
combo_box.addItem(QtGui.QIcon, "item", object): 这将在组合框弹出列表的末尾添加项目(第二个参数)为 Unicode 字符串类型和可选的用户数据(第三个参数,默认为None)。项目的文本将显示为图标(第一个参数)。
combo_box.addItems(["item"]): 这将添加多个具有 Unicode 字符串类型文本的项目到组合框弹出列表的末尾。参数中指定的列表的每个项目都将作为弹出列表的新行附加。
set
这些是与设置与组合框相关的参数/属性设置相关的函数,包括文本、对齐或功能设置:
combo_box.setCompleter(QtWidgets.QCompleter): 这将设置与组合框一起使用的补全器。
combo_box.setCurrentIndex(int): 这将设置组合框中参数指定的项目索引。具有此索引的项目将被标记为当前项并可见。
combo_box.setCurrentText("Item"): 这将设置组合框中参数指定的当前文本。具有此文本的项目将被标记为当前项并可见。
combo_box.setDuplicatesEnabled(bool): 如果参数为True,则允许将重复的项目输入到组合框中。
combo_box.setEditable(bool): 如果参数为True,则设置组合框可以使用行编辑字段进行编辑。
combo_box.setEditText("Text"): 这将设置组合框行编辑字段中的文本。
combo_box.setFrame(bool): 如果参数为True,则设置组合框周围的框架。
combo_box.setIconSize(QtCore.QSize): 这将设置组合框中显示的图标的大小。
combo_box.setInsertPolicy(QtWidgets.QComboBox.InsertPolicy): 这将设置此组合框的插入策略。可用的策略如下:
-
QtWidgets.QComboBox.NoInsert—0: 项目将不会被插入。 -
QtWidgets.QComboBox.InsertAtTop—1: 当前项目将被插入为第一个项目。 -
QtWidgets.QComboBox.InsertAtCurrent—2: 组合框中的当前项目将被新项目替换。 -
QtWidgets.QComboBox.InsertAtBottom—3: 当前项目将被插入到最后一个项目之后。 -
QtWidgets.QComboBox.InsertAfterCurrent—4: 此项目将被插入到当前项目之后。 -
QtWidgets.QComboBox.InsertBeforeCurrent—5: 此项目将被插入到当前项目之前。 -
QtWidgets.QComboBox.InsertAlphabetically—6: 此项目将按字母顺序插入。
combo_box.setItemData(int, object, int): 这将为具有索引(第一个参数)的项目设置数据角色(第三个参数),其值为第二个参数指定的值。
combo_box.setItemDelegate(QtWidgets.QAbstractItemDelegate): 这将为弹出列表视图项目设置代理。
combo_box.setItemIcon(int, QtGui.QIcon): 这将为由索引(第一个参数)指定的项目设置图标(第二个参数)。
combo_box.setItemText(int, "Item"): 这将为由索引(第一个参数)指定的项目设置文本(第二个参数)。
combo_box.setLineEdit(QtWidgets.QLineEdit): 这将为这个组合框设置将使用的行编辑字段。
combo_box.setMaxCount(int): 这将为这个组合框设置将使用的最大项目数。
combo_box.setMaxVisibleItems(int): 这将设置组合框屏幕中不滚动时将可见的最大项目数。
combo_box.setMinimumContentsLength(int): 这将设置用组合框屏幕表示的项目所需的最小字符数。
combo_box.setModel(QtCore.QAbstractItemModel): 这将为这个组合框设置模型。
combo_box.setModelColumn(int): 这将为组合框模型设置可见列。
combo_box.setRootModelIndex(QtCore.QModelIndex): 这将为组合框项的参数设置根模型项作为索引。
combo_box.setSizeAdjustPolicy(QtWidgets.QComboBox.SizeAdjustPolicy): 这将为这个组合框设置大小调整策略。可用的策略如下:
-
QtWidgets.QComboBox.AdjustToContents—0: 总是调整到内容。 -
QtWidgets.QComboBox.AdjustToContentsOnFirstShow—1: 第一次显示时将调整到内容。 -
QtWidgets.QComboBox.AdjustToMinimumContentsLength—2: 将调整到最小内容长度。 -
QtWidgets.QComboBox.AdjustToMinimumContentsLengthWithIcon—3: 将调整到最小内容长度,加上图标的空白。
combo_box.setValidator(QtGui.QValidator): 这将为这个组合框设置将使用的验证器。
combo_box.setView(QtWidgets.QAbstractItemView): 这将为组合框弹出列表设置视图。
edit
这些是进行一些更改当前组合框内容的函数,包括清除、撤销和重做:
combo_box.clear(): 这将从组合框中清除弹出列表项。
combo_box.clearEditText(): 这将清除组合框编辑字段的文本。组合框的行编辑文本将被清除。
combo_box.hidePopup(): 这将隐藏组合框弹出列表;列表将被重置。
combo_box.showPopup(): 这将显示组合框弹出列表。
is/has
这些是返回与组合框状态相关的布尔值(bool)的函数,例如,检查可用性:
combo_box.hasFrame(): 如果组合框有一个周围的框架,则返回True。
combo_box.isEditable(): 如果这个组合框的行字段可以编辑,则返回True。
functional
以下是与当前组合框返回的值、功能变化等相关联的函数:
combo_box.completer(): 这返回用于此组合框文本输入自动完成的补全器。
combo_box.count(): 这计算弹出列表的项目数量并返回整数值。
combo_box.currentData(int): 这返回描述弹出列表当前数据的对象,具有 QtCore.Qt.UserRole 参数类型。
combo_box.currentIndex(): 这返回用户可能选择的弹出列表中当前项的索引(整数值)。
combo_box.currentText(): 这返回用户可能选择的弹出列表中当前项的文本(字符串)。
combo_box.duplicatesEnabled(): 如果可以在组合框中输入重复项,则返回 True。
combo_box.findData(object, int, QtCore.Qt.MatchFlags): 这返回包含指定数据(第一个参数)、角色(第二个参数)和标志(第三个参数)的项目索引。否则,它返回 -1 的值。
combo_box.findText("Text to find", QtCore.Qt.MatchFlags): 这返回包含文本(第一个参数)和标志(第二个参数)的项目索引,例如 QtCore.Qt.MatchCaseSensitive。否则,它返回 -1 的值。
combo_box.iconSize(): 这返回 QtCore.QSize 类型的图标大小。
combo_box.initStyleOption(QtWidgets.QStyleOptionFrame): 这使用参数中的值初始化样式选项。
combo_box.inputMethodQuery(QtCore.Qt.InputMethodQuery, object): 这用于查询组合框的属性集,以启用对复杂输入方法操作的支持,例如支持周围文本和重转换。
combo_box.insertItem(int, "Item text", object): 这在弹出列表的位置(第一个参数)插入带有文本(第二个参数)和用户数据(第三个参数)的项目。
combo_box.insertItem(int, QtGui.QIcon, "Item text", object): 这在弹出列表的位置(第一个参数)插入带有文本(第三个参数)的项目,该文本将使用图标(第二个参数)和用户数据(第四个参数)显示。
combo_box.insertItems(int, ["Item text"]): 这将在组合框弹出列表的位置(第一个参数)插入多个具有 Unicode 字符串类型文本的项目。可迭代对象(第二个参数)中的每个项目都将作为弹出列表的新行插入,并从给定的位置索引开始。
combo_box.insertPolicy(): 这返回在将策略插入组合框时使用的 QtWidgets.QComboBox.InsertPolicy 类型的策略。
combo_box.insertSeparator(int): 这在参数指定的位置插入这些组合框项目的分隔符。
combo_box.itemData(int, int): 这根据索引(第一个参数)和给定的角色(第二个参数)返回组合框中项的数据。
combo_box.itemDelegate(): 这返回用于弹出列表视图的 QtWidgets.QAbstractItemDelegate 类型的项目代理。
combo_box.itemIcon(int): 这返回参数中指定的索引在 combobox 内的项目 QtGui.QIcon 类型的图标。
combo_box.itemText(int): 这返回参数中指定的索引在 combobox 中的项目的文本。
combo_box.lineEdit(): 如果 combobox 可编辑,则此返回用于编辑 combobox 中项目的行编辑字段。
combo_box.maxCount(): 这返回可以与 combobox 一起使用的最大项目数。
combo_box.maxVisibleItems(): 这返回可以显示为 combobox 弹出列表的最大项目数。如果有更多元素,则可以通过滚动 combobox 屏幕使它们可见。
combo_box.minimumContentsLength(): 这返回将用 combobox 屏幕表示的最小字符数(默认 0)。
combo_box.model(): 这返回 combobox 的模型。
combo_box.modelColumn(): 这返回 combobox 模型中的可见列。
combo_box.removeItem(int): 这从 combobox 中移除由参数指定的索引的项目。
combo_box.rootModelIndex(): 这返回 combobox 项目的根模型项索引。
combo_box.sizeAdjustPolicy(): 这返回与 combobox 一起使用的 QtWidgets.QComboBox.SizeAdjustPolicy 类型的调整大小策略。
combo_box.validator(): 这返回 combobox 文本输入的验证器。
combo_box.view(): 这返回用于 combobox 的弹出列表视图。
事件
这些是与事件相关的函数,例如事件处理程序:
combo_box.changeEvent(QtCore.QEvent): 这处理 combobox 内的状态变化。
combo_box.contextMenuEvent(QtGui.QContextMenuEvent): 此事件处理程序旨在接收 combobox 的上下文菜单事件。
combo_box.event(QtCore.QEvent): 这接收对象的事件,如果事件被识别并处理,则应返回 True。
combo_box.focusOutEvent(QtGui.QFocusEvent): 此事件处理程序旨在接收在失去焦点时通过事件参数传递的 combobox 键盘焦点事件。
combo_box.focusInEvent(QtGui.QFocusEvent): 此事件处理程序旨在接收在获得焦点时通过事件参数传递的 comb box 键盘焦点事件。
combo_box.inputMethodEvent(QtGui.QInputMethodEvent): 此事件处理程序旨在接收通过事件参数传递的输入法组合事件。
combo_box.keyPressEvent(QtGui.QKeyEvent): 此事件处理程序旨在接收通过事件参数传递的 combobox 键按下事件。
combo_box.keyReleaseEvent(QtGui.QKeyEvent): 此事件处理程序旨在接收通过事件参数传递的 combobox 键释放事件。
combo_box.mousePressEvent(QtGui.QMouseEvent): 此事件处理器旨在接收带有事件参数的 combobox 的鼠标按下事件。
combo_box.mouseReleaseEvent(QtGui.QMouseEvent): 此事件处理器旨在接收带有事件参数的 combobox 的鼠标释放事件。
combo_box.paintEvent(QtGui.QPaintEvent): 此事件处理器旨在接收带有事件参数的 combobox 的绘制事件。
combo_box.resizeEvent(QtGui.QResizeEvent): 此事件处理器旨在接收和带有事件参数的 combobox 的调整大小事件。
combo_box.showEvent(QtGui.QShowEvent): 此事件处理器旨在接收带有事件参数的 combobox 的显示事件。
combo_box.wheelEvent(QtGui.QWheelEvent): 此事件处理器旨在接收带有事件参数的 combobox 的鼠标滚轮事件。
signals
QComboBox 类可用的信号如下:
combo_box.activated(int): 当在 combobox 中选择项时,会发出此信号,其中包含传递的参数中的项的索引。
combo_box.activated(str): 当在 combobox 中选择项时,会发出此信号,其中包含传递的参数中的项的文本。
combo_box.currentIndexChanged(int): 当在 combobox 中选择项并且项的当前索引发生变化时,会发出此信号,其中包含传递的参数中的索引。
combo_box.currentIndexChanged(str): 当在 combobox 中选择项时,会发出此信号,并且项的当前索引发生变化,其中包含传递的参数中的项的文本。
combo_box.currentTextChanged(str): 当在 combobox 中选择项并且项的当前文本发生变化时,会发出此信号,其中包含传递的参数中的项的文本。
combo_box.editTextChanged(str): 当可编辑行字段中的文本发生变化时,会发出此信号,其中包含传递的文本。
combo_box.highlighted(int): 当用户突出显示项时,会发出此信号,其中包含传递的参数中的项的索引。
combo_box.highlighted(str): 当用户突出显示项时,会发出此信号,其中包含传递的参数中的项的文本。
QFontComboBox
PyQt5 和 PySide2 提供了完整的 combobox,以便您可以根据文本字段中的文本(例如)选择字体家族。我们可以在应用程序中使用以下行来使用此 combobox:
combo_boxf = QtWidgets.QFontComboBox()
QFontComboBox 继承了 QComboBox 并具有以下功能。
set
这些是与设置与字体 combobox 相关的参数/属性设置相关的函数,例如设置文本、对齐方式等:
combo_boxf.setCurrentFont(QtGui.QFont): 这为此组合框设置当前字体家族。传递给参数的字体家族名称,如 Helvetica 或 Times New Roman,可以用于。
combo_boxf.setFontFilters(QtWidgets.QFontComboBox.FontFilters): 这设置将与此组合框一起使用的过滤器。可用的过滤器如下:
-
QtWidgets.QFontComboBox.AllFonts: 显示所有字体。 -
QtWidgets.QFontComboBox.ScalableFonts: 显示可缩放字体。 -
QtWidgets.QFontComboBox.NonScalableFonts: 组合框中的非可缩放字体。 -
QtWidgets.QFontComboBox.MonospacedFonts: 组合框中的等宽字体。 -
QtWidgets.QFontComboBox.ProportionalFonts: 组合框中的比例字体。
combo_boxf.setWritingSystem(QtGui.QFontDatabase.WritingSystem): 这设置作为此组合框过滤器的书写系统。
功能
这些函数返回字体组合框的当前值、功能变化等:
combo_boxf.currentFont(): 这返回由字体组合框显示/选择的QtGui.QFont类型的当前字体家族。
combo_boxf.fontFilters(): 这返回组合框的QtWidgets.QFontComboBox.FontFilters类型的过滤器。
combo_boxf.writingSystem(): 这返回组合框的书写系统。
事件
此函数与事件相关,例如事件处理程序:
combo_boxf.event(QtCore.QEvent): 这接收对象的事件,如果事件被识别并处理,则应返回True。
信号
以下是为QFontComboBox类提供的可用信号:
combo_boxf.currentFontChanged(QtGui.QFont): 当组合框的当前字体家族更改时,会发出此信号,并且当在参数中传递新字体时发生。
QComboBox 示例
让我们在应用程序中实现之前描述的组合框。我们正在创建组合框,以便可以在将可视化的不同字段之间进行选择——文本字段和表格。将QComboBox类添加到u_style.py文件中:
- 使用以下行添加
UComBox类:
...
class UComBox(QtWidgets.QComboBox):
def __init__(self, parent=None, icon=None, pad=10,
bdr=5, bdw=1, bdc=color[3]):
super(UComBox, self).__init__(parent)
self.icon, self.pad = icon, pad
self.bdr, self.bdw, self.bdc = bdr, bdw, bdc
font = UFonts(size=14, weight=59)
self.setFont(font.font1)
self.setStyleSheet(
"""QComboBox {padding: %spx; background-color: %s;
color: %s; border-style: solid; border-radius: %spx;
border-width: %spx; border-color: %s;}
QComboBox:drop-down:down-arrow { image: url(%s);
width: 14px; height: 14px;}
QComboBox:drop-down:button { margin: %spx;
background-color: %s; border-style: solid;
border-radius: %spx; border-width: %spx;
border-color: %s;}"""
% (self.pad, color[0], color[3], self.bdr, self.bdw,
self.bdc, self.icon, self.pad, color[0], self.bdr,
self.bdw, self.bdc))
...
此组合框具有可重写的样式属性。现在,我们需要将其添加到u_app.py文件中,以便我们可以在应用程序中使用它们。
- 将以下内容添加到
u_app.py文件的导入部分:
...
from u_style import UComBox
...
- 然后,将以下行添加到
u_app.py文件的__init__()函数中:
...
def __init__(self, parent=None):
...
self.combox1 = UComBox(self.frame2)
self.combox1.addItems(["Texts", "Table"])
...
self.layfr2.addWidget(self.combox1, 0, 0, 1, 1)
self.layfr2.addWidget(self.label1, 1, 0, 1, 1)
self.layfr2.addWidget(self.line_ed3, 4, 0, 1, 1)
...
...
这是将显示项目列表的组合框实例。
- 要将组合框按钮的箭头更改为图标,我们可以更改以下行,如下所示:
...
self.combox1 = UComBox(self.frame2, icon="Path/to/Icon")
...
这将添加指定路径的图标,并将默认箭头图标更改。
QListView
此类提供了一个在模型上实现的列表或图标视图。QListView用于将项目显示为简单的非层次列表。借助列表视图,组合框弹出列表可以以另一种方式表示。QListView的继承方案如下:

以下是在应用程序中此类的声明语句:
list_view = QtWidgets.QListView()
QListView 类的函数
QListView 类通过以下函数提高功能。
set
这些是与设置与列表视图相关的参数/属性相关的函数。
list_view.setBatchSize(int): 如果布局模式设置为 Batched,则此方法设置每个批次的项数。
list_view.setFlow(QtWidgets.QListView.Flow): 这将设置与列表视图一起使用的内容的流动方式。可用的流动方式如下:
-
QtWidgets.QListView.LeftToRight—0: 项目将从左到右进行布局。 -
QtWidgets.QListView.TopToBottom—1: 项目将从上到下进行布局。
list_view.setGridSize(QtCore.QSize): 这将设置布局网格的大小。
list_view.setLayoutMode(QtWidgets.QListView.LayoutMode): 这将设置此列表视图的布局模式。可用的模式如下:
-
QtWidgets.QListView.SinglePass—0: 所有项目将同时布局。 -
QtWidgets.QListView.Batched—1: 项目将分批布局。
list_view.setModelColumn(int): 这将设置参数指定的模型中的列,该列将可见。
list_view.setMovement(QtWidgets.QListView.Movement): 这将设置此列表视图中项目的移动方式。可用的移动方式如下:
-
QtWidgets.QListView.Static—0: 项目不能被移动。 -
QtWidgets.QListView.Free—1: 项目可以被移动。 -
QtWidgets.QListView.Snap—2: 当项目被吸附到指定的网格时,项目将被移动。
list_view.setPositionForIndex(QtCore.QPoint, QtCore.QModelIndex): 这将设置模型中索引(第二个参数)指定的项目的位置,相对于第一个参数指定的位置。
list_view.setResizeMode(QtWidgets.QListView.ResizeMode): 这将设置列表视图模型的调整大小模式。可用的调整大小方式如下:
-
QtWidgets.QListView.Fixed—0: 项目将在列表视图显示时首次布局。 -
QtWidgets.QListView.Adjust—1: 每次列表视图大小调整时,项目都将进行布局。
list_view.setRowHidden(int, bool): 如果第二个参数设置为 True,则将行(第一个参数)设置为隐藏。
list_view.setSelectionRectVisible(bool): 如果参数为 True,则将选择矩形设置为可见。
list_view.setSpacing(int): 这将设置布局中表示的项目的所有边框的空间。
list_view.setUniformItemSizes(bool): 如果参数为 True,则列表视图中的所有项目都应具有相同的大小。
list_view.setViewMode(QtWidgets.QListView.ViewMode): 这将设置此列表视图的视图模式。可用的视图模式如下:
-
QtWidgets.QListView.ListMode—0: 项目将使用静态移动、TopToBottom流和较小的尺寸进行布局。 -
QtWidgets.QListView.IconMode—1: 项将使用自由移动、LeftToRight流和较大大小进行布局。
list_view.setWordWrap(bool): 如果参数为 True,则项文本将在单词断点处换行。
list_view.setWrapping(bool): 如果参数为 True,则当可见区域的空间不足时,项布局将自动换行。
is/has
这些是返回与列表视图状态相关的布尔值 (bool) 的函数,例如,用于检查可见性:
-
list_view.isRowHidden(int): 如果参数中指定的行在列表视图中被隐藏,则此函数返回True;否则,它返回False。 -
list_view.isSelectionRectVisible(): 如果选择矩形可见,则此函数返回True;否则,选择矩形被隐藏。 -
list_view.isWrapping(): 如果布局将在可见区域的空间不足时自动换行,则此函数返回True。
functional
这些是与当前列表视图的返回值相关的函数:
list_view.batchSize(): 如果布局模式设置为 Batched,则此函数返回每个批次的项数。
list_view.clearPropertyFlags(): 这清除列表视图中的属性标志。
list_view.flow(): 这返回与 QtWidgets.QListView.Flow 类型的列表视图一起使用的内容的流动。
list_view.gridSize(): 这返回与 QtCore.QSize 类型的列表视图一起使用的布局网格的大小。
list_view.layoutMode(): 这返回了 QtWidgets.QListView.LayoutMode 类型的布局模式。
list_view.modelColumn(): 这返回模型中可见的列数。
list_view.movement(): 这返回 QtWidgets.QListView.Movement 类型的移动,描述了项是否可以移动、吸附到网格或不能移动。
list_view.rectForIndex(QtCore.QModelIndex): 此函数返回模型中指定位置索引的项的 QtCore.QRect 类型的矩形,如参数中指定。
list_view.resizeMode(): 这返回了 QtWidgets.QListView.ResizeMode 类型的调整大小模式,或当列表视图调整大小时项的布局方式。
list_view.spacing(): 这返回布局中所有项周围的空间。
list_view.uniformItemSizes(): 如果在此列表视图中所有项的大小都相同,则此函数返回 True。
list_view.viewMode(): 这返回此列表视图的 QtWidgets.QListView.ViewMode 类型的视图模式。
list_view.wordWrap(): 如果项文本在单词断点处换行,则此函数返回 True。
events
这些是与事件相关的函数,例如事件处理器:
list_view.dragLeaveEvent(QtGui.QDragLeaveEvent): 当鼠标离开列表视图且正在执行拖动操作时,此事件处理器会使用事件参数被调用。
list_view.dragMoveEvent(QtGui.QDragMoveEvent): 当发生条件时,例如光标进入或移动到视图内,键盘上的修改键在列表视图有焦点时被点击,或者如果有一个拖动操作正在进行,这个事件处理程序会使用事件参数被调用。
list_view.dropEvent(QtGui.QDropEvent): 当拖动操作在列表视图上放下时,这个事件处理程序会使用事件参数被调用。
list_view.event(QtCore.QEvent): 这个接收对象的事件,如果事件被识别并处理,则应返回True。
list_view.mouseMoveEvent(QtGui.QMouseEvent): 这个事件处理程序接收列表视图的鼠标移动事件,以及传递给参数的鼠标事件。
list_view.mouseReleaseEvent(QtGui.QMouseEvent): 这个事件处理程序接收列表视图的鼠标释放事件,以及传递给参数的鼠标事件。
list_view.paintEvent(QtGui.QPaintEvent): 这个事件处理程序接收列表视图的绘制事件,以及传递给参数的绘制事件。
list_view.resizeEvent(QtGui.QResizeEvent): 这个事件处理程序接收列表视图的调整大小事件,以及传递给参数的调整大小事件。
list_view.timerEvent(QtCore.QTimerEvent): 这个事件处理程序接收列表视图的计时器事件,以及传递给参数的计时器事件。
list_view.wheelEvent(QtGui.QWheelEvent): 这个事件处理程序接收列表视图的鼠标滚轮事件,以及传递给参数的滚轮事件。
信号
QListView类可用的信号如下:
list_view.indexesMoved(QtCore.QModelIndexList): 当参数中指定的索引在视图中移动时,会发出这个信号。
QListView 示例
现在,我们将在 PySide2 和 PyQt5 应用程序的u_style.py文件中创建UListV类。这个类将展示如何使用我们之前创建的组合框与列表视图:
- 将
UListV类添加到u_style.py文件中:
...
class UListV(QtWidgets.QListView):
def __init__(self, parent=None, mg=5, pad=10,
bdr=5, bdw=1, bdc=color[3]):
super(UListV, self).__init__(parent)
self.setWordWrap(True)
self.mg, self.pad = mg, pad
self.bdr, self.bdw, self.bdc = bdr, bdw, bdc
font = UFonts(size=14, weight=59)
self.setFont(font.font1)
self.setStyleSheet(
"""margin: %spx; padding: %spx; background-color: %s;
color: %s; border-style: solid; border-radius: %spx;
border-width: %spx; border-color: %s;"""
% (self.mg, self.pad, color[0], color[3],
self.bdr, self.bdw, self.bdc))
...
这个列表视图将在组合框中用于显示弹出窗口。为了在应用程序中将这个列表视图与组合框实现,我们需要在u_app.py文件中添加一些行。
- 在
u_app.py文件的导入部分添加UListV类,与UCombo类保持一致:
...
from u_style import UComBox, UListV
...
- 此外,修改组合框的行,如下:
...
def __init__(self, parent=None):
...
self.combox1.addItems(["Texts", "Table"])
self.combox1.setView(UListV())
...
...
这设置了组合框元素的列表视图。通过这样做,我们可以为组合框弹出列表设置样式并添加功能。
QTableView
让我们描述在 GUI 应用程序中的表格实现。QTableView 类提供了以表格形式表示数据。根据 Qt 框架的范式,此类(包括列表视图)提供了表格视图的默认模型-视图实现。要填充表格中的数据,您需要使用 QtCore 模块中的 QAbstractTableModel 类等模型。QTableView 类具有以下继承方案:

在应用程序中此类的声明如下:
table_view = QtWidgets.QTableView()
QTableView 函数
QTableView 类通过以下函数增强了功能。
设置
这些是与设置与表格视图相关的参数/属性相关的函数:
table_view.setColumnHidden(int, bool): 如果第二个参数为 True,则将参数指定的列设置为隐藏。
table_view.setColumnWidth(int, int): 这将设置第一个参数指定的列的宽度(第二个参数)。
table_view.setCornerButtonEnabled(bool): 如果参数为 True,则将此表左上角的按钮设置为选择整个表。
table_view.setGridStyle(QtCore.Qt.PenStyle): 这将设置用于绘制此表网格的笔风格。可用的样式如下:
-
QtCore.Qt.NoPen—0: 无笔。 -
QtCore.Qt.SolidLine—1: 实线。 -
QtCore.Qt.DashLine—2: 虚线。 -
QtCore.Qt.DotLine—3: 点划线。 -
QtCore.Qt.DashDotLine—4: 虚线点划线。 -
QtCore.Qt.DashDotDotLine—5: 虚线双点划线。 -
QtCore.Qt.CustomDashLine—6: 自定义虚线,通过使用QtGui.QPainterPathStroker自定义图案定义。
table_view.setHorizontalHeader(QtWidgets.QHeaderView): 这将设置参数中指定的用作水平表头的表头。
table_view.setModel(QtCore.QAbstractItemModel): 这将设置用于表视图的数据模型。
table_view.setRowHeight(int, int): 这将设置第一个参数指定的行的宽度(第二个参数)。
table_view.setRowHidden(int, bool): 如果第二个参数为 True,则将行(第一个参数)设置为隐藏。
table_view.setShowGrid(bool): 如果参数为 True,则将使用此表显示网格。
table_view.setSortingEnabled(bool): 如果参数为 True,则将表格的排序设置为启用。
table_view.setSpan(int, int, int, int): 这将设置行(第一个参数)和列(第二个参数)中元素的跨距为行数(第三个参数)和列数(第四个参数)。
table_view.setVerticalHeader(QtWidgets.QHeaderView): 这将设置参数中指定的用作垂直表头的表头。
table_view.setWordWrap(bool): 如果参数为True,则为此项的文本设置自动换行策略。
is
这些是返回与表格视图状态相关的布尔值(bool)的函数,例如,用于检查可见性:
table_view.isColumnHidden(int): 如果参数中指定的列被隐藏,则返回True。
table_view.isCornerButtonEnabled(): 如果表格视图左上角显示的按钮被启用,则返回True。
table_view.isRowHidden(int): 如果参数中指定的行被隐藏,则返回True。
table_view.isSortingEnabled(): 如果此表格启用了排序,则返回True。
functional
这些是返回当前表格视图值、功能变化等的函数:
table_view.clearSpans(): 这从表格视图中移除所有行/列跨度。
table_view.columnAt(int): 这返回在内容坐标中通过参数指定的 y 坐标定位的列。
table_view.columnCountChanged(int, int): 当列被添加或删除时调用此槽。之前的列数作为第一个参数指定,而新的列数作为第二个参数指定。
table_view.columnMoved(int, int, int): 这是当指定为第一个参数的列的索引改变时被调用的槽。之前的索引作为第二个参数指定,而新的索引作为第三个参数指定。
table_view.columnResized(int, int, int): 这是当指定为第一个参数的列的宽度改变时被调用的槽。之前的宽度作为第二个参数指定,而新的宽度作为第三个参数指定。
table_view.columnSpan(int, int): 这返回在指定的行(第一个参数)和列(第二个参数)中表格中元素的列跨度。
table_view.columnViewportPosition(int): 这返回参数中指定的列在内容坐标中的 x 坐标。
table_view.columnWidth(int): 这返回参数中指定的列的宽度。
table_view.gridStyle(): 这返回表格网格的QtCore.Qt.PenStyle类型的样式。
table_view.hideColumn(int): 这隐藏参数中指定的表格列。
table_view.hideRow(int): 这将隐藏参数中指定的行。
table_view.horizontalHeader(): 这返回表格视图的QtWidgets.QHeaderView类型的水平表头。
table_view.resizeColumnsToContents(): 这将所有列的大小调整为基于用于列中每个项目的代理的大小提示。
table_view.resizeColumnToContents(int): 这将参数中指定的列的大小调整为基于用于列中每个项目的代理的大小提示。
table_view.resizeRowsToContents(): 这将所有行的大小调整为基于用于每行中每个项目的代理的大小提示。
table_view.resizeRowToContents(int): 这将参数指定的行的大小调整为基于该行中每个项目的代理的大小提示。
table_view.rowAt(int): 这返回在内容坐标中通过参数指定的 y 坐标定位的行。
table_view.rowCountChanged(int, int): 当添加或删除列时调用此槽,即上一个行数(第一个参数)和新的行数(第二个参数)。
table_view.rowHeight(int): 这返回参数指定的行的长度。
table_view.rowMoved(int, int, int): 这是调用以更改第一个参数指定的行索引的槽。上一个索引由第二个参数指定,而新索引由第三个参数指定。
table_view.rowResized(int, int, int): 这是调用以更改第一个参数指定的行宽度的槽。上一个宽度由第二个参数指定,而新宽度由第三个参数指定。
table_view.rowSpan(int, int): 这返回在指定的行(第一个参数)和列(第二个参数)中的表格元素的水平跨行数。
table_view.rowViewportPosition(int): 这返回参数指定的行在内容坐标中的 y 坐标。
table_view.selectColumn(int): 这将选择由该表格视图参数指定的列。
table_view.selectRow(int): 这将选择由该表格视图参数指定的行。
table_view.showColumn(int): 这将显示参数指定的列。
table_view.showGrid(): 如果表格以网格模式显示,则返回 True。
table_view.showRow(int): 这将显示由参数指定的行。
table_view.sortByColumn(int, QtCore.Qt.SortOrder): 这将根据第一个参数指定的列按顺序(第二个参数)对模型进行排序。
table_view.verticalHeader(): 这返回用于此表格视图的 QtWidgets.QHeaderView 类型的垂直标题。
table_view.wordWrap(): 如果启用了项目文本的自动换行策略,则返回 True。
事件
这是一个与事件处理程序、等等相关联的函数:
table_view.paintEvent(QtGui.QPaintEvent): 此事件处理程序接收传递给参数的 paint 事件,用于此表格视图。
QTableView 示例
要在应用程序中演示表格,我们需要为表格创建数据模型和视图。首先,让我们使用来自 QtCore 模块的 QAbstractTableModel 类来创建模型。在 App/App_PyQt5/ 和 App/App_PySide2/ 目录中创建名为 u_table.py 的文件,并在其中包含以下行:
- 在 PyQt5 的情况下,将以下内容添加到
u_table.py文件的导入部分:
...
from PyQt5 import QtCore
import random
...
- 在 PySide2 的情况下,将以下内容添加到
u_table.py文件的导入部分:
...
from PySide2 import QtCore
import random
...
- 然后,将
UTModel类添加到u_table.py文件中:
...
class UTModel(QtCore.QAbstractTableModel):
def __init__(self, parent=None):
super(UTModel, self).__init__(parent)
def rowCount(self, parent):
return 27
def columnCount(self, parent):
return 14
def data(self, row, column):
randn = random.randint(1, 100)
return randn
...
这些方法在抽象类中是必需的。它们描述了表格中的总行数和列数,以及每个单元格的数据。现在,我们需要使用 u_style.py 文件为这个表格添加一些样式。
- 在
u_style.py文件中创建一个名为UTabView的类:
...
class UTabView(QtWidgets.QTableView):
def __init__(self, parent=None, tvpad=7, tvbgcolor=color[1],
tvtxc=color[3], bdr=5, bdw=1, bdc=color[3]):
super(UTabView, self).__init__(parent)
self.tvpad = tvpad
self.tvbgcolor, self.tvtxc = tvbgcolor, tvtxc
self.bdr, self.bdw, self.bdc = bdr, bdw, bdc
font = UFonts(size=14, weight=59)
self.setFont(font.font1)
self.setStyleSheet(
"""QTableView {padding: %spx; background-color: %s;
color: %s; border-style: solid;
border-radius: %spx; border-width: %spx;
border-color: %s; gridline-color: %s;}"""
% (self.tvpad, self.tvbgcolor, self.tvtxc,
self.bdr, self.bdw, self.bdc, color[3]))
...
这个表格视图将用于使用自定义属性来样式化表格,并允许我们在需要时重新实现它们。
现在,向 u_app.py 文件中添加一些行:
- 在
u_app.py文件的导入部分添加UTabView类,如下所示:
...
from u_style import UComBox, UListV, UTabView
from u_table import UTModel
...
- 然后,在
UApp类的__init__()函数内部,添加表格并设置模型。最后,添加组合框的信号和将调用的函数:
...
def __init__(self, parent=None):
...
self.table = UTabView(self.frame1)
self.table.setVisible(False)
model = UTModel()
self.table.setModel(model)
self.layfr1 = QtWidgets.QGridLayout()
self.layfr1.addWidget(self.table, 0, 0, 1, 1)
self.layfr1.addWidget(self.text_edit, 0, 0, 1, 1)
...
self.combox1.activated.connect(self.txt_table)
def txt_table(self):
if self.combox1.currentText() == "Texts":
self.text_edit.setVisible(True)
self.table.setVisible(False)
if self.combox1.currentText() == "Table":
self.text_edit.setVisible(False)
self.table.setVisible(True)
...
我们使用表格视图来表示应用程序中的表格,并使用模型来表示表格中的数据(遵循模型-视图范式)。因此,如果组合框中选择了表格,表格将如下所示:

这个表格的每个单元格都使用随机数作为值。
摘要
在本章中,我们描述了 Qt 框架的基本范式,即模型-视图。从广义上讲,MVC 架构为我们提供了使用数据和以灵活形式表示数据的机会;换句话说,将模型与数据模型的数据视图分开。这样,几乎任何类型的数据都可以用 GUI 应用程序实现。在开发过程中,一些功能,如树视图和列表视图,没有展示,但可以在广泛的软件开发领域中与文档结合使用。在接下来的章节中,将详细介绍具有数据的模型。
下一章将描述使用 Python 绑定创建 GUI 应用程序时使用的不同类型按钮的基本结构。
第八章:实现按钮
在本章中,我们将描述 GUI 应用程序的主要控制元素——按钮。按钮是任何 GUI 应用程序中最常用的图形组件。不同的按钮类型为用户提供根据其定义的功能操作应用程序的选项。用户可以点击按钮来启动一个过程并选择可用的选项,或者打开文件对话框窗口。所有这些操作都需要一个实现这些操作的元素。Qt 框架以及相应的 Python 绑定(PySide2 和 PyQt5)提供了用于创建各种任务按钮的广泛类。这些元素非常可定制,允许软件开发者以现代风格实现这些组件。
本章将涵盖以下元素:
-
按钮
-
复选框
-
其他组件
QAbstractButton
这是一个用于按钮小部件的抽象基类,它提供了与 Qt 框架中按钮相关的功能。本章中描述的按钮将继承这个类。
QAbstractButton 函数
QAbstractButton 继承自 QWidget 并通过以下函数增强了功能。
设置
这些是与按钮参数/属性设置相关的函数,包括设置文本、对齐或功能:
setAutoExclusive(bool): 如果参数为 True,则启用按钮的自动排他性。这意味着该按钮是具有相同父组的排他按钮组的一部分。在排他按钮组中,一次只能选中一个按钮,如果之前选中了某个按钮,它将自动取消选中。
setAutoRepeat(bool): 如果参数为 True,则在按钮被按下时启用自动重复。这与移动滑块等按钮相关。
setAutoRepeatDelay(int): 这设置了按钮自动重复的延迟,或者当重复开始后经过参数中指定的毫秒数。
setAutoRepeatInterval(int): 这设置了按钮自动重复的间隔,或者重复发生的间隔,以参数中指定的毫秒数表示。
setChecked(bool): 如果参数为 True,则将按钮设置为选中状态。此按钮需要能够被选中。
setDown(bool): 如果参数为 True,则将按钮设置为按下状态。
setIcon(QtGui.QIcon): 这指定了按钮将使用的图标。
setIconSize(QtCore.QSize): 这设置了按钮图标的尺寸。
setShortcut(QtGui.QKeySequence): 这设置了将与该按钮关联的助记符,或用于执行动作的键盘快捷键。
setText("Okay"): 这设置了按钮的文本。
是
这些是返回与按钮状态相关的布尔值(bool)的函数:
isCheckable(): 此函数返回True,如果按钮可选中。
isChecked(): 此函数返回True,如果按钮被选中且可选中。
isDown(): 此函数返回True,如果按钮处于按下状态。
functional
这些是与按钮当前值、功能变化等相关联的函数:
animateClick(int): 此函数执行按钮的动画点击。
autoExclusive(): 此函数返回True,如果此按钮启用了自动排他性。
autoRepeat(): 此函数返回True,如果此按钮启用了自动重复功能。
autoRepeatDelay(): 此函数返回与按钮自动重复功能相关的延迟。
autoRepeatInterval(): 此函数返回与按钮自动重复功能相关的间隔。
click(): 此函数执行按钮的点击操作。与此按钮点击相关的所有信号都会被发射。
group(): 此函数返回按钮所属的组。
hitButton(QtCore.QPoint): 如果参数指定的位置在按钮矩形内,则此函数返回True;否则返回False。
icon(): 此函数返回此按钮包含的图标,类型为QtGui.QIcon。
iconSize(): 此函数返回此按钮包含的图标大小,类型为QtCore.QSize。
shortcut(): 此函数返回与此按钮一起使用的键盘快捷键。
text(): 此函数返回此按钮上显示的文本。
events
这些是与事件相关的函数,例如事件处理程序:
changeEvent(QtCore.QEvent): 此函数处理与按钮相关的状态变化。
checkStateSet(): 当使用QAbstractButton.setChecked()时,此为虚拟处理程序被调用。
event(QtCore.QEvent): 这是QtCore.QObject函数,用于接收对象的事件,如果事件被识别并处理,则应返回True。
focusOutEvent(QtGui.QFocusEvent): 这是一个事件处理程序,旨在接收当失去焦点时,带有焦点事件参数的按钮的键盘焦点事件。
focusInEvent(QtGui.QFocusEvent): 这是一个事件处理程序,旨在接收当接收到焦点时,带有焦点事件参数的按钮的键盘焦点事件。
keyPressEvent(QtGui.QKeyEvent): 这是一个事件处理程序,旨在接收按钮的按键事件,以及通过参数传递的按键事件。
keyReleaseEvent(QtGui.QKeyEvent): 这是一个事件处理程序,旨在接收按钮的按键释放事件,以及通过参数传递的按键事件。
mousePressEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收此按钮的鼠标按下事件,以及通过参数传递的鼠标事件。
mouseReleaseEvent(QtGui.QMouseEvent): 这是一个事件处理程序,用于接收按钮的鼠标释放事件,以及通过参数传入的鼠标事件。
nextCheckState(): 当按钮被点击时,会调用此虚拟处理程序。
paintEvent(QtGui.QPaintEvent): 这是一个事件处理程序,用于接收此按钮的绘制事件,以及通过参数传入的绘制事件。
timerEvent(QtCore.QTimerEvent): 这是一个事件处理程序,用于接收按钮的计时器事件,以及通过参数传入的计时器事件。
信号
QAbstractButton 类可用的信号如下:
clicked(bool): 当按钮被激活、按下快捷键或调用 click() 或 animateClick() 函数时,会发出此信号。如果按钮可勾选,参数为 True 表示已勾选,为 False 表示未勾选。
pressed(): 当按钮被按下时,会发出此信号。
released(): 当按钮被释放时,会发出此信号。
toggled(bool): 当按钮状态改变时,会发出此信号。如果按钮可勾选,参数为 True 表示已勾选,为 False 表示未勾选。
QPushButton
应用程序中最常用的图形组件是按钮。用户可以点击按钮执行操作或通过使用他们喜欢的应用程序达到某种效果。Qt 框架提供了 QPushButton 类来实现应用程序中的标准按钮,并且可以与 PySide 和 PyQt Python 绑定一起使用。丰富的自定义选项使此元素具有现代风格,可以在各种形式中用于任何地方。应用程序中按钮的声明语法如下:
push_button = QtWidgets.QPushButton()
QPushButton 函数
QPushButton 继承自 QAbstractButton 类,并通过以下函数增强了功能。
设置
这些是与设置与按钮相关的参数/属性设置相关的函数:
push_button.setAutoDefault(bool): 如果参数为 True,则将此按钮设置为自动默认按钮。
push_button.setDefault(bool): 如果参数为 True,则将此按钮设置为默认按钮。
push_button.setFlat(bool): 如果参数为 True,则将此按钮设置为平面。
push_button.setMenu(QtWidgets.QMenu): 这将设置与按钮相关的参数指定的弹出菜单。
是
这些是与当前按钮状态的布尔值 (bool) 相关的函数:
push_button.isDefault(): 如果此按钮是默认按钮,则返回 True。
push_button.isFlat(): 如果此按钮是平面的,则返回 True。
功能性
这些是与当前按钮的当前值、功能变化等相关的函数:
push_button.autoDefault(): 如果该按钮是自动默认按钮,则返回 True。
push_button.menu(): 这返回与该按钮关联的 QtWidgets.QMenu 类型的弹出菜单。
push_button.showMenu(): 这显示与该按钮关联的弹出菜单。
事件
这些是与事件相关的函数,例如事件处理程序:
push_button.changeEvent(QtCore.QEvent): 这处理按钮内的状态变化。
push_button.enterEvent(QtCore.QEvent): 这是一个事件处理程序,旨在接收传递带有事件参数的按钮进入事件,并在鼠标光标进入按钮时发送。
push_button.event(QtCore.QEvent): 这接收对象的事件,如果事件被识别并处理,则应返回 True。
push_button.focusOutEvent(QtGui.QFocusEvent): 这是一个事件处理程序,旨在接收此按钮的键盘焦点事件,并在失去焦点时通过事件参数传递。
push_button.focusInEvent(QtGui.QFocusEvent): 这是一个事件处理程序,旨在接收此按钮的键盘焦点事件,并在获得焦点时通过事件参数传递。
push_button.keyPressEvent(QtGui.QKeyEvent): 这是一个事件处理程序,旨在接收此按钮的按键事件,事件通过参数传递。
push_button.keyReleaseEvent(QtGui.QKeyEvent): 这是一个事件处理程序,旨在接收此按钮的按键释放事件,事件通过参数传递。
push_button.leaveEvent(QEvent): 这是一个事件处理程序,旨在接收此按钮的离开事件,事件通过参数传递。
push_button.mousePressEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收此按钮的鼠标按下事件,事件通过参数传递。
push_button.mouseReleaseEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收此按钮的鼠标释放事件,事件通过参数传递。
push_button.paintEvent(QtGui.QPaintEvent): 这是一个事件处理程序,旨在接收此按钮的绘制事件,事件通过参数传递。
push_button.timerEvent(QtCore.QTimerEvent): 这是一个事件处理程序,旨在接收此按钮的定时事件,事件通过参数传递。
QToolButton
QToolButton 类构建应用程序中的快速访问工具按钮,用于通常在工具栏中定义的命令或选项。此类按钮的声明语法如下:
tool_button = QtWidgets.QToolButton()
QToolButton 函数
QToolButton 类从 QAbstractButton 类继承,并通过以下函数改进了功能。
设置
这些是与设置工具按钮相关参数/属性的函数:
tool_button.setArrowType(QtCore.Qt.ArrowType): 这将为该工具按钮设置箭头类型,箭头将显示而不是正常图标。
tool_button.setAutoRaise(bool): 如果参数为 True,则为此工具按钮启用自动提升功能。
tool_button.setDefaultAction(QtWidgets.QAction): 这将为该工具按钮设置参数中指定的默认操作。
tool_button.setMenu(QtWidgets.QMenu): 这将指定与该工具按钮关联的菜单。菜单将根据弹出模式显示。
tool_button.setPopupMode(QtWidgets.QToolButton.ToolButtonPopupMode): 这将为此工具按钮设置弹出模式。可用的弹出模式如下:
-
QtWidgets.QToolButton.DelayedPopup—0: 菜单将延迟显示 -
QtWidgets.QToolButton.MenuButtonPopup—1: 菜单将带有特殊箭头显示 -
QtWidgets.QToolButton.InstantPopup—2: 菜单将无延迟显示,且不会触发操作
tool_button.setToolButtonStyle(QtCore.Qt.ToolButtonStyle): 这将为该工具按钮设置参数中指定的样式。
功能性
这些是与工具按钮当前值返回、功能变化等相关联的函数:
tool_button.arrowType(): 这将返回与该工具按钮一起使用的 QtCore.Qt.ArrowType 类型的箭头。
tool_button.autoRaise(): 如果为该工具按钮启用了自动提升功能,则返回 True。
tool_button.defaultAction(): 这将返回与该工具按钮一起使用的 QtWidgets.QAction 类型的默认操作。
tool_button.menu(): 这将返回与该工具按钮关联的菜单。
tool_button.popupMode(): 这将返回与该工具按钮弹出菜单一起使用的 QtWidgets.QToolButton.ToolButtonPopupMode 类型的模式。
tool_button.showMenu(): 这将显示与该工具按钮关联的弹出菜单。
tool_button.toolButtonStyle(): 这将返回与该工具按钮一起使用的 QtCore.Qt.ToolButtonStyle 类型的样式。
事件
这些是与事件相关的函数,例如事件处理器:
tool_button.actionEvent(QtGui.QActionEvent): 当与该工具按钮相关的操作发生变化时,将调用此事件处理器,事件通过参数传递。
tool_button.changeEvent(QtCore.QEvent): 这处理与该工具按钮相关的状态变化。
tool_button.enterEvent(QtCore.QEvent): 这是一个事件处理器,旨在接收该工具按钮的进入事件,这些事件通过事件参数传递,并在鼠标光标进入工具按钮时发送。
tool_button.event(QtCore.QEvent): 这将接收对象的事件,如果事件被识别并处理,则应返回 True。
tool_button.leaveEvent(QEvent): 这是一个事件处理程序,旨在接收此工具按钮的离开事件,事件通过参数传递。
tool_button.mousePressEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收此工具按钮的鼠标按下事件,鼠标事件通过参数传递。
tool_button.mouseReleaseEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收此工具按钮的鼠标释放事件,鼠标事件通过参数传递。
tool_button.nextCheckState(): 当工具按钮被点击时,会调用虚拟处理程序。
tool_button.paintEvent(QtGui.QPaintEvent): 这是一个事件处理程序,旨在接收此工具按钮的绘制事件,绘制事件通过参数传递。
tool_button.timerEvent(QtCore.QTimerEvent): 这是一个事件处理程序,旨在接收此工具按钮的计时器事件,计时器事件通过参数传递。
信号
QToolButton 类的可用信号如下:
tool_button.triggered(QtWidgets.QAction): 当传递给参数的动作被触发时,会发出此信号。
QRadioButton
应用程序中可以实现另一种类型的按钮,称为无线电按钮。此组件是选项按钮,因为用户可以在不同选项之间进行选择。一次只能检查包含无线电按钮的组中的单个无线电按钮。如果用户选择了无线电按钮,则此组内的其他无线电按钮将被取消选中。QRadioButton 类从 QAbstractButton 类继承,并提供了那里表示的功能、信号和事件。无线电按钮还可以显示文本和图标。在应用程序中无线电按钮的声明语法如下:
radio_button = QtWidgets.QRadioButton("Choice #1")
此按钮的图标可以使用如下方式使用:
radio_button.setIcon(QtGui.QIcon("Path/To/The/icon.png"))
在文本的情况下,我们有以下内容:
radio_button.setText("Choice #1")
无线电按钮可以像使用 setStyleSheet() 函数的每个小部件一样进行样式化。
QButtonGroup
此类实现了按钮组的容器。带有按钮的容器对于创建具有多个选项的无线电按钮或复选框以传达信息的复杂性非常有用。此类提供了一个抽象容器,不提供视觉表示。按钮组管理组中每个按钮的状态。在应用程序中按钮组的声明语法如下:
button_group = QtWidgets.QButtonGroup()
QButtonGroup 函数
QButtonGroup 类从 QObject 类继承,并通过以下函数改进了功能。
添加
以下函数与向按钮组添加元素相关:
button_group.addButton(QtWidgets.QAbstractButton, int): 此函数将第一个参数指定的按钮添加到此按钮组,并使用第二个参数指定的 ID。如果 ID 是 1(默认值),则 ID 将分配给添加的按钮。
设置
这些是与设置按钮组相关参数/属性的函数:
button_group.setExclusive(bool): 如果参数为 True,则将此按钮组设置为排他性。在这种情况下,这个组中任何时候只能选中一个按钮。
button_group.setId(QtWidgets.QAbstractButton, int): 将第二个参数指定的 ID 设置为第一个参数中指定的按钮。
功能
这些是与按钮组当前值返回、功能变化等相关的函数:
button_group.button(int): 返回参数中指定 ID 的按钮。
button_group.buttons(): 返回此按钮组中的按钮列表。
button_group.checkedButton(): 返回此按钮组中选中的按钮,如果没有选中按钮则返回 0。
button_group.checkedId(): 返回此按钮组中选中按钮的 ID,如果没有选中按钮则返回 -1。
button_group.exclusive(): 如果按钮组是排他的,则返回 True。这意味着在这个组中任何时候只能选中一个按钮。
button_group.id(QtWidgets.QAbstractButton): 返回参数中指定按钮的 ID。
button_group.removeButton(QtWidgets.QAbstractButton): 从此按钮组中移除参数中指定的按钮。
信号
QButtonGroup 类可用的信号如下:
button_group.buttonClicked(QtWidgets.QAbstractButton): 当参数中指定的按钮被点击时,会发出此信号。
button_group.buttonClicked(int): 当参数中指定的按钮被点击时,会发出此信号。
button_group.buttonPressed(QtWidgets.QAbstractButton): 当参数中指定的按钮被按下时,会发出此信号。
button_group.buttonPressed(int): 当参数中指定的按钮被按下时,会发出此信号。
button_group.buttonReleased(QtWidgets.QAbstractButton): 当参数中指定的按钮被释放时,会发出此信号。
button_group.buttonReleased(int): 当参数中指定的按钮被释放时,会发出此信号。
button_group.buttonToggled(QtWidgets.QAbstractButton, bool): 当第一个参数指定的按钮被切换时,会发出此信号。如果按钮被选中,第二个参数为 True,如果没有选中,则为 False。
button_group.buttonToggled(int, bool): 当第一个参数指定的按钮被切换时,会发出此信号。如果按钮被选中,第二个参数为 True,如果没有选中,则为 False。
按钮示例
现在,让我们尝试创建一个用于应用程序的按钮。本书后面将根据需要实现其他类型的按钮。作为一个例子,让我们创建一个按钮:
- 首先,在两个
u_style.py文件中构建UBut1类:
...
class UBut1(QtWidgets.QPushButton):
def __init__(self, parent=None,
bg="rgba(9,219,190,140)",
bgh="rgba(9,219,190,255)",
txc="rgba(1,255,255,190)",
txch="rgba(1,255,255,255)",
minw=0, minh=0, maxw=None,
maxh=None, fixw=None, fixh=None,
mrg=0, pad=7, bds="solid",
bdr=3, bdw=0, bdc=color[3], checks=False):
super(UBut1, self).__init__(parent)
self.setFlat(True)
self.setMouseTracking(True)
self.setMinimumWidth(minw)
self.setMinimumHeight(minh)
if maxw is not None:
self.setMaximumWidth(maxw)
if maxh is not None:
self.setMaximumHeight(maxh)
if fixw is not None:
self.setFixedWidth(fixw)
if fixh is not None:
self.setFixedHeight(fixh)
self.checks = checks
self.setCheckable(self.checks)
self.bg, self.bgh, self.txc, self.txch = bg, bgh, txc, txch
self.mrg, self.pad = mrg, pad
self.bds, self.bdr, self.bdw, self.bdc = bds, bdr, bdw, bdc
self.setStyleSheet(self.but_style(self.mrg, self.pad, self.bg,
self.txc, self.bds, self.bdr, self.bdw, self.bgh))
...
...
我们已经向UBut1类的__init__()函数添加了各种参数。最大宽度和高度可以根据 GUI 中按钮的外观进行调整。
- 将用于样式化此按钮的
but_style()函数添加到UBut1类中:
...
...
def but_style(self, mrg=None, pad=None, bg=None,
txc=None, bds=None, bdr=None,
bdw=None, bdc=None):
style = """margin: %spx; padding: %spx;
background-color: %s; color: %s;
border-style: %s; border-radius: %spx;
border-width: %spx; border-color: %s;"""
% (mrg, pad, bg, txc, bds, bdr, bdw, bdc)
return style
...
...
此函数将用于避免代码重复,并在事件发生时样式化此按钮。添加将用于事件发生的函数;在第一个实例中,我们将添加处理按钮调整大小事件的函数,或者当按钮根据窗口大小调整大小时,更改此按钮文本的字体。
- 这里是处理调整大小事件的函数:
...
...
def resizeEvent(self, event):
self.fonts = UFonts(
size=int(
(self.width() + self.height())/self.pad),
weight=100)
self.setFont(self.fonts.font1)
...
...
此函数处理通过参数传递的event参数的调整大小事件。它根据按钮的大小更改按钮的字体。
- 添加
enterEvent函数,该函数处理鼠标进入按钮区域时的按钮进入事件。enterEvent函数添加如下:
...
...
def enterEvent(self, event):
self.setStyleSheet(self.but_style(self.mrg, self.pad,
self.bgh, self.txch, self.bds,
self.bdr, self.bdw, self.bdc))
...
...
此函数处理此按钮的进入事件并相应地更改样式。
- 为此按钮的离开事件添加
leaveEvent函数:
...
...
def leaveEvent(self, event):.
self.setStyleSheet(self.but_style(self.mrg,
self.pad, self.bg, self.txc, self.bds,
self.bdr, self.bdw, self.bgh))
...
...
此函数处理按钮的离开事件并相应地更改样式。这是一个尝试创建一个提供各种用途的按钮类的例子。或者换句话说,它给用户提供了根据应用程序任务和功能来样式化按钮组件的机会。所有这些样式参数都可以在这个类中更改,也可以在外部更改,例如在主应用程序或其他地方使用时。
现在,我们需要在u_app.py文件中将UBut1类添加到主应用程序类中,并使用一些自定义参数。按照以下步骤进行操作:
- 在
u_app.py文件的import部分添加以下行:
...
from u_style import UBut1
...
- 然后,我们需要将此按钮添加到
UApp类中,如下所示:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.push_but1 = UBut1(self.frame2)
self.push_but1.setText("Ok")
self.layfr2_1 = QtWidgets.QGridLayout()
self.layfr2_1.addWidget(self.push_but1, 0, 1, 1, 1)
...
...
...
我们已经添加了按钮实例并创建了一个将包含此按钮的布局。
- 然后,将使用此按钮创建的布局添加到第二个框架的布局中:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.layfr2.addLayout(self.layfr2_1, 5, 0, 1, 1)
...
...
...
我们将看到以下结果:

在右下角,我们可以看到“确定”按钮。当鼠标指针悬停在按钮上时,它将提供一个更浅绿色的悬停效果。
QCheckBox
就像单选按钮一样,复选框是一个选项按钮,允许用户做出选择。这些按钮通常与特定动作将使用的功能结合使用。这些选项可以根据用户的偏好开启或关闭。复选框可以显示选项的文本,以及图标。此类按钮的声明语法如下:
check_box = QtWidgets.QCheckBox()
QCheckBox 函数
QCheckBox 从 QAbstractButton 类继承,并通过以下函数改进了功能。
set
这些是与设置复选框相关参数/属性的函数:
check_box.setCheckState(QtCore.Qt.CheckState): 这将设置复选框的检查状态。
check_box.setTristate(bool): 这将设置与复选框一起使用的三态可用性。可以使用的状态如下:
-
QtCore.Qt.Unchecked: 复选框未被选中。 -
QtCore.Qt.PartiallyChecked: 复选框部分选中。 -
QtCore.Qt.Checked: 复选框被选中。
is
此函数返回与复选框状态相关的布尔值 (bool):
check_box.isTristate(): 如果这个复选框有三个状态,则返回 True。
functional
此函数与复选框当前值的返回相关:
check_box.checkState(): 这返回复选框的 QtCore.Qt.CheckState 类型的检查状态。
事件
这些是与事件相关的函数,例如事件处理程序:
check_box.event(QtCore.QEvent): 这是 QtCore.QObject 函数,接收对象的事件,如果事件被识别并处理,则应返回 True。
check_box.mouseMoveEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收复选框的鼠标移动事件,事件通过参数传递。
check_box.paintEvent(QtGui.QPaintEvent): 这是一个事件处理程序,旨在接收复选框的绘制事件,事件通过参数传递。
信号
QCheckBox 类可用的信号如下:
check_box.stateChanged(int): 当复选框的状态改变时,会发出此信号,状态通过参数传递。
额外组件
除了本章所涵盖的内容外,让我们考虑滑块和其他可用于 GUI 应用程序的有用组件。不同类型的滑块使得提供一些附加的特殊动作成为可能,例如滚动窗口和滑动值。
QAbstractSlider
此类是包括滚动条、滑块和旋钮在内的组件的父类。QAbstractSlider 从 QWidget 类继承,并通过以下函数改进了功能。
set
这些是与设置参数/属性相关的函数,包括大小、范围和功能:
setInvertedAppearance(bool): 如果参数为 True,则继承的组件将显示其值反转。
setInvertedControls(bool): 如果参数为 True,则将组件使用的轮和按键事件设置为反转。
setMaximum(int): 这将用于组件的参数中指定的最大值设置为。在滑块的情况下,这将是在范围内的最大值。
setMinimum(int): 这将用于组件的参数中指定的最小值设置为。在滑块的情况下,这将是在范围内的最小值。
setOrientation(QtCore.Qt.Orientation): 这将用于组件的朝向设置为 QtCore.Qt.Horizontal 或 QtCore.Qt.Vertical(默认)。
setPageStep(int): 这将设置与组件一起使用的参数中指定的页面步进。
setRange(int, int): 这将设置用于组件的范围值,从最小值(第一个参数)到最大值(第二个参数)。
setRepeatAction(QtWidgets.QAbstractSlider.SliderAction, int, int): 这设置在间隔(第三个参数)或延迟(第二个参数)时将触发的作用(第一个参数)。
setSingleStep(int): 这将设置用于组件的单步,通常通过响应组件之一的方向键的按下。
setSliderDown(bool): 如果参数为 True,则滑块将被拉下。
setSliderPosition(int): 这将设置滑块组件的当前位置指定的参数。
setTracking(bool): 如果参数为 True,则将跟踪设置为启用。如果此属性启用,组件在拖动时会发出 valueChanged() 信号。在另一种情况下,此信号仅在释放时发出。
setValue(int): 这将设置组件范围内的当前值指定的参数。例如,滑块的把手将移动到这个值。
is
这些函数返回与状态相关的布尔值 (bool):
isSliderDown(): 如果组件被按下,则返回 True。
functional
这些是与当前值返回、功能变化等相关联的函数:
invertedAppearance(): 如果继承的组件显示其值被反转,则返回 True。
invertedControls(): 如果组件使用的轮和按键事件被反转,则返回 True。
maximum(): 这返回正在使用的组件的整型最大值。在滑块的情况下,这将是在范围内的最大值。
minimum(): 这返回正在使用的组件的整型最小值。在滑块的情况下,这将是在范围内的最小值。
orientation(): 这返回正在使用的组件的 QtCore.Qt.Orientation 类型的朝向。
pageStep(): 这返回正在使用的组件的页面步进,以整数值表示。
repeatAction(): 这返回正在使用的组件的 QtWidgets.QAbstractSlider.SliderAction 类型的重复操作。
singleStep(): 这个函数返回正在使用的组件的单步值。
sliderChange(QtWidgets.QAbstractSlider.SliderChange): 这个函数跟踪滑动条的变化,使用可用的参数,如下所示:
-
QtWidgets.QAbstractSlider.SliderRangeChange—0: 范围变化。 -
QtWidgets.QAbstractSlider.SliderOrientationChange—1: 方向变化。 -
QtWidgets.QAbstractSlider.SliderStepsChange—2: 步长变化。 -
QtWidgets.QAbstractSlider.SliderValueChange—3: 值变化。
sliderPosition(): 这个函数返回滑动条组件在范围内的当前位置。
triggerAction(QtWidgets.QAbstractSlider.SliderAction): 这个函数触发参数中指定的滑动条动作。
value(): 这个函数返回滑动条组件的当前值。
事件
这些是与事件处理程序等事件相关的函数:
changeEvent(QtCore.QEvent): 这个函数处理状态变化。
event(QtCore.QEvent): 这是QtCore.QObject函数,它接收对象的事件,如果事件被识别并处理,则应返回True。
keyPressEvent(QtGui.QKeyEvent): 这是一个事件处理程序,用于接收用于组件的关键事件,其中事件通过参数传递。
timerEvent(QtCore.QTimerEvent): 这是一个事件处理程序,用于接收用于组件的计时器事件,其中计时器事件通过参数传递。
wheelEvent(QtGui.QWheelEvent): 这是一个事件处理程序,用于接收用于组件的鼠标滚轮事件,其中滚轮事件通过参数传递。
信号
QAbstractSlider类可用的信号如下:
actionTriggered(int): 当滑动条被传递参数的动作触发时,会发出此信号。
rangeChanged(int, int): 当滑动条的取值范围被修改为新的最小和最大范围参数时,会发出此信号。
sliderMoved(int): 当滑动条移动且sliderDown()为True时,会发出此信号,其中新的滑动条位置通过参数传递。
sliderPressed(): 当滑动条被按下时,会发出此信号,也可以通过setSliderDown(True)程序化地触发。
sliderReleased(): 当滑动条被释放时,会发出此信号,也可以通过setSliderDown(True)程序化地触发。
valueChanged(int): 当滑动条值被修订时,会发出此信号,其中新值通过参数传递。
QSlider
此类在 GUI 应用程序中提供了一个垂直或水平滑动条,可以用来移动滑动条手柄沿凹槽,并将手柄的位置转换为整数值。QSlider类继承自QAbstractSlider类。滑动条的声明语法如下:
slider = QtWidgets.QSlider()
QSlider类通过以下函数改进了功能。
设置
这些是与设置与滑动条相关的参数/属性的函数:
slider.setTickInterval(int): 这将设置此滑块的刻度线间隔。
slider.setTickPosition(QtWidgets.QSlider.TickPosition): 这将设置此滑块的刻度线位置。可用参数如下:
-
QtWidgets.QSlider.NoTicks—0: 没有刻度线。 -
QtWidgets.QSlider.TicksBothSides—3: 两边都有刻度线。 -
QtWidgets.QSlider.TicksAbove—1: 刻度线在上方(水平)。 -
QtWidgets.QSlider.TicksBelow—2: 刻度线在下方(水平)。 -
QtWidgets.QSlider.TicksLeft—TicksAbove: 刻度线在左侧(垂直)。 -
QtWidgets.QSlider.TicksRight—TicksBelow: 刻度线在右侧(垂直)。
功能性
这些是返回当前值的函数:
slider.tickInterval(): 这返回滑块刻度线之间的间隔。
slider.tickPosition(): 这返回QtWidgets.QSlider.TickPosition类型的刻度线位置。
事件
这些是与事件相关的函数,例如事件处理程序:
slider.event(QtCore.QEvent): 这是QtCore.QObject函数,它接收对象的事件,如果事件被识别并处理,则应返回True。
slider.mouseMoveEvent(QtGui.QMouseEvent): 这是一个事件处理程序,用于接收滑块的鼠标移动事件,并通过参数传递鼠标事件。
slider.mousePressEvent(QtGui.QMouseEvent): 这是一个事件处理程序,用于接收滑块的鼠标按下事件,并通过参数传递鼠标事件。
slider.mouseReleaseEvent(QtGui.QMouseEvent): 这是一个事件处理程序,用于接收滑块的鼠标释放事件,并通过参数传递鼠标事件。
slider.paintEvent(QtGui.QPaintEvent): 这是一个事件处理程序,用于接收滑块的绘制事件,并通过参数传递绘制事件。
QDial
此类提供了一个可以环绕在0到359度范围内的圆形范围组件。QDial类从QAbstractSlider类继承。旋钮的声明语法如下:
dial = QtWidgets.QDial()
QDial类通过以下函数增强了功能。
设置
这些是与设置与旋钮相关的参数/属性相关的函数:
dial.setNotchesVisible(bool): 如果参数为True,则将此旋钮的凹槽设置为可见。
dial.setNotchTarget(float): 这将设置此旋钮每个凹槽之间的像素参数指定的目标数值。
dial.setWrapping(bool): 如果参数为True,则为此旋钮启用环绕。
功能性
这些是与当前值返回相关的函数:
dial.notchesVisible(): 如果此旋钮上的凹槽可见,则返回True。
dial.notchSize(): 这返回旋钮凹槽的当前大小。
dial.notchTarget(): 这返回目标像素数作为浮点值,并用于此旋钮的凹槽之间。
dial.wrapping(): 如果此旋钮启用了包装,则返回 True。
事件
这些是与事件处理程序等事件相关的函数:
dial.event(QtCore.QEvent): 这接收对象的事件,如果事件被识别并处理,则应返回 True。
dial.mouseMoveEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收此旋钮的鼠标移动事件,并通过参数传递鼠标事件。
dial.mousePressEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收此旋钮的鼠标按下事件,并通过参数传递鼠标事件。
dial.mouseReleaseEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收此旋钮的鼠标释放事件,并通过参数传递鼠标事件。
dial.paintEvent(QtGui.QPaintEvent): 这是一个事件处理程序,旨在接收此旋钮的绘制事件,并通过参数传递绘制事件。
dial.resizeEvent(QtGui.QResizeEvent): 这是一个事件处理程序,旨在接收此旋钮的部件大小调整事件,并通过参数传递大小调整事件。
QProgressBar
进度条提供了一个水平或垂直组件来指示操作的进度。这可以在应用程序中实现。应用程序的声明语法如下:
progress = QtWidgets.QProgressBar()
QProgressBar 从 QWidget 类继承,并通过以下函数改进了功能。
设置
这些是与进度条参数/属性设置相关的函数:
progress.setAlignment(QtCore.Qt.Alignment): 这将设置与进度条一起使用的对齐方式。
progress.setFormat("%p%"): 这将设置用于进度的文本格式。可用的格式如下:
-
"%p%": 这些值将被替换为百分比(默认) -
"%v%": 这些值将被当前值替换 -
"%m%": 这些值将被替换为已完成的步骤总数
progress.setInvertedAppearance(bool): 如果参数为 True,则条形将显示其逆序进度。
progress.setMaximum(int): 这将设置此进度条的最大值。
progress.setMinimum(int): 这将设置此进度条的最低值。
progress.setOrientation(QtCore.Qt.Orientation): 这将设置此进度条的朝向。在参数中,可以使用 QtCore.Qt.Vertical 或 QtCore.Qt.Horizontal(默认)朝向。
progress.setRange(int, int): 这将设置进度条值的范围,指定最小值(第一个参数)和最大值(第二个参数)。通过使用 setRange(0, 0),进度条将被设置为不确定状态。
progress.setTextDirection(QtWidgets.QProgressBar.Direction): 这设置参数中指定的文本显示方向。垂直进度条的可选方向如下:
-
QtWidgets.QProgressBar.TopToBottom—0: 文本将顺时针旋转90度 -
QtWidgets.QProgressBar.BottomToTop—1: 文本将逆时针旋转90度
progress.setTextVisible(bool): 如果参数为 True,则将通过此进度条显示当前完成百分比。
progress.setValue(int): 这设置此进度条指定的当前值。
是
此函数返回与状态相关的布尔值 (bool):
progress.isTextVisible(): 如果当前完成百分比被显示,则返回 True。
功能性
这些函数与当前值的返回、功能变化等相关:
progress.alignment(): 这返回将与该进度条一起使用的 QtCore.Qt.Alignment 类型的对齐方式。
progress.format(): 这返回用于生成进度条中显示的文本的格式字符串。
progress.maximum(): 这返回进度条的最大值。
progress.minimum(): 这返回进度条的最小值。
progress.orientation(): 这返回进度条的 QtCore.Qt.Orientation 类型的方向。
progress.reset(): 这将重置进度条。进度条不会前进,而是回退。
progress.resetFormat(): 这将重置与进度条一起使用的文本格式。
progress.text(): 这返回与该进度条一起显示的文本。
progress.value(): 这返回此进度条当前值。
事件
这些函数与事件处理程序等事件相关:
progress.event(QtCore.QEvent): 这接收对象的事件,如果事件被识别并处理,则应返回 True。
progress.mouseMoveEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收进度条的鼠标移动事件,并通过参数传递鼠标事件。
progress.mousePressEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收进度条的鼠标按下事件,并通过参数传递鼠标事件。
progress.mouseReleaseEvent(QtGui.QMouseEvent): 这是一个事件处理程序,旨在接收进度条的鼠标释放事件,并通过参数传递鼠标事件。
progress.paintEvent(QtGui.QPaintEvent): 这是一个事件处理程序,旨在接收此进度条的绘制事件,并通过参数传递绘制事件。
信号
QProgressBar 类可用的信号如下:
valueChanged(int): 当进度条值发生变化时,会发出此信号,并通过参数传递新值。
QProgressBar 示例
现在,我们可以为应用程序创建进度条。这将指示将要运行的操作的进度。为此,在u_style.py文件中创建一个名为UProgress的类:
- 为进度条添加
UProgress类:
...
class UProgress(QtWidgets.QProgressBar):
def __init__(self, parent=None,
bg="rgba(0,190,255,140)",
txc="rgba(1,255,255,190)",
minw=0, minh=0, maxw=None, maxh=None,
fixw=None, fixh=None, mrg=0, pad=7,
bds="solid", bdr=3, bdw=0, bdc=color[3]):
super(UProgress, self).__init__(parent)
self.setMinimumWidth(minw)
self.setMinimumHeight(minh)
if maxw is not None:
self.setMaximumWidth(maxw)
if maxh is not None:
self.setMaximumHeight(maxh)
if fixw is not None:
self.setFixedWidth(fixw)
if fixh is not None:
self.setFixedHeight(fixh)
self.bg, self.txc, self.mrg, self.pad = bg, txc, mrg, pad
self.bds, self.bdr, self.bdw, self.bdc = bds, bdr, bdw, bdc
self.setStyleSheet(self.pgrs_style(self.mrg, self.pad,
self.bg, self.txc, self.bds, self.bdr, self.bdw, color[2]))
...
...
我们已成功添加了进度条的风格属性。这些可以在应用程序中重新实现。
- 然后,将
pgrs_style()函数添加到这个类中。这将用于设置进度条的风格:
...
...
def pgrs_style(self, mrg=None, pad=None, bg=None,
txc=None, bds=None, bdr=None, bdw=None, bdc=None):
style = """QProgressBar {margin: %spx; padding: %spx;
border-style: %s; border-radius: %spx;
border-width: %spx; border-color: %s;}
QProgressBar::chunk {background-color: %s;
color: %s;} """ % (mrg, pad, bds, bdr, bdw,
bdc, bg, txc)
return style
...
此函数将重新设置进度条的风格,并依赖于某些事件。这些事件的处理器可以稍后添加。现在,我们需要通过向u_app.py文件添加一些类来实现这个进度条在 GUI 中的显示。
- 将
UProgress类添加到导入部分:
...
from u_style import UProgress
...
- 然后,将进度条添加到
UApp类中:
...
...
def __init__(self, parent=None):
...
self.progress1 = UProgress(self.frame2)
self.progress1.setRange(0, 0)
self.layfr2_1 = QtWidgets.QGridLayout()
self.layfr2_1.addWidget(self.push_but1, 0, 1, 1, 1)
self.layfr2_1.addWidget(self.progress1, 1, 0, 1, 2)
...
...
...
我们正在使用条的setRange()方法来设置不确定模式的进度。当我们运行u_app.py文件时,我们将看到以下结果(进度条在不确定模式下无限滑动):

我们在按钮下方添加了进度条。目前,它处于不确定状态。
摘要
本章展示了在 GUI 应用程序中可以使用的最流行组件的基本特性和属性。这些元素包括按钮,以及一些控件和指示条。并非所有这些都在我们的示例中涵盖,但它们可以在需要时添加到应用程序功能实现中。
本章在 GUI 应用程序主要组件的描述下划了一条线。在下一章中,我们将深入探讨 GUI 应用程序中图形的基础知识。
第九章:图形基础
Qt 框架为您提供了在应用程序中使用和/或表示各种图形的机会。在这里,我们将介绍我们可以用来绘制、绘制和使用图像的基本类。本章主要涉及使用 Qt 和 Python 绑定管理创建图形元素的基础知识。由于 Qt 是一个图形库,这个主题非常广泛,因此本章基本上是图形基础介绍,将在未来的章节中进一步展开。
在本章中,我们将涵盖以下主题:
-
基础
-
绘制和渐变
-
图片
基础
Qt 框架和 Python 绑定,如 PySide 和 PyQt,实际上绘制了在上一章中描述的图形组件。这种绘制与按钮、字段、标签和其他小部件相关。正如我们之前所描述的,QWidget 类继承自 QObject 类,它为图形元素提供了一些功能,以及 QPaintDevice 类,它提供了在 GUI 应用程序中绘制元素的功能。这种结构是 Qt 图形库的主要范式。此外,还有一些支持类,将在本节中首先介绍。然而,本章无法容纳所有需要学习的类,以便完全理解在开发过程中管理图形的机制。为了实现这一点,请查阅相关文档(Qt—doc.qt.io/,PySide2—doc.qt.io/qtforpython/index.html,PyQt5—www.riverbankcomputing.com/static/Docs/PyQt5/)。
QFont
此类提供了一个字体,该字体将用于绘制应用程序中组件的文本。还有其他用于处理字体的类,例如 QFontInfo、QFontMetrics、QFontMetricsF 和 QFontDatabase。在代码中使用 QFont 类可能的形式如下:
font = QtGui.QFont()
QFont 通过以下功能提高功能。
设置
这些是与设置字体相关参数和属性相关的函数,包括设置字体家族和间距:
font.setBold(bool): 如果参数为 True,则将当前字体设置为粗体。
font.setCapitalization(QtGui.QFont.Capitalization): 这将设置文本的字母大小写;所有单词都将大写。可用的参数如下:
-
QtGui.QFont.MixedCase—0: 不应用大小写。 -
QtGui.QFont.AllUppercase—1: 全大写。 -
QtGui.QFont.AllLowercase—2: 全小写。 -
QtGui.QFont.SmallCaps—3: 小写字母。 -
QtGui.QFont.Capitalize—4: 每个单词的首字母大写。
font.setFamily("Font family"): 这将为此字体设置字体家族名称(不区分大小写)。
font.setFixedPitch(bool): 如果参数为True,则为此字体设置固定间距。
font.setHintingPreference(QtGui.QFont.HintingPreference): 这将为参数中指定的此字体的符号设置提示级别。这取决于操作系统。可用的参数如下:
-
QtGui.QFont.PreferDefaultHinting—0: 平台的默认提示级别。 -
QtGui.QFont.PreferNoHinting—1: 在可能的情况下,不提示的文本。 -
QtGui.QFont.PreferVerticalHinting—2: 在可能的情况下,垂直对齐符号,而不进行文本的水平提示。 -
QtGui.QFont.PreferFullHinting—3: 在可能的情况下,提供水平和垂直提示。
font.setItalic(bool): 如果参数为True,则将字体设置为斜体(草书)。
font.setKerning(bool): 如果参数为True,则为此字体设置启用间距(默认:True);符号度量不累加。
font.setLetterSpacing(QtGui.QFont.SpacingType, float): 这将为具有在第一个参数中指定的类型和第二个参数中指定的float值的间距的文本字体设置每个字母之间的间距。可用的间距类型如下:
-
QtGui.QFont.PercentageSpacing—0: 间距作为百分比;值为200.0时,间距将根据其字符宽度放大。 -
QtGui.QFont.AbsoluteSpacing—0: 像素间距。
font.setOverline(bool): 如果参数为True,则将此字体的文本设置为上划线。
font.setPixelSize(int): 这将设置参数中指定的字体文本的大小,以像素值表示。
font.setPointSize(int): 这将设置参数中指定的字体文本的大小,以点值表示。
font.setPointSizeF(float): 这将设置参数中指定的字体文本的大小,以点值表示,具有浮点精度。
font.setRawName(str): 这将设置由其系统名称使用的字体。
font.setStretch(int): 这将设置此字体的拉伸因子,从1到4000(因子为250时,所有字符都将宽 2.5 倍)。
font.setStrikeOut(bool): 如果参数为True,则将此字体的文本设置为删除线。
font.setStyle(QtGui.QFont.Style): 这将设置参数中指定的字体样式。可用的样式如下:
-
QtGui.QFont.StyleNormal—0: 正常符号。 -
QtGui.QFont.StyleItalic—1: 斜体符号。 -
QtGui.QFont.StyleOblique—2: 基于无样式符号的斜体外观符号。
font.setStyleHint(QtGui.QFont.StyleHint, QtGui.QFont.StyleStrategy): 这将为字体匹配器首选的样式提示(第一个参数)和提示策略(第二个参数)设置样式提示。可用的样式提示如下:
-
QtGui.QFont.SansSerif—Helvetica: 优先使用无衬线字体。 -
QtGui.QFont.Helvetica—0: 优先使用无衬线字体。 -
QtGui.QFont.Serif—Times: 优先选择衬线字体。 -
QtGui.QFont.Times—1: 优先选择衬线字体。 -
QtGui.QFont.TypeWriter—Courier: 优先选择固定间距字体。 -
QtGui.QFont.Courier—2: 优先选择固定间距字体。 -
QtGui.QFont.OldEnglish—3: 优先选择装饰字体。 -
QtGui.QFont.Decorative—OldEnglish: 优先选择装饰字体。 -
QtGui.QFont.System—4: 优先选择系统字体。 -
QtGui.QFont.AnyStyle—5: 优先选择选择。 -
QtGui.QFont.Cursive—6: 优先选择草书字体家族。 -
QtGui.QFont.Monospace—7: 优先选择等宽字体家族。 -
QtGui.QFont.Fantasy—8: 优先选择幻想字体家族。
font.setStyleName(str): 这将设置样式名称,名称由参数指定。
font.setStyleStrategy(QtGui.QFont.StyleStrategy): 这将设置字体的样式策略。以下样式策略可用于指定字体匹配器应使用哪种类型来查找默认家族:
-
QtGui.QFont.PreferDefault: 不优先选择任何字体。 -
QtGui.QFont.PreferBitmap: 优先选择位图字体。 -
QtGui.QFont.PreferDevice: 优先选择设备字体。 -
QtGui.QFont.ForceOutline: 使用轮廓字体。 -
QtGui.QFont.NoAntialias: 不对字体进行抗锯齿。 -
QtGui.QFont.NoSubpixelAntialias: 如果可能,将不会对字体进行子像素抗锯齿。 -
QtGui.QFont.PreferAntialias: 优先选择抗锯齿。 -
QtGui.QFont.OpenGLCompatible: 使用与 OpenGL 兼容的字体。 -
QtGui.QFont.NoFontMerging: 如果书写系统不包含此字符,则禁用自动查找类似字体的功能。 -
QtGui.QFont.PreferNoShaping: 禁用不需要时应用复杂规则等特性。
可用于与 OR (|) 运算符一起使用的可用标志如下:
-
QtGui.QFont.PreferMatch: 优先选择精确匹配。 -
QtGui.QFont.PreferQuality: 优先选择最佳质量的字体。 -
QtGui.QFont.ForceIntegerMetrics: 在字体引擎中使用整数值。
font.setUnderline(bool): 如果参数为 True,则将此字体的文本设置为下划线。
font.setWeight(int): 这将设置字体的重量,重量由参数指定。字体重量的可用值如下:
-
QtGui.QFont.Thin:0 -
QtGui.QFont.ExtraLight:12 -
QtGui.QFont.Light:25 -
QtGui.QFont.Normal:50 -
QtGui.QFont.Medium:57 -
QtGui.QFont.DemiBold:63 -
QtGui.QFont.Bold:75 -
QtGui.QFont.ExtraBold:81 -
QtGui.QFont.Black:87
font.setWordSpacing(float): 这将设置此字体中每个单词之间的间距,间距由参数指定。
is
这些是返回与字体相关的布尔值(bool)的函数:
font.isCopyOf(QtGui.QFont): 如果在参数中指定的字体是当前字体的副本,则返回 True。
functional
这些是与当前字体值的返回相关的函数:
font.bold(): 如果 font.weight() 的值大于 QFont.Medium,则返回 True;否则返回 False。
font.cacheStatistics(): 这输出字体的缓存统计信息。
font.capitalization(): 这返回此字体QtGui.QFont.Capitalization类型的当前大写化。
font.cleanup(): 这清理字体系统。
font.defaultFamily(): 这返回用于当前样式提示的字体家族。
font.exactMatch(): 如果窗口系统中有与该字体设置匹配的字体,则返回True。
font.family(): 这返回与该字体一起使用的当前字体家族名称。
font.fixedPitch(): 如果为此字体设置了固定间距,则返回True。
font.fromString(str): 这设置此字体,它将匹配参数中指定的描述,作为带有字体属性的逗号分隔列表。
font.hintingPreference(): 这返回当前首选的符号的提示级别,并将使用此字体进行渲染。
font.initialize(): 这初始化字体系统。
font.insertSubstitution(str, str): 这将第二个参数中指定的替代名称插入到字体家族(第一个参数)的替换表中。
font.insertSubstitution(str, [str]): 这将第二个参数中指定的替代名称列表插入到字体家族(第一个参数)的替换表中。
font.italic(): 如果当前字体是斜体(草书),则返回True。
font.kerning(): 如果与此字体一起使用字距调整,则返回True。
font.key(): 这返回当前字体的键,作为此字体的文本表示。
font.lastResortFamily(): 这返回字体家族名称,作为最后的手段。
font.lastResortFont(): 这返回字体:最后的手段。
font.letterSpacing(): 这以浮点值返回每个字母之间的间距,该值与此字体一起使用。
font.letterSpacingType(): 这返回作为QtGui.QFont.SpacingType的间距类型,并用于字母间距。
font.overline(): 如果字体有上划线,则返回True。
font.pixelSize(): 这返回像素表示中的字体大小。
font.pointSize(): 这以点表示返回字体的大小。
font.pointSizeF(): 这以浮点值返回点表示中的字体大小。
font.rawName(): 这返回底层窗口系统中使用的字体名称。
font.removeSubstitutions(str): 这删除参数中指定的字体家族名称的替换。
font.resolve(QtGui.QFont): 这返回具有参数中指定的字体属性的新字体,这些属性尚未设置。
font.stretch(): 这返回此字体的拉伸因子。
font.strikeOut(): 如果此字体的文本有删除线,则返回True。
font.style(): 这返回此字体QtGui.QFont.Style类型的样式。
font.styleHint(): 这返回此字体QtGui.QFont.StyleHint类型的样式提示。
font.styleName(): 这返回用于此字体样式的样式名称。
font.styleStrategy(): 这返回QtGui.QFont.StyleStrategy类型的策略,并用于此字体的字体匹配器。
font.substitute(str): 这返回与参数中指定的家族名称一起使用的第一个替换字体家族名称。
font.substitutes(str): 这返回使用指定家族名称的替换字体家族名称列表。
font.substitutions(): 这返回一个排序后的替换字体家族名称列表。
font.swap(QtGui.QFont): 这将此字体与参数中指定的字体进行交换。
font.toString(): 这返回以逗号分隔的描述此字体的列表。
font.underline(): 如果此字体的文本被下划线,则返回True。
font.weight(): 这返回此字体的权重。
font.wordSpacing(): 这返回文本中每个单词之间的间距,以浮点值表示。
QColor
此类提供了用于应用程序组件的颜色操作。此类表示基于 RGB (红色、绿色和蓝色)、HSV (色调、饱和度和亮度)和 CMYK (青色、品红色、黄色和黑色)值颜色的模型。它们可以按以下方式使用:
-
命名颜色:"white"。
-
字符串/值:"#FFFFFF",
(255, 255, 255),(1, 1, 1),换句话说,#redgreenblue 或 (red, green, blue)。 -
字符串/值:"#FFFFFFFF",
(255, 255, 255, 255),(1, 1, 1, 1),换句话说,#redgreenbluealpha 或 (red, green, blue, alpha)。
颜色的 alpha 通道(RGBA 中的字母A)是透明度。HSV 和 CMYK 可以以类似的方式用于其颜色模型的颜色。我们可以像这样使用QColor类:
color = QtGui.QColor()
QColor通过以下函数提高功能。
set
这些是与设置颜色相关参数和属性相关的函数,包括设置颜色或色调:
color.setAlpha(a): 这将 alpha,a,设置为该颜色的整数值(0-255)。
color.setAlphaF(a): 这将 alpha,a,设置为该颜色的浮点值(0.0-1.0)。
color.setBlue(b): 这将蓝色,b,设置为该颜色的整数值(0-255)。
color.setBlueF(b): 这将蓝色,b,设置为该颜色的浮点值(0.0-1.0)。
color.setCmyk(c, m, y, k, a): 这将参数中指定的 CMYK 颜色设置为:
-
c: 青色 (0-255). -
m: 品红色 (0-255). -
y: 黄色 (0-255). -
k: 黑色 (0-255). -
a: Alpha (0-255).
color.setCmykF(c, m, y, k, a): 这将参数中指定的 CMYK 颜色设置为:
-
c: 青色 (0.0-1.0). -
m: 品红色 (0.0-1.0). -
y: 黄色 (0.0-1.0). -
k: 黑色 (0.0-1.0). -
a: Alpha (0.0-1.0).
color.setGreen(g): 这将绿色,g,设置为该颜色的整数值(0-255)。
color.setGreenF(g): 这将绿色,g,设置为该颜色的浮点值(0.0-1.0)。
color.setHsl(h, s, l, a): 这设置由参数指定的 HSL 颜色:
-
h: 色调 (0-255)。 -
s: 饱和度 (0-255)。 -
l: 亮度 (0-255)。 -
a: 透明度 (0.0-255)。
color.setHslF(h, s, l, a): 这设置由参数指定的 HSL 颜色:
-
h: 色调 (0.0-1.0)。 -
s: 饱和度 (0.0-1.0)。 -
l: 亮度 (0.0-1.0)。 -
a: 透明度 (0.0-1.0)。
color.setHsv(h, s, v, a): 这设置由参数指定的 HSV 颜色:
-
h: 色调 (0-255)。 -
s: 饱和度 (0-255)。 -
v: 亮度 (0-255)。 -
a: 透明度 (0-255)。
color.setHsvF(h, s, v, a): 这设置由参数指定的 HSV 颜色:
-
h: 色调 (0.0-1.0)。 -
s: 饱和度 (0.0-1.0)。 -
v: 亮度 (0.0-1.0)。 -
a: 透明度 (0.0-1.0)。
color.setNamedColor(str): 这将此颜色的 RGB 值设置为参数中指定的名称。将要命名的颜色格式如下:"#RGB","#RRGGBB","#AARRGGBB","#RRRGGGBBB",和 "#RRRRGGGGBBBB"。
color.setRed(r): 这将红色 r 设置为该颜色的整数值 (0-255)。
color.setRedF(r): 这将红色 r 设置为该颜色的浮点值 (0.0-1.0)。
color.setRgb(r, g, b, a): 这设置由参数指定的 RGB 颜色:
-
r: 红色 (0-255)。 -
g: 绿色 (0-255)。 -
b: 蓝色 (0-255)。 -
a: 透明度 (0-255)。
color.setRgbF(r, g, b, a): 这设置由参数指定的 RGB 颜色:
-
r: 红色 (0.0-1.0)。 -
g: 绿色 (0.0-1.0)。 -
b: 蓝色 (0.0-1.0)。 -
a: 透明度 (0.0-1.0)。
is
这些是返回与颜色相关的布尔值 (bool) 的函数:
color.isValid(): 如果此颜色有效,则返回 True。
color.isValidColor(str): 如果参数中指定的颜色是有效颜色,则返回 True。
functional
这些是与当前颜色值返回相关的函数:
color.alpha(): 这返回颜色的透明度粒子,以该颜色的整数值表示。
color.alphaF(): 这返回颜色的透明度粒子,以该颜色的浮点值表示。
color.black(): 这返回颜色的黑色粒子,以该颜色的整数值表示。
color.blackF(): 这返回颜色的黑色粒子,以该颜色的浮点值表示。
color.blue(): 这返回颜色的蓝色粒子,以该颜色的整数值表示。
color.blueF(): 这返回颜色的蓝色粒子,以该颜色的浮点值表示。
color.colorNames(): 这返回包含 Qt 颜色列表中可用颜色名称的字符串列表。
color.convertTo(QtGui.QColor.Spec): 这将参数中的指定符的颜色复制并返回 QtGui.QColor 类型的颜色。可用的指定符如下:
-
QtGui.QColor.Rgb—1: 红色、绿色、蓝色。 -
QtGui.QColor.Hsv—2: 色调、饱和度、亮度。 -
QtGui.QColor.Cmyk—3: 青色、品红色、黄色、黑色。 -
QtGui.QColor.Hsl—4: 色调、饱和度、亮度。
color.cyan(): 此函数返回颜色的青色部分,以该颜色的整数值表示。
color.cyanF(): 此函数返回颜色的青色部分,以该颜色的 float 值表示。
color.darker(int): 此函数返回 QtGui.QColor 类型的较暗或较亮颜色,参数中指定了一个整数值作为因子。如果因子大于 100,则颜色较暗;如果因子小于 100,则颜色较亮。
color.fromCmyk(c, m, y, k, a): 此函数返回具有指定参数的 QtGui.QColor 类型的 CMYK 颜色:
-
c: 青色 (0-255). -
m: 品红色 (0-255). -
y: 黄色 (0-255). -
k: 黑色 (0-255). -
a: 透明度 (0-255).
color.fromCmykF(c, m, y, k, a): 此函数返回具有指定参数的 QtGui.QColor 类型的 CMYK 颜色:
-
c: 青色 (0.0-1.0). -
m: 品红色 (0.0-1.0). -
y: 黄色 (0.0-1.0). -
k: 黑色 (0-1.0). -
a: 透明度 (0.0-1.0).
color.fromHsl(h, s, l, a): 此函数返回具有指定参数的 QtGui.QColor 类型的 HSL 颜色:
-
h: 色调 (0-255). -
s: 饱和度 (0-255). -
l: 亮度 (0-255). -
a: 透明度 (0-255).
color.fromHslF(h, s, l, a): 此函数返回具有指定参数的 QtGui.QColor 类型的 HSL 颜色:
-
h: 色调 (0.0-1.0). -
s: 饱和度 (0.0-1.0). -
l: 亮度 (0.0-1.0). -
a: 透明度 (0.0-1.0).
color.fromHsv(h, s, v, a): 此函数返回具有指定参数的 QtGui.QColor 类型的 HSV 颜色:
-
h: 色调 (0-255). -
s: 饱和度 (0-255). -
v: 价值 (0-255). -
a: 透明度 (0-255).
color.fromHsvF(h, s, v, a): 此函数返回具有指定参数的 QtGui.QColor 类型的 HSV 颜色:
-
h: 色调 (0.0-1.0). -
s: 饱和度 (0.0-1.0). -
v: 价值 (0.0-1.0). -
a: 透明度 (0.0-1.0).
color.fromRgb(r, g, b, a): 此函数返回具有指定参数的 QtGui.QColor 类型的 RGB 颜色:
-
r: 红色 (0-255). -
g: 绿色 (0-255). -
b: 蓝色 (0-255). -
a: 透明度 (0-255).
color.fromRgbF(r, g, b, a): 此函数返回具有指定参数的 QtGui.QColor 类型的 RGB 颜色:
-
r: 红色 (0.0-1.0) . -
g: 绿色 (0.0-1.0). -
b: 蓝色 (0.0-1.0). -
a: 透明度 (0.0-1.0).
color.getCmyk(): 此函数检索 c、m、y、k 和 a 的内容,并以整数值设置组件为 CMYK 颜色的青色、品红色、黄色、黑色和透明度值。
color.getCmykF(): 此函数检索 c、m、y、k 和 a 的内容,并以 float 值设置组件为 CMYK 颜色的青色、品红色、黄色、黑色和透明度值。
color.getHsl(): 此函数检索 h、s、l 和 a 的内容,并以整数值设置组件为 HSL 颜色的色调、饱和度、亮度和透明度值。
color.getHslF(): 此函数检索 h、s、l 和 a 的内容,并以 float 值设置组件为 HSL 颜色的色调、饱和度、亮度和透明度值。
color.getHsv(): 这检索 h、s、v 和 a 的内容,并以整数值设置这些组件为 HSV 颜色的色调、饱和度、值和透明度。
color.getHsvF(): 这检索 h、s、v 和 a 的内容,并以浮点值设置这些组件为 HSV 颜色的色调、饱和度、值和透明度。
color.getRgb(): 这检索 r、g、b 和 a 的内容,并以整数值设置这些组件为 RGB 颜色的红色、绿色、蓝色和透明度值。
color.getRgbF(): 这检索 r、g、b 和 a 的内容,并以浮点值设置这些组件为 RGB 颜色的红色、绿色、蓝色和透明度。
color.green(): 这返回颜色的绿色粒子,以该颜色的整数值表示。
color.greenF(): 这返回颜色的绿色粒子,以该颜色的浮点值表示。
color.hslHue(): 这返回颜色的色调粒子,以该颜色的整数值表示。
color.hslHueF(): 这返回颜色的色调粒子,以该颜色的浮点值表示。
color.hslSaturation(): 这返回颜色的饱和度粒子,以该颜色的整数值表示。
color.hslSaturationF(): 这返回颜色的饱和度粒子,以该颜色的浮点值表示。
color.hsvHue(): 这返回颜色的色调粒子,以该颜色的整数值表示。
color.hsvHueF(): 这返回颜色的色调粒子,以该颜色的浮点值表示。
color.hsvSaturation(): 这返回颜色的饱和度粒子,以该颜色的整数值表示。
color.hsvSaturationF(): 这返回颜色的饱和度粒子,以该颜色的浮点值表示。
color.hue(): 这返回颜色的色调粒子,以该颜色的整数值表示。
color.hueF(): 这返回颜色的色调粒子,以该颜色的浮点值表示。
color.lighter(int): 这返回一个 QtGui.QColor 类型的更亮或更暗的颜色,参数中指定的因子以整数值表示。如果因子大于 100,颜色更亮;如果因子小于 100,颜色更暗。
color.lightness(): 这返回颜色的亮度粒子,以该颜色的整数值表示。
color.lightnessF(): 这返回颜色的亮度粒子,以该颜色的浮点值表示。
color.magenta(): 这返回颜色的洋红色粒子,以该颜色的整数值表示。
color.magentaF(): 这返回颜色的洋红色粒子,以该颜色的浮点值表示。
color.name(): 这以 "#RRGGBB" 格式返回颜色名称。
color.name(QtGui.QColor.NameFormat): 这返回参数中指定的格式的颜色名称。
color.red(): 这返回颜色的红色粒子,以该颜色的整数值表示。
color.redF(): 这返回颜色的红色粒子,以该颜色的浮点值表示。
color.saturation(): 这返回颜色的饱和度粒子,以该颜色的整数值形式。
color.saturationF(): 这返回颜色的饱和度粒子,以该颜色的浮点值形式。
color.spec(): 这返回该颜色的 QtGui.QColor.Spec 类型的指定符。
color.toCmyk(): 这创建并返回该颜色的 QtGui.QColor 类型的 CMYK 颜色。
color.toHsl(): 这创建并返回该颜色的 QtGui.QColor 类型的 HSL 颜色。
color.toHsv(): 这创建并返回该颜色的 QtGui.QColor 类型的 HSV 颜色。
color.toRgb(): 这创建并返回该颜色的 QtGui.QColor 类型的 RGB 颜色。
color.value(): 这返回颜色的值粒子,以该颜色的整数值形式。
color.valueF(): 这返回颜色的值粒子,以该颜色的浮点值形式。
color.yellow(): 这返回颜色的黄色粒子,以该颜色的整数值形式。
color.yellowF(): 这返回颜色的黄色粒子,以该颜色的浮点值形式。
绘制和渐变
Qt 框架提供了您可以在应用程序中用于处理绘图和绘画的类。几乎每个小部件都是为了可视化目的而构建的,并且使用 Qt 库类图形表示的那些小部件将根据这些类进行绘制或绘制。渐变使各种元素的色彩更加现代,并赋予它们更佳的外观。
QPainter
QPainter 类是 Qt 图形系统的主要组件之一。此类提供以各种形式对图形元素进行低级绘制的功能。从 QWidget 继承的 QPaintDevice 类与该类一起绘制元素。QPainter 类用于执行与绘制和绘画相关的操作,以及 QPaintDevice 和 QPaintEngine 等类。此类的声明语法如下:
painter = QtGui.QPainter()
此外,如果绘图设备是小部件,则此类只能在 paintEvent() 函数或调用 paintEvent() 函数的函数内部实现,如下所示:
def paintEvent(self, event):
painter = QtGui.QPainter(self)
QPainter 类通过以下函数提高功能。
设置
这些是与设置画家相关参数和属性相关的函数。
painter.setBackground(QtGui.QBrush): 这将此画家的背景画笔设置为参数中指定的画笔。
painter.setBackgroundMode(QtCore.Qt.BGMode): 这将此画家的背景模式设置为参数中指定的模式。
painter.setBrush(QtGui.QBrush): 这将此画家的画笔设置为参数中指定的画笔。
painter.setBrush(QtCore.Qt.BrushStyle): 这将此画家的画笔设置为黑色和指定的样式。
painter.setBrushOrigin(QtCore.QPoint): 这将画笔原点设置为参数中指定的点,使用整数值。
painter.setBrushOrigin(QtCore.QPointF): 这将设置画笔原点为参数中指定的具有浮点值的点。
painter.setBrushOrigin(x, y): 这将设置画笔原点在 x(x 轴)和 y(y 轴)位置。
painter.setClipping(bool): 如果参数是 True,则启用剪辑。
painter.setClipPath(QtGui.QPainterPath, QtCore.Qt.ClipOperation): 这将为这个画家设置剪辑路径为路径(第一个参数)和剪辑操作(第二个参数)。
painter.setClipRect(QtCore.QRect, QtCore.Qt.ClipOperation): 这将通过使用剪辑操作(第二个参数)将剪辑区域设置为具有整数值的矩形(第一个参数)。
painter.setClipRect(QtCore.QRectF, QtCore.Qt.ClipOperation): 这将通过使用剪辑操作(第二个参数)将剪辑区域设置为具有浮点值的矩形(第一个参数)。
painter.setClipRect(QtGui.QRegion, QtCore.Qt.ClipOperation): 这将通过使用剪辑操作(第二个参数)将剪辑区域设置为第一个参数中指定的区域。
painter.setClipRect(x, y, w, h, QtCore.Qt.ClipOperation): 这将通过使用剪辑操作(第五个参数)将剪辑区域设置为从 x(x 轴)和 y(y 轴)开始的矩形,以及 w(宽度)和 h(高度)。
painter.setCompositionMode(QtGui.QPainter.CompositionMode): 这将设置参数中指定的合成模式。
painter.setFont(QtGui.QFont): 这将设置画家的字体为参数中指定的字体。
painter.setLayoutDirection(QtCore.Qt.LayoutDirection): 这将设置绘制文本的布局方向。
painter.setOpacity(float): 这将设置透明度,指定在参数中(0.0:完全透明,1.0:完全不透明),将与这个画家一起使用。
painter.setPen(QtGui.QPen): 这将设置参数中指定的笔到这个画家。
painter.setPen(QtGui.QColor): 这将设置具有参数中指定的颜色的笔到这个画家。
painter.setPen(QtCore.Qt.PenStyle): 这将设置具有参数中指定的样式和黑色颜色的笔到这个画家。
painter.setRenderHint(QtGui.QPainter.RenderHint, bool): 如果第二个参数是 True,则将渲染提示(第一个参数)设置为画家。可用的提示如下:
-
QtGui.QPainter.Antialiasing: 如果可能,将抗锯齿原始图形的边缘。 -
QtGui.QPainter.TextAntialiasing: 如果可能,将抗锯齿文本。 -
QtGui.QPainter.SmoothPixmapTransform: 引擎将使用平滑的位图变换。 -
QtGui.QPainter.Qt4CompatiblePainting: 引擎将使用与 Qt4 相同的填充规则。
painter.setRenderHints(QtGui.QPainter.RenderHint | QtGui.QPainter.RenderHint, bool): 如果第二个参数是 True,则将渲染提示(第一个参数)设置为画家。
painter.setTransform(QtGui.QTransform, bool): 这设置由第一个参数指定的变换矩阵。如果第二个参数为 True,则变换将与当前矩阵组合;否则,它将替换当前矩阵。
painter.setViewTransformEnabled(bool): 如果参数为 True,则设置视图变换为启用。
painter.setViewport(QtCore.QRect): 这将画笔的视口矩形设置为参数中指定的矩形。视口表示设备的坐标系。
painter.setViewport(x, y, w, h): 这将画笔的视口矩形设置为指定的矩形,从 x(x 轴)和 y(y 轴)开始,以及 w(宽度)和 h(高度)。
painter.setWindow(QtCore.QRect): 这将画笔的窗口设置为参数中指定的矩形。
painter.setWindow(x, y, w, h): 这将画笔的窗口设置为指定的矩形,从 x(x 轴)和 y(y 轴)开始,以及 w(宽度)和 h(高度)。
painter.setWorldMatrixEnabled(bool): 如果参数为 True,则设置世界变换为启用。
painter.setWorldTransform(QtGui.QTransform, bool): 这设置由第一个参数指定的世界变换矩阵。如果第二个参数为 True,则变换将与当前矩阵组合;否则,它将替换当前矩阵。
has 和 is
这些是返回与画笔相关的布尔值 (bool) 的函数:
painter.hasClipping(): 如果此画笔设置了裁剪,则返回 True。
painter.isActive(): 如果画笔是活动的并且已调用 begin(),则返回 True,而 end() 尚未调用。
functional
这些是与当前画笔值的返回相关的函数:
painter.background(): 这返回用于背景的当前 QtGui.QBrush 类型的画笔。
painter.backgroundMode(): 这返回用于背景的当前 QtCore.Qt.BGMode 类型的模式。
painter.begin(QtGui.QPaintDevice): 这使用参数中指定的绘图设备开始绘制,如果绘制成功则返回 True。
painter.beginNativePainting(): 这刷新绘图管道并准备对底层图形上下文进行绘制。
painter.boundingRect(QtCore.QRectF, QtCore.Qt.Alignment, str): 这返回 QtCore.QRectF 类型的边界矩形,其中包含文本(第三个参数)、矩形(第一个参数)和标志(第二个参数),如它们在绘图中所出现。
painter.brush(): 这返回与该画笔一起使用的当前 QtGui.QBrush 类型的画笔。
painter.brushOrigin(): 这返回 QtCore.QPoint 类型的画笔原点。
painter.clipBoundingRect(): 如果存在裁剪,则返回当前裁剪的 QtCore.QRectF 类型的边界矩形。
painter.combinedTransform(): 这返回组合当前世界变换和窗口/视口的变换矩阵。
painter.compositionMode(): 这返回当前使用的 QtGui.QPainter.CompositionMode 类型的合成模式。
painter.device(): 这返回用于绘图的当前 QtGui.QPaintDevice 类型的绘图设备。
painter.deviceTransform(): 这返回将逻辑坐标转换为平台相关绘图设备的设备坐标的矩阵。
painter.end(): 这将结束绘图操作,如果绘图器结束操作并且不再活跃,则返回 True。
painter.endNativePainting(): 这在发出原生绘图命令后恢复绘图器。
painter.eraseRect(QtCore.QRect): 这擦除参数中指定的整数值指定的矩形内的区域。
painter.eraseRect(QtCore.QRectF): 这使用参数中指定的浮点值擦除矩形内的区域。
painter.eraseRect(x, y, w, h): 这擦除从 x(x 轴)和 y(y 轴)开始的矩形内的区域,以及 w(宽度)和 h(高度)。
painter.font(): 这返回使用此绘图器绘制文本的当前字体。
painter.fontInfo(): 这返回与该绘图器一起使用的字体的字体信息。
painter.fontMetrics(): 这返回与该绘图器一起使用的字体的字体度量。
painter.layoutDirection(): 这返回与该绘图器一起用于绘制文本的 QtCore.Qt.LayoutDirection 类型的布局方向。
painter.opacity(): 这返回与该绘图器一起使用的透明度。
painter.paintEngine(): 这返回此绘图器正在操作的当前 QtGui.QPaintEngine 类型的绘图引擎。
painter.pen(): 这返回与该绘图器一起使用的当前 QtGui.QPen 类型的笔。
painter.renderHints(): 这返回用于此绘图器绘图的 QtGui.QPainter.RenderHints 类型的渲染提示。
painter.resetTransform(): 这重置使用此绘图器的 translate()、scale()、shear()、rotate()、setWorldTransform()、setViewport() 和 setWindow() 函数所做的变换。
painter.restore(): 这恢复此绘图器的当前状态。
painter.rotate(float): 这以角度参数按顺时针方向旋转此绘图器的坐标系。
painter.save(): 这保存此绘图器的当前状态。
painter.scale(x, y): 这通过 x(x 轴)和 y(y 轴)值缩放此绘图器的坐标系,这些值是浮点数。
painter.shear(float, float): 这根据指定的参数剪切坐标系。
painter.strokePath(QtGui.QPainterPath, QtGui.QPen): 这使用第二个参数指定的笔来绘制第一个参数指定的路径的轮廓。
painter.testRenderHint(QtGui.QPainter.RenderHint): 如果参数中指定的提示设置为该画家,则返回 True。
painter.transform(): 这返回 QtGui.QTransform 类型的变换矩阵。
painter.translate(QtCore.QPoint): 这将在参数中指定的点(以整数值指定)处平移坐标系。
painter.translate(QtCore.QPointF): 这将在参数中指定的点(以浮点值指定)处平移坐标系。
painter.translate(float, float): 这将根据指定的向量平移坐标系。
painter.viewTransformEnabled(): 如果此画家的视图变换被启用,则返回 True。
painter.viewport(): 这返回 QtCore.QRect 类型的视口矩形。
painter.window(): 这返回 QtCore.QRect 类型的窗口矩形。
painter.worldMatrixEnabled(): 如果此画家的世界变换被启用,则返回 True。
painter.worldTransform(): 这返回 QtGui.QTransform 类型的世界变换矩阵。
draw
这些是与该画家相关的绘图操作函数:
painter.drawArc(QtCore.QRect, int, int): 这将使用参数中指定的整数值(第一个参数)和起始角度(第二个参数)以及跨度角度(第三个参数)绘制圆弧。
painter.drawArc(QtCore.QRectF, int, int): 这将使用参数中指定的浮点值(第一个参数)和起始角度(第二个参数)以及跨度角度(第三个参数)绘制圆弧。
painter.drawArc(x, y, w, h, int, int): 这将使用指定的参数绘制圆弧——一个以 x(x 轴)和 y(y 轴)开始的矩形;具有 w(宽度)和 h(高度);起始角度(第五个参数)和跨度角度(第六个参数)。
painter.drawChord(QtCore.QRect, int, int): 这将使用参数中指定的整数值(第一个参数),起始角度(第二个参数)和跨度角度(第三个参数)绘制圆弧。
painter.drawChord(QtCore.QRectF, int, int): 这将使用参数中指定的浮点值(第一个参数),起始角度(第二个参数)和跨度角度(第三个参数)绘制圆弧。
painter.drawChord(x, y, w, h, int, int): 这将使用指定的参数绘制圆弧——一个以 x(x 轴)和 y(y 轴)开始的矩形;具有 w(宽度)和 h(高度);起始角度(第五个参数)和跨度角度(第六个参数)。
painter.drawConvexPolygon(QtGui.QPolygon): 这将使用参数中指定的多边形绘制凸多边形。
painter.drawEllipse(QtCore.QRect): 这将使用参数中指定的整数值绘制定义的椭圆。
painter.drawEllipse(QtCore.QRectF): 这将使用参数中指定的浮点值绘制定义的椭圆。
painter.drawEllipse(QtCore.QPoint, int, int): 这将在中心位置以整数值(第一个参数)绘制椭圆,半径 x(第二个参数)和半径 y(第三个参数)。
painter.drawEllipse(QtCore.QPointF, int, int): 这将在中心位置以浮点值(第一个参数)绘制椭圆,半径 x(第二个参数)和半径 y(第三个参数)。
painter.drawEllipse(x, y, w, h): 这将在指定参数的椭圆上绘制——从 x(x 轴)和 y(y 轴)开始的矩形,宽度为 w,高度为 h。
painter.drawImage(QtCore.QRect, QtGui.QImage): 这将在具有整数值(第一个参数)的矩形中绘制第二个参数指定的图像。
painter.drawImage(QtCore.QRectF, QtGui.QImage): 这将在具有浮点值(第一个参数)的矩形中绘制第二个参数指定的图像。
painter.drawImage(QtCore.QPoint, QtGui.QImage): 这将在具有整数值(第一个参数)的点处绘制第二个参数指定的图像。
painter.drawImage(QtCore.QPointF, QtGui.QImage): 这将在具有浮点值(第一个参数)的点处绘制第二个参数指定的图像。
painter.drawImage(QtCore.QRect, QtGui.QImage, QtCore.QRect, QtCore.Qt.ImageConversionFlags): 这将在具有整数值(第三个参数)的图像(第二个参数)的矩形源上绘制矩形,该矩形位于具有整数值(第一个参数)的画布设备中的矩形内,并带有标志(第四个参数)。
painter.drawImage(QtCore.QPoint, QtGui.QImage, QtCore.QRect, QtCore.Qt.ImageConversionFlags): 这将在具有整数值(第三个参数)的图像(第二个参数)的矩形源上绘制浮点值(第一个参数)的点,并带有标志(第四个参数)。
painter.drawImage(QtCore.QPointF, QtGui.QImage, QtCore.QRectF, QtCore.Qt.ImageConversionFlags): 这将在具有浮点值(第三个参数)的图像(第二个参数)的矩形源上绘制浮点值(第一个参数)的点,并带有标志(第四个参数)。
painter.drawImage(QtCore.QRectF, QtGui.QImage, QtCore.QRectF, QtCore.Qt.ImageConversionFlags): 这将在具有浮点值(第三个参数)的图像(第二个参数)的矩形源上绘制矩形,该矩形位于具有浮点值(第一个参数)的画布设备中的矩形内,并带有标志(第四个参数)。
painter.drawImage(x, y, QtGui.QImage, tx, ly, w, h, QtCore.Qt.ImageConversionFlags): 这将在位置绘制图像(第二个参数),从 x(x 轴)和 y(y 轴)开始;在图像中具有 tx(顶部)和 ly(左侧)点,宽度为 w,高度为 h,并带有标志(第八个参数)的画布设备中。
painter.drawLine(QtCore.QLine): 这将绘制由参数中指定的具有整数值的线。
painter.drawLine(QtCore.QLineF): 这条语句根据参数中指定的具有浮点值的线绘制一条线。
painter.drawLine(QtCore.QPoint, QtCore.QPoint): 这条语句从具有整数值的点(第一个参数)绘制一条线到具有整数值的点(第二个参数)。
painter.drawLine(QtCore.QPointF, QtCore.QPointF): 这条语句从具有浮点值的点(第一个参数)绘制一条线到具有浮点值的点(第二个参数)。
painter.drawLine(x1, y1, x2, y2): 这条语句从 x1(x 轴)和 y1(y 轴)到 x2(x 轴)和 y2(y 轴)绘制一条线。
painter.drawLines([QtCore.QLine]): 这条语句绘制列表中指定的具有整数值的线。
painter.drawLines([QtCore.QLineF]): 这条语句绘制列表中指定的具有浮点值的线。
painter.drawPath(QtGui.QPainterPath): 这条语句绘制参数中指定的路径。
painter.drawPicture(QtCore.QPoint, QtGui.QPicture): 这条语句在具有整数值的点上绘制一个图片(第二个参数)。
painter.drawPicture(QtCore.QPointF, QtGui.QPicture): 这条语句在具有浮点值的点上绘制一个图片(第二个参数)。
painter.drawPicture(x, y, QPicture): 这条语句在由 x(x 轴)和 y(y 轴)指定的点上绘制一个图片(第三个参数)。
painter.drawPie(QtCore.QRect, int, int): 这条语句通过矩形(第一个参数)和整数值(起始角度的第二个参数和跨度角度的第三个参数)绘制一个饼图。
painter.drawPie(QtCore.QRectF, int, int): 这条语句通过具有浮点值的矩形(第一个参数)和起始角度(第二个参数)以及跨度角度(第三个参数)绘制一个饼图。
painter.drawPie(x, y, w, h, int, int): 这条语句使用指定的参数绘制一个饼图——一个从 x(x 轴)和 y(y 轴)开始的矩形;具有 w(宽度)和 h(高度);以及起始角度(第五个参数)和跨度角度(第六个参数)。
painter.drawPixmap(QtCore.QRect, QtGui.QPixmap): 这条语句在具有整数值的矩形内绘制一个位图(第二个参数)。
painter.drawPixmap(QtCore.QPoint, QtGui.QPixmap): 这条语句在具有整数值的点上绘制一个位图(第二个参数)。
painter.drawPixmap(QtCore.QPointF, QtGui.QPixmap): 这条语句在具有浮点值的点上绘制一个位图(第二个参数)。
painter.drawPixmap(QtCore.QRect, QtGui.QPixmap, QtCore.QRect): 这条语句在画布中绘制位图的矩形部分(第三个参数),该部分位于具有整数值的矩形(第一个参数)内。
painter.drawPixmap(QtCore.QRectF, QtGui.QPixmap, QtCore.QRectF): 这将在画布设备中,以浮点值(第三个参数)的矩形部分(第二个参数)在具有浮点值(第一个参数)的矩形中绘制位图。
painter.drawPixmap(QtCore.QPoint, QtGui.QPixmap, QtCore.QRect): 这将在画布设备中,以整数值(第三个参数)的矩形部分(第二个参数)在具有整数值(第一个参数)的点处绘制位图。
painter.drawPixmap(QtCore.QPointF, QtGui.QPixmap, QtCore.QRectF): 这将在画布设备中,以浮点值(第三个参数)的矩形部分(第二个参数)在具有浮点值(第一个参数)的点处绘制位图。
painter.drawPixmap(x, y, QtGui.QPixmap): 这将在根据 x(x 轴)和 y(y 轴)的位置开始绘制指定在第三个参数中的位图。
painter.drawPixmap(x, y, QtGui.QPixmap, tx, ly, w, h): 这将在指定参数的情况下绘制位图(第三个参数),从 x(x 轴)和 y(y 轴)开始;使用 tx(x-top)和 ly(y-left)点;大小为 w(宽度)和 h(高度)。
painter.drawPixmap(x, y, w, h, QtGui.QPixmap, tx, ly, pw, ph): 这将在指定参数的情况下绘制位图(第五个参数),从 x(x 轴)和 y(y 轴)开始;大小为 w(宽度)和 h(高度);使用 tx(x-top);ly(y-left);pw(宽度)和 ph(高度)。
painter.drawPixmap(x, y, w, h, QtGui.QPixmap): 这将在根据 x(x 轴)和 y(y 轴)的位置,大小为 w(宽度)和 h(高度)的矩形中绘制位图(第五个参数)。
painter.drawPixmapFragments([QtGui.QPainter.PixmapFragment], int, QtGui.QPixmap, QtGui.QPainter.PixmapFragmentHints): 这将在多个位置(片段)绘制位图(第三个参数),具有不同的缩放、旋转和透明度。片段(第一个参数)是用于绘制每个位图片段的片段计数(第二个参数)的元素数组,以及构成绘图提示的提示(第四个参数)。
painter.drawPoint(QtCore.QPoint): 这将在指定在点参数中的整数值位置绘制一个点。
painter.drawPointF(QtCore.QPoint): 这将在指定在点参数中的浮点值位置绘制一个点。
painter.drawPoint(x, y): 这将在指定 x(x 轴)和 y(y 轴)的位置绘制一个点。
painter.drawPoints(QtGui.QPolygon): 这将根据向量中的点以整数值绘制多边形。
painter.drawPoints(QtGui.QPolygonF): 这将根据向量中的点以浮点值绘制多边形。
painter.drawPolygon(QtGui.QPolygon, QtCore.Qt.FillRule): 这将根据多边形中指定的整数值点绘制多边形,并使用规则(第二个参数)。
painter.drawPolygon(QtGui.QPolygonF, QtCore.Qt.FillRule): 这将根据多边形中指定的浮点值点绘制多边形(第一个参数),并且有规则(第二个参数)。
painter.drawPolyline(QtGui.QPolygon, QtCore.Qt.FillRule): 这将根据多边形中指定的整数值点绘制折线。
painter.drawPolyline(QtGui.QPolygonF, QtCore.Qt.FillRule): 这将根据多边形中指定的浮点值点绘制折线。
painter.drawRect(QtCore.QRect): 这将绘制由整数值指定的参数指定的矩形。
painter.drawRect(QtCore.QRectF): 这将绘制由浮点值指定的参数指定的矩形。
painter.drawRect(x, y, w, h): 这将绘制从左上角开始,由 x(x 轴)和 y(y 轴)指定的矩形,宽度为 w,高度为 h。
painter.drawRects(QtCore.QRect, QtCore.QRect...): 这将绘制由整数值指定的参数指定的矩形。
painter.drawRects([QtCore.QRectF]): 这将绘制由浮点值指定的参数指定的矩形。
painter.drawRoundRect(QtCore.QRect, rx, ry): 这将绘制具有圆角的矩形,圆角的大小由 rx 和 ry(矩形的圆角)指定。
painter.drawRoundRect(QtCore.QRectF, rx, ry): 这将绘制具有圆角的矩形,圆角的大小由 rx 和 ry(矩形的圆角)指定,并且矩形的大小由浮点值指定(第一个参数)。
painter.drawRoundRect(x, y, w, h, rx, ry): 这将绘制具有圆角的矩形,圆角的大小由 rx 和 ry(矩形的圆角)指定,并且从 x(x 轴)和 y(y 轴)的起点开始;宽度为 w,高度为 h。
painter.drawRoundedRect(QtCore.QRect, rx, ry, QtCore.Qt.SizeMode): 这将绘制具有圆角的矩形,圆角的大小由 rx 和 ry(矩形的圆角)指定,并且有一个模式(第四个参数),矩形的大小由整数值指定(第一个参数)。
painter.drawRoundedRect(QtCore.QRectF, rx, ry, QtCore.Qt.SizeMode): 这将绘制具有圆角的矩形,圆角的大小由 rx 和 ry(矩形的圆角)指定,并且有一个模式(第四个参数),矩形的大小由浮点值指定(第一个参数)。
painter.drawRoundedRect(x, y, w, h, rx, ry, QtCore.Qt.SizeMode): 这将绘制具有圆角的矩形,圆角的大小由 rx 和 ry(矩形的圆角)指定,并且有一个模式(第七个参数),矩形的大小由参数指定,从点 x(X 轴)和 y(Y 轴)开始;宽度为 w,高度为 h。
painter.drawStaticText(QtCore.QPoint, QtGui.QStaticText): 这将在具有整数值(第一个参数)的点处绘制静态文本(第二个参数)。
painter.drawStaticText(QtCore.QPointF, QtGui.QStaticText): 这将在具有浮点值(第一个参数)的点绘制静态文本(第二个参数)。
painter.drawStaticText(int, int, QStaticText): 这将在左(第一个参数)和顶(第二个参数)坐标绘制静态文本(第三个参数)。
painter.drawText(QtCore.QRect, flags, str): 这将在提供的矩形内绘制文本(第三个参数),矩形由整数值(第一个参数)和标志(第二个参数)定义。可用的标志可以用 OR(|)组合,如下所示:
-
QtCore.Qt.AlignLeft: 左对齐。 -
QtCore.Qt.AlignRight: 右对齐。 -
QtCore.Qt.AlignHCenter: 水平居中对齐。 -
QtCore.Qt.AlignJustify: 段落对齐。 -
QtCore.Qt.AlignTop: 顶部对齐。 -
QtCore.Qt.AlignBottom: 底部对齐。 -
QtCore.Qt.AlignVCenter: 垂直居中对齐。 -
QtCore.Qt.AlignCenter: 居中对齐。 -
QtCore.Qt.TextDontClip: 文本不会裁剪。 -
QtCore.Qt.TextSingleLine: 文本单行。 -
QtCore.Qt.TextExpandTabs: 这使得 ASCII 制表符移动到下一个停止位置。 -
QtCore.Qt.TextShowMnemonic: 显示如"&P"之类的字符串为P。 -
QtCore.Qt.TextWordWrap: 按单词换行。 -
QtCore.Qt.TextIncludeTrailingSpaces: 如果使用此选项,naturalTextWidth()和naturalTextRect()将返回一个包含文本末尾空格宽度的值;否则,它将被排除。
painter.drawText(QtCore.QRectF, flags, str): 这将在提供的矩形内绘制文本(第三个参数),矩形由浮点值(第一个参数)和标志(第二个参数)定义。
painter.drawText(x, y, str): 这将在根据x(x轴)和y(y轴)的位置绘制文本(第三个参数)。
painter.drawText(x, y, w, h, flags, str): 这将在根据x(x轴)和y(y轴)的位置绘制文本(第六个参数),以及w(宽度)和h(高度)和标志(第五个参数)。
painter.drawText(QtCore.QRectF, str, QtGui.QTextOption): 这将在具有浮点值(第一个参数)的矩形内绘制文本(第二个参数),并带有文本选项(第三个参数)。
painter.drawText(QtCore.QPoint, str): 这将在具有整数值(第一个参数)的点绘制文本(第二个参数)。
painter.drawText(QtCore.QPointF, str): 这将在具有浮点值(第一个参数)的点绘制文本(第二个参数)。
painter.drawTextItem(QtCore.QPoint, QtGui.QTextItem): 这将在具有整数值(第一个参数)的点绘制文本项(第二个参数)。
painter.drawTextItem(QtCore.QPointF, QtGui.QTextItem): 这将在具有浮点值(第一个参数)的点绘制文本项(第二个参数)。
painter.drawTextItem(x, y, QtGui.QTextItem): 这将在根据x(x轴)和y(y轴)的位置绘制文本项(第三个参数)。
painter.drawTiledPixmap(QtCore.QRect, QtGui.QPixmap, QtCore.QPoint): 这将在具有整数值的矩形(第一个参数)中绘制平铺的位图(第二个参数),从具有整数值的点(第三个参数)开始。
painter.drawTiledPixmap(QtCore.QRectF, QtGui.QPixmap, QtCore.QPointF): 这将在具有浮点值的矩形(第一个参数)中绘制平铺的位图(第二个参数),从具有浮点值的点(第三个参数)开始。
painter.drawTiledPixmap(x, y, w, h, QtGui.QPixmap, tx, ly): 这将在指定的矩形中绘制平铺的位图(第五个参数),从 x(x 轴)和 y(y 轴)开始;宽度为 w,高度为 h;并且以位图中的 tx(顶部)和 ly(左侧)点为起点。
fill
这些是与使用此画家填充相关的函数:
painter.fillPath(QtGui.QPainterPath, QtGui.QBrush): 这将使用画笔(第二个参数)填充第一个参数指定的路径。
painter.fillRect(QtCore.QRect, QtCore.Qt.GlobalColor): 这将使用第二个参数指定的颜色填充由整数值表示的矩形(第一个参数)。
painter.fillRect(QtCore.QRectF, QtCore.Qt.GlobalColor): 这将使用第二个参数指定的颜色填充由浮点值表示的矩形(第一个参数)。
painter.fillRect(QtCore.QRect, QtGui.QColor): 这将使用第二个参数指定的颜色填充由整数值表示的矩形(第一个参数)。
painter.fillRect(QtCore.QRectF, QtGui.QColor): 这将使用第二个参数指定的颜色填充由浮点值表示的矩形(第一个参数)。
painter.fillRect(QtCore.QRect, QtGui.QBrush): 这将使用第二个参数指定的画笔填充由整数值表示的矩形(第一个参数)。
painter.fillRect(QtCore.QRectF, QtGui.QBrush): 这将使用第二个参数指定的画笔填充由浮点值表示的矩形(第一个参数)。
painter.fillRect(QtCore.QRect, QtGui.QGradient.Preset): 这将使用第二个参数指定的预设渐变填充由整数值表示的矩形(第一个参数)。
painter.fillRect(QtCore.QRectF, QtGui.QGradient.Preset): 这将使用第二个参数指定的预设渐变填充由浮点值表示的矩形(第一个参数)。
painter.fillRect(QtCore.QRect, QtCore.Qt.BrushStyle): 这将使用第二个参数指定的画笔样式填充由整数值表示的矩形(第一个参数)。
painter.fillRect(QtCore.QRectF, QtCore.Qt.BrushStyle): 这将使用第二个参数指定的画笔样式填充由浮点值表示的矩形(第一个参数)。
painter.fillRect(x, y, w, h, QtGui.QGradient.Preset):这用指定的预设渐变填充矩形,从x(x轴)和y(y轴)开始;使用w(宽度)和h(高度),在第五个参数指定的预设渐变中。
painter.fillRect(x, y, w, h, QtCore.Qt.BrushStyle):这用指定的画刷样式填充矩形,从x(x轴)和y(y轴)开始;使用w(宽度)和h(高度),在第五个参数指定的画刷样式中。
painter.fillRect(x, y, w, h, QtGui.QColor):这用指定的颜色填充矩形,从x(x轴)和y(y轴)开始;使用w(宽度)和h(高度),在第五个参数指定的颜色中。
painter.fillRect(x, y, w, h, QtGui.QBrush):这用指定的画刷填充矩形,从x(x轴)和y(y轴)开始;使用w(宽度)和h(高度),在第五个参数指定的画刷中。
painter.fillRect(x, y, w, h, QtCore.Qt.GlobalColor):这用指定的颜色填充矩形,从x(x轴)和y(y轴)开始;使用w(宽度)和h(高度),在第五个参数指定的颜色中。
QPen
此类通过QPainter类提供了绘制形状和线条轮廓的方法。笔的声明如下:
pen = QtGui.QPen()
QPen类通过以下函数提高了功能。
set
这些是设置笔的参数和属性的函数:
pen.setBrush(QtGui.QBrush):这设置了参数中指定的画刷,该画刷将用于填充线条。
pen.setCapStyle(QtCore.Qt.PenCapStyle):这设置了笔的帽样式为参数中指定的样式。可用的样式有QtCore.Qt.SquareCap、QtCore.Qt.FlatCap和QtCore.Qt.RoundCap。
pen.setColor(QtGui.QColor):这设置了此笔的画刷颜色为参数中指定的颜色。
pen.setCosmetic(bool):如果参数为True,则将此笔设置为装饰性。装饰性笔以恒定宽度绘制线条,不受任何变换的影响。用装饰性笔绘制的形状将确保轮廓具有相同的厚度。
pen.setDashOffset(float):这设置了参数中指定的虚线偏移。
pen.setDashPattern([float]):这设置了参数中指定的虚线模式,作为浮点值的可迭代对象,必须是[1.0, 2.0, 3.0, 4.0],其中1.0和3.0是虚线,2.0和4.0是空格。
pen.setJoinStyle(QtCore.Qt.PenJoinStyle):这设置了笔的连接样式为参数中指定的样式。可用的样式有QtCore.Qt.BevelJoin、QtCore.Qt.MiterJoin和QtCore.Qt.RoundJoin。
pen.setMiterLimit(float):这设置了笔的斜接限制。
pen.setStyle(QtCore.Qt.PenStyle):这设置了此笔的样式。可用的样式如下:
-
QtCore.Qt.SolidLine:实线。 -
QtCore.Qt.DashLine:分离的虚线。 -
QtCore.Qt.DotLine:分离的点。 -
QtCore.Qt.DashDotLine:点划线。 -
QtCore.Qt.DashDotDotLine: 一个破折号,两个点,一个破折号,两个点。 -
QtCore.Qt.CustomDashLine: 将是使用setDashPattern()定义的定制模式。 -
QtCore.Qt.NoPen: 无线条。
pen.setWidth(int): 这将参数中指定的宽度作为整数值设置,并用作画笔的宽度。
pen.setWidth(float): 这将参数中指定的宽度作为浮点值设置,并用作画笔的宽度。
是
这些是与画笔相关的函数,返回一个布尔值(bool):
pen.isCosmetic(): 如果此画笔是装饰性的,则返回 True。
pen.isSolid(): 如果这是一个实心填充画笔,则返回 True。
功能性
这些是与当前画笔值的返回值相关的函数:
pen.brush(): 这返回 QtGui.QBrush 类型的画笔,并用于填充线条。
pen.capStyle(): 这返回与画笔一起使用的 QtCore.Qt.PenCapStyle 类型的端点样式。
pen.color(): 这返回与画笔的刷子一起使用的 QtGui.QColor 类型的颜色。
pen.dashOffset(): 这返回画笔的虚线偏移量。
pen.dashPattern(): 这返回画笔的虚线模式。
pen.joinStyle(): 这返回 QtCore.Qt.PenJoinStyle 类型的连接样式,如与该画笔一起使用。
pen.miterLimit(): 这返回画笔的斜接限制。
pen.style(): 这返回此画笔的样式。
pen.swap(QtGui.QPen): 这将参数中指定的画笔与此画笔交换。
pen.width(): 这返回此画笔的宽度作为整数值。
pen.widthF(): 这返回此画笔的宽度作为浮点值。
QBrush
画笔描述了使用 QPainter 类绘制的形状的填充模式。画笔的声明如下:
brush = QtGui.QBrush()
QBrush 类通过以下函数提高了功能性。
设置
这些是与设置画笔相关参数和属性的函数:
brush.setColor(QtGui.QColor): 这将设置参数中指定的此画笔的颜色。
brush.setColor(QtCore.Qt.GlobalColor): 这将设置此画笔参数中指定的全局颜色。
brush.setStyle(QtCore.Qt.BrushStyle): 这将设置参数中指定的此画笔的样式。可用的画笔样式如下:
-
QtCore.Qt.NoBrush—0: 无画笔。 -
QtCore.Qt.SolidPattern—1: 均匀画笔。 -
QtCore.Qt.Dense1Pattern—2: 非常密集的画笔。 -
QtCore.Qt.Dense2Pattern—3: 非常密集的画笔。 -
QtCore.Qt.Dense3Pattern—4: 有点密集的画笔。 -
QtCore.Qt.Dense4Pattern—5: 半密集的画笔。 -
QtCore.Qt.Dense5Pattern—6: 有点稀疏的画笔。 -
QtCore.Qt.Dense6Pattern—7: 非常稀疏的画笔。 -
QtCore.Qt.Dense7Pattern—8: 非常稀疏的画笔。 -
QtCore.Qt.HorPattern—9: 水平。 -
QtCore.Qt.VerPattern—10: 垂直。 -
QtCore.Qt.CrossPattern—11: 横向/纵向交叉。 -
QtCore.Qt.BDiagPattern—12: 反向对角。 -
QtCore.Qt.FDiagPattern—13: 正向对角。 -
QtCore.Qt.DiagCrossPattern—14: 对角交叉。 -
QtCore.Qt.LinearGradientPattern—15: 线性渐变画笔。 -
QtCore.Qt.RadialGradientPattern—16: 径向渐变画笔。 -
QtCore.Qt.ConicalGradientPattern—17: 锥形渐变画笔。 -
QtCore.Qt.TexturePattern—24: 自定义。
brush.setTexture(QtGui.QPixmap): 这将参数中指定的位图设置为画笔位图。
brush.setTextureImage(QtGui.QImage): 这将参数中指定的图像设置为画笔图像。
brush.setTransform(QtGui.QTransform): 这将参数中指定的矩阵作为显式变换矩阵设置在画笔上。
是
此函数返回与画笔相关的布尔值 (bool):
brush.isOpaque(): 如果画笔完全不透明,则返回 True。
功能性
这些是与画笔当前值返回相关的函数:
brush.color(): 这返回与该画笔一起使用的 QtGui.QColor 类型的颜色。
brush.gradient(): 这返回与该画笔一起使用的 QtGui.QGradient 类型的渐变。
brush.style(): 这返回与该画笔一起使用的 QtCore.Qt.BrushStyle 类型的样式。
brush.swap(QtGui.QBrush): 这将此画笔与参数中指定的画笔交换。
brush.texture(): 这返回 QtGui.QPixmap 类型的自定义画笔图案。
brush.textureImage(): 这返回 QtGui.QImage 类型的自定义画笔图案。
brush.transform(): 这返回与该画笔一起使用的 QtGui.QTransform 类型的当前变换矩阵。
QGradient
此类与 QBrush 风格一起使用,用于在图形创建中实现简单的渐变。声明语法如下:
gradient = QtGui.QGradient()
QGradient 类通过以下函数提高功能。
设置
这些是与设置与渐变相关的参数和属性相关的函数:
gradient.setColorAt(float, QtGui.QColor): 这在第一个参数指定的位置创建一个停止点(0.0–1.0),第二个参数指定颜色。
gradient.setCoordinateMode(QtGui.QGradient.CoordinateMode): 这设置此渐变的参数中指定的坐标模式。可用的参数如下:
-
QtGui.QGradient.LogicalMode—0: 坐标在逻辑空间中指定。 -
QtGui.QGradient.StretchToDeviceMode—1: 坐标相对于绘图设备的矩形。 -
QtGui.QGradient.ObjectMode—3: 坐标相对于对象的矩形。
gradient.setSpread(QtGui.QGradient.Spread): 这设置此渐变的参数中指定的扩散方法。可用的扩散方法如下:
-
QtGui.QGradient.PadSpread—0: 用最接近的停止颜色填充。 -
QtGui.QGradient.ReflectSpread—1: 在渐变区域外反射。 -
QtGui.QGradient.RepeatSpread—2: 在渐变区域外重复。
gradient.setStops([float]): 这用参数中指定的停止点替换当前设置的停止点。点必须按从最低点开始的顺序排序,并且在 0.0 到 1.0 的范围内。
functional
这些是与梯度当前值返回相关的函数:
gradient.coordinateMode(): 这返回梯度坐标模式,类型为 QtGui.QGradient.CoordinateMode。
gradient.spread(): 这返回与该梯度一起使用的 QtGui.QGradient.Spread 类型的扩散方法。
gradient.stops(): 这返回与该梯度一起使用的停止点。
gradient.type(): 这返回梯度类型。类型如下:
-
QtGui.QGradient.LinearGradient—0: 起点和终点之间的色彩。 -
QtGui.QGradient.RadialGradient—1: 点与其终点之间的色彩。 -
QtGui.QGradient.ConicalGradient—2: 中心周围的色彩。 -
QtGui.QGradient.NoGradient—3: 无渐变。
QLinearGradient
这是 QGradient 类的子类,表示在起点和终点之间填充颜色的线性梯度。声明如下:
linear_gradient = QtGui.QLinearGradient()
QLinearGradient 从 QGradient 类继承,并通过以下函数改进了功能。
set
这些是与设置与线性梯度相关的参数和属性相关的函数:
linear_gradient.setFinalStop(QtCore.QPointF): 这使用参数中指定的浮点值在逻辑坐标中设置线性梯度的最终停止点。
linear_gradient.setFinalStop(x, y): 这根据线性梯度在逻辑坐标中的x (x 轴) 和 y (y 轴) 位置,使用浮点值设置最终停止点。
linear_gradient.setStart(QtCore.QPointF): 这使用参数中指定的浮点值在逻辑坐标中设置线性梯度的起点。
linear_gradient.setStart(x, y): 这根据线性梯度在逻辑坐标中的x (x 轴) 和 y (y 轴) 位置,使用浮点值设置起点。
functional
这些是与线性梯度当前值返回相关的函数:
linear_gradient.finalStop(): 这返回线性梯度的最终停止点,类型为 QtCore.QPointF,在逻辑坐标中。
linear_gradient.start(): 这返回线性梯度的起点,类型为 QtCore.QPointF,在逻辑坐标中。
QRadialGradient
这是 QGradient 类的子类,表示在焦点和其端点之间填充颜色的径向梯度。声明如下:
radial_gradient = QtGui.QRadialGradient()
QRadialGradient 从 QGradient 类继承,并通过以下函数改进了功能。
set
这些是与设置与径向梯度相关的参数和属性相关的函数:
radial_gradient.setCenter(QtCore.QPointF): 这将使用参数中指定的浮点值设置中心点,在逻辑坐标中,对于这个径向渐变。
radial_gradient.setCenter(x, y): 这将根据逻辑坐标中的x(x轴)和y(y轴)位置,使用浮点值设置中心点。
radial_gradient.setCenterRadius(float): 这将设置中心半径,在逻辑坐标中,对于这个径向渐变。
radial_gradient.setFocalPoint(QtCore.QPointF): 这将使用参数中指定的浮点值设置焦点,在逻辑坐标中,对于这个径向渐变。
radial_gradient.setFocalPoint(x, y): 这将使用浮点值在x(x轴)和y(y轴)位置设置焦点,在逻辑坐标中,对于这个径向渐变。
radial_gradient.setFocalRadius(float): 这将设置参数中指定的焦点半径,在逻辑坐标中,对于这个径向渐变。
radial_gradient.setRadius(float): 这将设置参数中指定的半径,在逻辑坐标中,对于这个径向渐变。
functional
这些是与径向渐变当前值返回相关的函数:
radial_gradient.center(): 这返回QtCore.QPointF类型的中心,在逻辑坐标中,对于这个径向渐变。
radial_gradient.centerRadius(): 这返回中心半径作为一个浮点值,在逻辑坐标中,对于这个径向渐变。
radial_gradient.focalPoint(): 这返回QtCore.QPointF类型的焦点,在逻辑坐标中,对于这个径向渐变。
radial_gradient.focalRadius(): 这返回焦点半径作为一个浮点值,在逻辑坐标中,对于这个径向渐变。
radial_gradient.radius(): 这返回半径作为一个浮点值,在逻辑坐标中,对于这个径向渐变。
QConicalGradient
这是一个QGradient类的子类,表示围绕中心点填充颜色的锥形渐变。声明如下:
conical_gradient = QtGui.QConicalGradient()
QConicalGradient从QGradient类继承,并通过以下函数增强了功能。
set
这些是与设置锥形渐变参数和属性相关的函数:
conical_gradient.setAngle(float): 这将设置参数中指定的起始角度,在逻辑坐标中,对于这个锥形渐变。
conical_gradient.setCenter(QtCore.QPointF): 这将使用参数中指定的浮点值设置中心点,在逻辑坐标中,对于这个锥形渐变。
conical_gradient.setCenter(x, y): 这将根据逻辑坐标中的x(x轴)和y(y 轴)位置,使用浮点值设置中心点,对于这个锥形渐变。
functional
这些是与锥形渐变当前值返回相关的函数:
conical_gradient.angle(): 这返回此圆锥渐变的起始角度,作为逻辑坐标中的浮点值。
conical_gradient.center(): 这返回此圆锥渐变的 QtCore.QPointF 类型的中心,在逻辑坐标中。
图片
Qt 库提供了一套完整的类,用于处理不同类型的图像。所有最流行的图像处理格式都得到了支持。主要格式在此描述。
QPicture
此类表示重放和记录 QPainter 类命令的绘图设备。使用此类,可以将 QPainter 的绘图命令序列化为平台无关的格式,并作为图片表示。这用于保存绘图图片和加载它。图片将以类似于 filename.pic 的名称保存到文件中,以供以后使用。此类的声明如下:
picture = QtGui.QPicture()
QPicture 类继承自 QPaintDevice 类,并通过以下函数增强了功能。
设置
这些是与图片相关的设置参数和属性的函数:
picture.setBoundingRect(QtCore.QRect): 这为此图片设置参数中指定的边界矩形。
picture.setData(bytes): 这将从参数中指定的数据设置此图片的数据。它还会复制输入数据。
是
此函数返回与图片相关的布尔值 (bool):
picture.isNull(): 如果此图片不包含任何数据,则返回 True。
功能
这些是与当前图片值的返回或功能仪器相关的函数:
picture.boundingRect(): 这返回此图片的 QtCore.QRect 类型的边界矩形。
picture.data(): 这返回指向此图片数据的指针。
picture.inputFormats(): 这返回支持图片输入的格式列表。
picture.load(r"/Path/To/filename.pic"): 这从参数中指定的文件加载图片,如果成功则返回 True。
picture.outputFormats(): 这返回支持图片输出的格式列表。
picture.pictureFormat(r"/Path/To/filename.pic"): 这返回参数中指定的图片的格式。
picture.play(QtGui.QPainter): 这使用参数中指定的画家重放图片,如果成功则返回 True。
picture.save(r"/Path/To/filename.pic"): 这将保存创建的图片到参数中指定的文件,如果成功则返回 True。
picture.size(): 这返回图片的数据大小。
picture.swap(QtGui.QPicture): 这与此参数指定的图片交换。
QPixmap
QPixmap 类提供了一种处理像素映射数据的方法。位图允许像素为任何颜色。它是图像的离屏表示,可用于直接访问和操作像素。此类的声明如下:
pixmap = QtGui.QPixmap()
QPixmap 从 QPaintDevice 类继承,并通过以下函数改进了功能。
set
这些是与设置与位图相关的参数和属性相关的函数:
-
pixmap.setDevicePixelRatio(float): 这将指定参数中指定的设备像素比率应用于此位图。它表示位图像素与设备无关像素之间的比率。 -
pixmap.setMask(QtGui.QBitmap): 这设置参数中指定的掩码位图。
is/has
这些是与位图状态相关的返回布尔值(bool)的函数:
pixmap.hasAlpha(): 如果它为此位图具有 alpha 通道或掩码,则返回 True。
pixmap.hasAlphaChannel(): 如果它为此位图具有尊重 alpha 通道的格式,则返回 True。
pixmap.isNull(): 如果此位图是 null(无数据),则返回 True。
pixmap.isQBitmap(): 如果这是一个 QtGui.QBitmap 类型,则返回 True。
functional
这些是与位图当前值或功能仪器相关的函数:
pixmap.cacheKey(): 这返回作为此位图标识符的键。
pixmap.convertFromImage(QtGui.QImage, QtCore.Qt.ImageConversionFlags): 这用标志(第二个参数)中指定的转换替换图像(第一个参数)的位图数据。可用的转换标志有 QtCore.Qt.AutoColor、QtCore.Qt.ColorOnly 和 QtCore.Qt.MonoOnly(单色)。
pixmap.copy(QtCore.QRect): 这返回指定参数中矩形的 QtGui.QPixmap 类型位图子集的深度副本。
pixmap.copy(x, y, w, h): 这返回指定矩形的 QtGui.QPixmap 类型位图子集的深度副本,从 x(x 轴)和 y(y 轴)开始;具有 w(宽度)和 h(高度)。
pixmap.createHeuristicMask(bool): 如果此参数为 True,则为此位图创建 QtGui.QBitmap 类型的启发式掩码。
pixmap.createMaskFromColor(QtGui.QColor, QtCore.Qt.MaskMode): 这为此位图创建并返回 QtGui.QBitmap 类型的掩码。掩码将基于颜色(第一个参数)并相对于掩码模式(第二个参数)。
pixmap.defaultDepth(): 这返回此应用程序默认使用的位图深度。
pixmap.depth(): 这返回位图的深度(每像素位数(bpp)或位平面)。
pixmap.detach(): 这将此位图从此位图的共享数据中分离出来。
pixmap.devicePixelRatio(): 这返回设备像素与设备无关像素之间的比率。
pixmap.fill(QtGui.QColor): 这用参数中指定的颜色填充此位图。
pixmap.fromImage(QtGui.QImage, QtCore.Qt.ImageConversionFlags): 这使用标志(第二个参数)将图像(第一个参数)转换为位图。
pixmap.fromImageReader(QtGui.QImageReader, QtCore.Qt.ImageConversionFlags): 这直接使用标志(第二个参数)从图像读取器(第一个参数)创建位图。
pixmap.load(r"/Path/To/filename.png", str, QtCore.Qt.ImageConversionFlags): 这从文件(第一个参数)加载位图,使用格式(第二个参数)和标志(第三个参数)。
pixmap.loadFromData(QtCore.QByteArray, str, QtCore.Qt.ImageConversionFlags): 这从二进制数据(第一个参数)加载位图,使用格式(第二个参数)和标志(第三个参数)。
pixmap.mask(): 这从位图的 alpha 通道中提取位图遮罩。
pixmap.rect(): 这返回此位图的包围矩形。
pixmap.save(r"/Path/To/filename.png", str, int): 这将位图保存到文件(第一个参数),使用格式(第二个参数)和品质因子(第三个参数)。品质因子必须在0到100之间,或者为-1(默认设置)。
pixmap.scaled(QtCore.QSize, QtCore.Qt.AspectRatioMode, QtCore.Qt.TransformationMode): 这将此位图缩放到指定的大小(第一个参数),保持宽高比(第二个参数)和变换模式(第三个参数)。
pixmap.scaled(w, h, QtCore.Qt.AspectRatioMode, QtCore.Qt.TransformationMode): 这将此位图缩放到具有w(宽度)和h(高度)的矩形,并带有宽高比(第二个参数)和变换模式(第三个参数)。
pixmap.scaledToHeight(h, QtCore.Qt.TransformationMode): 这根据h(高度)缩放此位图,并带有变换模式(第二个参数)。
pixmap.scaledToWidth(w, QtCore.Qt.TransformationMode): 这根据w(宽度)缩放此位图,并带有变换模式(第二个参数)。
pixmap.scroll(dx, dy, QtCore.QRect, QtGui.QRegion): 这根据dx和dy整数值滚动此位图的矩形区域(第三个参数)。暴露的区域(第四个参数)保持不变。
pixmap.scroll(dx, dy, x, y, w, h, QtGui.QRegion): 这根据dx和dy整数值滚动指定矩形的区域,从x(x轴)和y(y轴)开始;w(宽度)和h(高度)为此位图的大小。暴露的区域(第四个参数)保持不变。
pixmap.size(): 这返回位图的大小。
pixmap.swap(QtGui.QPixmap): 这与此参数指定的位图交换此位图。
pixmap.toImage(): 这将位图转换为QtGui.QImage类型的图像。
pixmap.transformed(QtGui.QTransform, QtCore.Qt.TransformationMode): 这返回使用变换(第一个参数)和变换模式(第二个参数)转换后的位图副本。原始位图将不会改变。
pixmap.trueMatrix(QtGui.QTransform, w, h): 这返回用于转换此位图的实际矩阵,以及矩阵(第一个参数)和 w(宽度)和 h(高度)。
QBitmap
QBitmap 类提供了一种处理单色或 1 位深度像素映射数据的方法。它是一个离屏绘图设备,用于创建自定义光标和画笔,以及构建诸如 QRegion、位图和小部件的掩码等对象。此类的声明如下:
bitmap = QtGui.QBitmap()
QBitmap 从 QPixmap 类继承,并通过以下函数改进了功能。
functional
这些是与当前位图值的返回或与功能仪器相关的函数。
bitmap.clear(): 这将清除此位图并将所有位设置为 Qt.color0,或零像素值。
bitmap.fromData(QtCore.QSize, bytes, QtGui.QImage.Format): 这使用大小(第一个参数)构建此位图,并将内容设置为位(第二个参数),字节对齐,按位顺序(第三个参数)。
bitmap.swap(QtGui.QBitmap): 这将此位图与参数中指定的位图交换。
bitmap.transformed(QtGui.QTransform): 这返回使用参数中指定的变换转换后的位图副本。
QImage
此类提供硬件无关的图像表示,用于处理图像。它还允许直接访问像素数据。QImage 类的声明如下:
image = QtGui.QImage()
QImage 从 QPaintDevice 类继承,并通过以下函数改进了功能。
set
这些是与设置与图像相关的参数和属性相关的函数。
image.setAlphaChannel(QtGui.QImage): 这将此图像的 alpha 通道设置为参数中指定的一个。
image.setColor(int, int): 这会将颜色表中的索引(第一个参数)设置为颜色值(第二个参数)。
image.setColorCount(int): 这会将颜色表计数调整为参数中指定的值。
image.setColorTable([int]): 这会将颜色表设置为参数中指定的颜色。
image.setDevicePixelRatio(float): 这将为该图像设置参数中指定的设备像素比。这是图像像素与设备无关像素之间的比率。
image.setDotsPerMeterX(int): 这将设置物理米中由 x 轴定位的像素数量。这将描述此图像的缩放和宽高比。
image.setDotsPerMeterY(int): 这设置由 y 轴在物理米中定位的像素数。这将描述此图像的缩放和宽高比。
image.setOffset(QtCore.QPoint): 这设置相对于其他图像,图像偏移的像素数,到参数指定的点。
image.setPixel(QtCore.QPoint, int): 这在点(第一个参数)处设置第二个参数指定的像素索引或颜色。
image.setPixel(x, y, int): 这将在坐标 x 和 y 处设置第三参数指定的像素索引或颜色。
image.setPixelColor(QtCore.QPoint, QtGui.QColor): 这将点(第一个参数)处的像素设置为颜色(第二个参数)。
image.setPixel(x, y, QtGui.QColor): 这将坐标 x 和 y 处的像素设置为颜色(第三个参数)。
image.setText(str, str): 这设置图像(第二个参数)的文本,并将其与键(第一个参数)关联。
has and is
这些是返回与图像状态相关的布尔值 (bool) 的函数:
image.hasAlphaChannel(): 如果它具有尊重此图像的 alpha 通道的格式,则返回 True。
image.isGrayscale(): 如果此图像中的所有颜色都是灰色阴影,则返回 True。
image.isNull(): 如果此图像为 null(无数据),则返回 True。
functional
这些是与图像当前值或功能仪器相关的函数:
image.allGray(): 如果此图像中的所有颜色都是灰色阴影,则返回 True。
image.bitPlaneCount(): 这返回图像位平面的数量——每个像素的颜色和透明度的位数。
image.byteCount(): 这返回此图像数据占用的字节数。
image.bytesPerLine(): 这返回每图像扫描行的字节数。
image.cacheKey(): 这返回作为此图像内容标识符的键。
image.color(int): 这返回颜色表在参数指定的索引处的颜色。索引从 0 开始。
image.colorTable(): 这返回此图像颜色表中的颜色列表。
image.constBits(): 这返回指向第一个像素数据的指针。
image.constScanLine(int): 这返回指向参数指定的索引处的扫描行像素数据的指针。索引从 0 开始。
image.convertToFormat(QtGui.QImage.Format, [int], QtCore.Qt.ImageConversionFlags): 这返回一个图像副本,该图像已转换为格式(第一个参数),使用颜色表(第二个参数)和标志(第三个参数)。
image.copy(QtCore.QRect): 这返回一个由参数中指定的矩形大小的图像子区域。
image.copy(x, y, w, h): 这返回从指定矩形开始复制(以 x(x 轴)和 y(y 轴)为起点)的图像,宽度为 w,高度为 h。
image.createAlphaMask(QtCore.Qt.ImageConversionFlags): 这从图像中的 alpha 缓冲区创建并返回一个每像素 1 位的掩码。
image.createHeuristicMask(bool): 这为图像创建并返回一个每像素 1 位的掩码。如果参数为 True,则掩码足以覆盖像素;否则,掩码大于数据像素。
image.createMaskFromColor(int, QtCore.Qt.MaskMode): 这根据颜色(第一个值)和模式(第二个参数)创建并返回掩码。
image.depth(): 这返回图像的深度(bpp)。
image.devicePixelRatio(): 这返回设备像素和设备无关像素之间的比率。
image.dotsPerMeterX(): 这返回在物理米中由 X 轴定位的像素数量。这描述了此图像的缩放和宽高比。
image.dotsPerMeterY(): 这返回在物理米中由 Y 轴定位的像素数量。这描述了此图像的缩放和宽高比。
image.fill(QtCore.Qt.GlobalColor): 这用参数中指定的颜色填充此图像。
image.fill(QtGui.QColor): 这用参数中指定的颜色填充此图像。
image.fill(int): 这用参数中指定的像素值填充此图像。
image.format(): 这返回此图像的 QtGui.QImage.Format 类型的格式。
image.fromData(bytes, str): 这从 QtCore.QByteArray 数据中加载此图像。
image.invertPixels(QtGui.QImage.InvertMode): 这通过使用参数中指定的模式反转此图像的所有像素值。
image.load(r"/Path/To/filename.png", str): 这以格式(第二个参数)从文件(第一个参数)中加载图像。
image.load(QtCore.QIODevice, str): 这以格式(第二个参数)从设备(第一个参数)中读取图像。
image.loadFromData(bytes, str): 这从字节(第一个参数)中加载图像,格式(第二个参数)。
image.mirrored(bool, bool): 这返回图像的镜像;如果第一个参数为 True,则镜像方向为水平,如果第二个参数为 True,则镜像方向为垂直。
image.offset(): 这返回相对于其他图像要偏移的像素数。
image.pixel(QtCore.QPoint): 这返回位于参数中指定点处的像素。
image.pixel(x, y): 这返回了位于 x 和 y 坐标处的像素。
image.pixelColor(QtCore.QPoint): 这返回位于参数中指定点处的像素颜色。
image.pixelColor(x, y): 这返回了位于 x 和 y 坐标处的像素颜色。
image.pixelFormat(): 这返回了作为此图像的 QtGui.QPixelFormat 格式。
image.pixelIndex(QtCore.QPoint): 这返回了位于参数中指定点位置的像素索引。
image.pixelIndex(x, y): 这将返回x和y坐标处的像素索引。
image.rect(): 这将返回包围此图像的QtCore.QRect类型的矩形。
image.reinterpretAsFormat(QtGui.QImage.Format): 这将图像的格式更改为参数中指定的格式;数据将不会改变。
image.rgbSwapped(): 这将返回所有像素的红色和蓝色分量交换后的图像。
image.save(r"/Path/To/filename.png", str, int): 这将图像保存到文件(第一个参数),格式(第二个参数)和品质因子(第三个参数)。品质因子必须在0(小,压缩)到100(大,未压缩)或-1(默认设置)的范围内。
image.scaled(QtCore.QSize, QtCore.Qt.AspectRatioMode, QtCore.Qt.TransformationMode): 这将返回一个副本,该副本按大小(第一个参数)缩放,并带有纵横比(第二个参数)和变换模式(第三个参数)。
image.scaled(w, h, QtCore.Qt.AspectRatioMode, QtCore.Qt.TransformationMode): 这将返回一个副本,该副本按w(宽度)和h(高度)缩放,并带有纵横比(第二个参数)和变换模式(第三个参数)。
image.scaledToHeight(h, QtCore.Qt.TransformationMode): 这将返回一个副本,该副本相对于h(高度)缩放,并带有变换模式(第二个参数)。
image.scaledToWidth(w, QtCore.Qt.TransformationMode): 这将返回一个副本,该副本相对于w(宽度)缩放,并带有变换模式(第二个参数)。
image.size(): 这将返回此图像的大小。
image.sizeInBytes(): 这将返回图像数据的大小(以字节为单位)。
image.smoothScaled(w, h): 这将返回一个图像副本,该图像经过平滑缩放,其大小为w(宽度)和h(高度)。
image.swap(QtGui.QImage): 这将与此参数指定的图像交换此图像。
image.text(str): 这将返回与参数中指定的键关联的图像文本。
image.textKeys(): 这将返回此图像文本的键列表。
image.toImageFormat(QtGui.QPixelFormat): 这将参数中指定的格式转换为QtGui.QImage.Format类型。
image.toPixelFormat(QtGui.QImage.Format): 这将参数中指定的格式转换为QtGui.QPixelFormat类型。
image.transformed(QtGui.QTransform, QtCore.Qt.TransformationMode): 这将返回一个经过变换的图像副本,使用变换(第一个参数)和变换模式(第二个参数)。
image.trueMatrix(QtGui.QTransform, w, h): 这将返回用于使用矩阵(第一个参数)和w(宽度)以及h(高度)变换此图像的实际矩阵。
image.valid(QPoint): 如果参数中指定的点在此图像中是有效的坐标,则返回True。
image.valid(x, y): 如果指定为坐标x和y的点在此图像中是有效坐标,则返回True。
QIcon
此类实现了 GUI 应用程序中的可缩放图标。这些可以与小部件、按钮或作为窗口图标一起使用。图标的声明语法如下:
icon = QtGui.QIcon()
QIcon通过以下函数提高功能。
add
这些是与图标添加相关的函数:
icon.addFile(r"/Path/To/filename.png", QtCore.QSize, QtGui.QIcon.Mode, QtGui.QIcon.State): 将文件(第一个参数)中的图像添加到图标中。它通过大小(第二个参数)、模式(第三个参数)和状态(第四个参数)进行指定。
icon.addPixmap(QtGui.QPixmap, QtGui.QIcon.Mode, QtGui.QIcon.State): 将位图(第一个参数)添加到图标中。它通过模式(第二个参数)和状态(第三个参数)进行指定。
set
这些是与图标相关的设置参数和属性的函数:
icon.setFallbackSearchPaths([str]): 将回退搜索路径设置为图标回退的路径列表。
icon.setIsMask(bool): 如果参数为True,则指定此图标为遮罩图像。
icon.setThemeName(str): 将图标主题名称设置为参数中指定的名称。
icon.setThemeSearchPaths([str]): 将主题搜索路径设置为图标主题的路径列表。
has/is
这些是与图像状态相关的布尔值(bool)返回值的函数:
icon.hasThemeIcon(str): 如果图标对于参数中指定的名称可用,则返回True。
icon.isMask(): 如果图标被标记为遮罩图像,则返回True。
icon.isNull(): 如果图标为空,则返回True。
functional
这些是与当前图标值的返回或功能仪器相关的函数:
icon.actualSize(QtCore.QSize, QtGui.QIcon.Mode, QtGui.QIcon.State): 返回图标在大小(第一个参数)、模式(第二个参数)和状态(第三个参数)下的实际大小。可用的图标模式如下:
-
QtGui.QIcon.Normal—0: 与图标无交互;功能可用。 -
QtGui.QIcon.Disabled—1: 功能不可用。 -
QtGui.QIcon.Active—2: 与图标的交互;功能可用。 -
QtGui.QIcon.Selected—3: 图标被选中。
图标状态如下:
-
QtGui.QIcon.On—0: 小部件处于开启状态。 -
QtGui.QIcon.Off—1: 小部件处于关闭状态。
icon.actualSize(QtGui.QWindow, QtCore.QSize, QtGui.QIcon.Mode, QtGui.QIcon.State): 返回图标相对于窗口(第一个参数)的大小(第二个参数),模式(第三个参数)和状态(第四个参数)的实际大小。
icon.availableSizes(QtGui.QIcon.Mode, QtGui.QIcon.State): 这返回与模式(第一个参数)和状态(第二个参数)相关的图标可用大小的列表。
icon.cacheKey(): 这返回图标内容的标识符。
icon.fallbackSearchPaths(): 这返回图标回退搜索路径的列表。
icon.fromTheme(str): 这返回与参数中指定的名称对应的图标,在当前图标主题中。
icon.fromTheme(str, QtGui.QIcon): 这返回与名称(第一个参数)对应的图标;如果找不到图标,则返回回退(第二个参数)。
icon.name(): 这返回图标的名称。
icon.paint(QtGui.QPainter, QtCore.QRect, QtCore.Qt.Alignment, QtGui.QIcon.Mode, QtGui.QIcon.State): 这使用画家(第一个参数)在指定的矩形(第二个参数)、对齐(第三个参数)、模式(第四个参数)和状态(第五个参数)中绘制图标。
icon.paint(QtGui.QPainter, x, y, w, h, QtCore.Qt.Alignment, QtGui.QIcon.Mode, QtGui.QIcon.State): 这使用画家(第一个参数)在以 x(x 轴)和 y(y 轴)开始的矩形内,使用 w(宽度)和 h(高度)大小,以及对齐(第三个参数),模式(第四个参数)和状态(第五个参数)来绘制图标。
icon.pixmap(QtCore.QSize, QtGui.QIcon.Mode, QtGui.QIcon.State): 这返回具有指定大小(第一个参数)、模式(第二个参数)和状态(第三个参数)的位图。
icon.pixmap(w, h, QtGui.QIcon.Mode, QtGui.QIcon.State): 这返回具有指定 w(宽度)和 h(高度)、模式(第三个参数)和状态(第四个参数)的位图。
icon.pixmap(QtGui.QWindow, QtCore.QSize, QtGui.QIcon.Mode, QtGui.QIcon.State): 这返回具有指定窗口(第一个参数)、大小(第二个参数)、模式(第三个参数)和状态(第四个参数)的位图。
icon.swap(QtGui.QIcon): 这将此图标与参数中指定的图标交换。
icon.themeName(): 这返回当前图标主题的名称。
icon.themeSearchPaths(): 这返回搜索图标主题的路径。
摘要
本章从管理图形元素和使用 Qt 库进行绘制的基本类的角度进行了描述。Qt 框架的目标是开发图形应用程序、图形工具以及与创建图形相关的类,并确保它们得到广泛应用。在可能的情况下,本书将讨论主要的内容。
虽然本章关注的是基本类,但在下一章中,我们将讨论在应用程序中创建图形表示的模型/视图范式以及实现此范式的类。
第十章:图形表示
在本章中,我们将探讨创建各种图形组件的下一部分,并在 GUI 应用程序中实现它们。这些类主要被用户用于创建图形元素,并在 Qt 库的标准图形类帮助下可视化它们。Qt 框架提供了表示这些图形的基本类。这些类是QGraphicsScene、QGraphicsView和QGraphicsItem。还有超过 50 个类实现了特殊功能,例如动画和图形元素。Qt 库实现了应用程序中创建的图形的模型-视图范式。模型-视图架构描述了如何将视图从模型中分离出来,并使用一个视图与不同的模型一起使用。具有图形元素的场景可以用不同的视图来表示。基于此,场景为项目提供了一个位置,这些项目可以是各种几何图形,而视图则可视化这个场景。虽然 Qt 是一个图形库,但我们将不会涵盖所有类,而只描述主要的一些。
在本章中,我们将涵盖以下主题:
-
QObject类 -
场景
-
视图
-
项目
QObject
此类是所有与 Qt 一起使用的对象的基类。正如我们在引言中提到的,此类由QWidget类(与QPaintDevice相同)继承。我们将从这个类开始,因为QGraphicsScene继承了这个类。此类的声明语法如下:
object = QtCore.QObject()
QObject 函数
QObject类通过以下函数增强了功能。
设置
这些函数设置对象的参数/属性:
object.setObjectName(str): 为此对象设置参数中指定的名称。
object.setParent(QtCore.QObject): 为此对象设置参数中指定的父对象。
object.setProperty(str, object): 将对象的名称(第一个参数)属性设置为值(第二个参数)。
是
这些函数返回与该对象状态相关的布尔值(bool):
object.isSignalConnected(QtCore.QMetaMethod): 如果在参数中指定的信号至少连接到一个接收器,则返回True。
object.isWidgetType(): 如果此对象具有小部件类型(或是一个小部件),则返回True。
object.isWindowType(): 如果此对象具有窗口类型(或是一个窗口),则返回True。
功能性
这些函数与返回此对象的当前值、功能变化等相关:
object.blockSignals(bool): 如果参数为True,则此对象将阻止发出信号。
object.children(): 返回此对象的子对象列表。
object.connect(QtCore.QObject, str, QtCore.QObject, str, QtCore.Qt.ConnectionType): 这从发送者(第一个参数)的信号(第二个参数)创建到接收者(第三个参数)的方法(第四个参数)的连接(第五个参数)。
object.connectNotify(QtCore.QMetaMethod): 当对象与参数中指定的信号连接时,此函数将被调用。
object.deleteLater(): 这安排删除此对象。
object.disconnect(QtCore.QObject, str): 这将断开对象的所有信号与接收者(第一个参数)的方法(第二个参数)的连接。
object.disconnect(str, QtCore.QObject, str): 这将断开信号(第一个参数)与接收者(第二个参数)的方法(第三个参数)的连接。
object.disconnect(QtCore.QObject, str, QtCore.QObject, str): 这将断开对象发送者(第一个参数)中的信号(第二个参数)与接收者(第三个参数)的方法(第四个参数)的连接。
object.disconnect(QtCore.QObject, QtCore.QMetaMethod, QtCore.QObject, QtCore.QMetaMethod): 这将断开对象发送者(第一个参数)中的信号(第二个参数)与接收者(第三个参数)的方法(第四个参数)的连接。
object.disconnectNotify(QtCore.QMetaMethod): 当对象从参数中指定的信号断开连接时,此函数将被调用。
object.dumpObjectInfo(): 这将输出该对象的信号连接。
object.dumpObjectTree(): 这将输出该对象的子对象树。
object.dynamicPropertyNames(): 这返回所有动态添加到该对象的setProperty()函数的所有属性的名称。
object.findChild(type, str): 这将找到具有指定类型(第一个参数)和名称(第二个参数)的子对象。
object.findChildren(type, str): 这将找到具有指定类型(第一个参数)和名称(第二个参数)的子对象。
object.inherits(str): 如果该对象是参数中指定的类或其子类的实例,则返回True。
object.killTimer(int): 这将杀死具有指定 ID(参数)的计时器。
object.metaObject(): 这返回该对象的元对象。
object.moveToThread(QtCore.QThread): 这将此对象及其子对象的线程亲和力更改为参数中指定的线程。
object.objectName(): 这返回该对象的名字。
object.parent(): 这返回该对象的QtCore.QObject类型的父对象。
object.property(str): 这返回对象名称属性的价值。
object.receivers(SIGNAL): 这返回连接到参数中指定的信号的接收者数量。
object.sender(): 这返回发送信号的 QtCore.QObject 类型的发送者。
object.senderSignalIndex(): 这返回调用槽的信号的元方法索引,该槽是 sender() 函数返回的类的成员。
object.signalsBlocked(): 如果此对象的信号被阻止,则返回 True。
object.startTimer(int, QtCore.Qt.TimerType): 这以间隔(第一个参数)和类型(第二个参数)启动计时器。
object.thread(): 这返回此对象正在运行的线程。
events
这些函数与事件相关,例如事件处理器:
object.childEvent(QtCore.QChildEvent): 此事件处理器接收此对象的子事件,事件通过参数传入。
object.customEvent(QtCore.QEvent): 此事件处理器接收此对象的自定义事件,事件通过参数传入。
object.event(QtCore.QEvent): 此函数接收发送给对象的信号,如果事件被识别并处理,则应返回 True。
object.eventFilter(QtCore.QObject, QtCore.QEvent): 如果对象作为事件过滤器安装在此对象上,则过滤事件。
object.installEventFilter(QtCore.QObject): 这在此对象上安装参数中指定的事件过滤器。
object.removeEventFilter(QtCore.QObject): 这将从对象中移除参数中指定的事件过滤器。
object.timerEvent(QtCore.QTimerEvent): 此事件处理器接收具有传入参数的事件的组件的计时器事件。
signals
以下是在 QObject 类中可用的信号:
object.destroyed(QtCore.QObject): 在对象被销毁之前发出此信号。
object.objectNameChanged(str): 当对象名称已更改时发出此信号。新名称通过参数传入。
QGraphicsScene
此类表示各种图形项的场景。这是图形视图架构的一部分,并提供图形视图场景。场景在应用程序中的作用如下:
-
管理项目的快速接口
-
未变换渲染
-
场中每个项目的信号
-
管理项目状态
场景的声明语法如下:
scene = QtWidgets.QGraphicsScene()
QGraphicsScene 函数
QGraphicsScene 类通过以下函数提高功能。
add
这些函数添加场景元素:
scene.addEllipse(QtCore.QRectF, QtGui.QPen, QtGui.QBrush): 使用矩形(第一个参数)的几何形状添加椭圆,指定笔(第二个参数)和刷(第三个参数)。
scene.addEllipse(x, y, w, h, QtGui.QPen, QtGui.QBrush): 这在 x 轴上的 x 和 y 轴上的 y 处添加一个椭圆,宽度为 w,高度为 h。笔(第五个参数)和刷(第六个参数)被指定。
scene.addItem(QtWidgets.QGraphicsItem): 这将在场景中添加一个由参数指定的图形项目。
scene.addLine(QtCore.QLineF, QtGui.QPen): 这将在场景中添加一条线,其几何形状由第一个参数指定,而笔由第二个参数指定。
scene.addLine(x1, y1, x2, y2, QtGui.QPen): 这将在点(x1, y1)开始并结束于点(x2, y2)的位置添加一条线。笔由第五个参数指定。
scene.addPath(QtGui.QPainterPath, QtGui.QPen, QtGui.QBrush): 这将在场景中添加一个由第一个参数指定的路径,并带有笔(第二个参数)和画刷(第三个参数)。
scene.addPixmap(QtGui.QPixmap): 这将在场景中添加一个指定的参数图样。
scene.addPolygon(QtGui.QPolygonF, QtGui.QPen, QtGui.QBrush): 这将在场景中添加一个由第一个参数指定的多边形,并带有笔(第二个参数)和画刷(第三个参数)。
scene.addRect(QtCore.QRectF, QtGui.QPen, QtGui.QBrush): 这将在场景中添加一个矩形,其几何形状由第一个参数指定,同时指定了笔(第二个参数)和画刷(第三个参数)。
scene.addRect(x, y, w, h, QtGui.QPen, QtGui.QBrush): 这将在(x, y)处开始,宽度为w,高度为h的位置添加一个矩形。笔(第五个参数)和画刷(第六个参数)也进行了指定。
scene.addSimpleText(str, QtGui.QFont): 这将在场景中添加一些简单文本(第一个参数),为QtWidgets.QGraphicsSimpleTextItem类型,并带有字体(第二个参数)。
scene.addText(str, QtGui.QFont): 这将在场景中添加一些格式化文本(第一个参数),为QtWidgets.QGraphicsTextItem类型,并带有字体(第二个参数)。
scene.addWidget(QtWidgets.QWidget, QtCore.Qt.WindowFlags): 这将在场景中添加一个QtWidgets.QGraphicsProxyWidget类型的新小部件。
set
这些函数将参数/属性设置到场景中:
scene.setActivePanel(QtWidgets.QGraphicsItem): 这将参数指定的项目设置为活动项目。
scene.setActiveWindow(QtWidgets.QGraphicsWidget): 这将为参数指定的窗口设置活动状态。
scene.setBackgroundBrush(QtGui.QBrush): 这将为场景设置参数指定的背景画刷。
scene.setBspTreeDepth(int): 这将为场景设置参数指定的二叉空间划分(BSP)索引树的深度。
scene.setFocus(QtCore.Qt.FocusReason): 这将设置场景的焦点,并通过参数传递焦点原因。
scene.setFocusItem(QtWidgets.QGraphicsItem, QtCore.Qt.FocusReason): 这将为场景设置焦点项目(第一个参数),并带有焦点原因(第二个参数)。
scene.setFocusOnTouch(bool): 如果参数为True,则在接收到触摸开始事件时,项目将获得焦点。
scene.setFont(QtGui.QFont): 这将为场景设置指定的参数,作为场景的默认字体。
scene.setForegroundBrush(QtGui.QBrush): 这将为场景设置指定的前景画笔。
scene.setItemIndexMethod(QtWidgets.QGraphicsScene.ItemIndexMethod): 这将设置项目索引方法。可用方法如下:
-
QtWidgets.QGraphicsScene.BspTreeIndex—0: 应用了 BSP(静态场景)。 -
QtWidgets.QGraphicsScene.NoIndex—1: 未应用索引(动态场景)。
scene.setMinimumRenderSize(float): 这将为要绘制的项目的最小视图变换大小设置。这将加快场景的渲染速度,在缩放视图下渲染许多对象。
scene.setPalette(QtGui.QPalette): 这将为场景设置指定的调色板。
scene.setSceneRect(QtCore.QRectF): 这将为场景设置指定的参数作为边界矩形。
scene.setSceneRect(x, y, w, h): 这将为场景设置一个以x/y为起点,宽度为w,高度为h的边界矩形。
scene.setSelectionArea(QtGui.QPainterPath, QtGui.QTransform): 这将设置选择区域为一个路径(第一个参数)以及应用了变换(第二个参数)。
scene.setSelectionArea(QtGui.QPainterPath, QtCore.Qt.ItemSelectionMode, QtGui.QTransform): 这将设置选择区域为一个路径(第一个参数),带有模式(第二个参数)和应用了变换(第三个参数)。
scene.setSelectionArea(QtGui.QPainterPath, QtCore.Qt.ItemSelectionOperation, QtCore.Qt.ItemSelectionMode, QtGui.QTransform): 这将设置选择区域为一个路径(第一个参数),带有模式(第三个参数)、应用了变换(第四个参数)以及当前选中项的选择操作(第二个参数)。
scene.setStickyFocus(bool): 如果参数为True,则焦点将保持不变,点击场景的背景或不接受焦点的项。否则,焦点将被清除。
scene.setStyle(QtWidgets.QStyle): 这将为场景设置指定的参数作为样式。
has/is
这些函数返回与场景状态相关的布尔值(bool):
scene.hasFocus(): 如果此场景有焦点,则返回True。
scene.isActive(): 如果此场景是活动的,则返回True。
functional
这些函数与场景当前值的返回、功能变化等相关:
scene.activePanel(): 这将返回此场景的活动面板。
scene.activeWindow(): 这将返回此场景的活动窗口。
scene.advance(): 这将场景向前推进一步(适用于场景上的所有项目)。
scene.backgroundBrush(): 这将返回此场景背景的QtGui.QBrush类型的画笔。
scene.bspTreeDepth(): 这将返回此场景中 BSP 索引树的深度。
scene.clear(): 这清除此场景中的所有项目。
scene.clearFocus(): 这清除此场景的焦点。
scene.clearSelection(): 这清除此场景的当前选择。
scene.collidingItems(QtWidgets.QGraphicsItem, QtCore.Qt.ItemSelectionMode): 这返回与项目(第一个参数)碰撞的项目列表,碰撞检测由模式(第二个参数)指定。
scene.createItemGroup([QtWidgets.QGraphicsItem]): 这将参数中指定的所有项目作为一个项目列表分组到新的项目组中。
scene.destroyItemGroup(QtWidgets.QGraphicsItemGroup): 这从场景中删除参数中指定的项目组。
scene.drawBackground(QtGui.QPainter, QtCore.QRectF): 这使用画家(第一个参数)和矩形(第二个参数)为此场景绘制背景。
scene.drawForeground(QtGui.QPainter, QtCore.QRectF): 这使用画家(第一个参数)和矩形(第二个参数)为此场景绘制前景。
scene.focusItem(): 这返回此场景的当前焦点项目。
scene.focusOnTouch(): 如果项目在接收到触摸开始事件时获得焦点,则返回 True。
scene.font(): 这返回此场景的当前字体。
scene.foregroundBrush(): 这返回此场景前景的 QtGui.QBrush 类型的画笔。
scene.invalidate(QtCore.QRectF, QtWidgets.QGraphicsScene.SceneLayers): 这安排在场景中矩形(第一个参数)的层(第二个参数)的重绘。
scene.invalidate(x, y, w, h, QtWidgets.QGraphicsScene.SceneLayers): 这安排在以 x/y 开始的矩形中重绘层(第五个参数),宽度为 w,高度为 h。
scene.itemAt(QtCore.QPointF, QtGui.QTransform): 这返回在特定点(第一个参数)的最顶层项目,带有应用变换(第二个参数)。
scene.itemAt(x, y, QtGui.QTransform): 这返回由 x 和 y 指定的位置(带有应用变换的第三个参数)的最顶层项目。
scene.itemIndexMethod(): 这返回项目的索引方法。
scene.items(QtCore.Qt.SortOrder): 这返回在参数中指定的堆叠顺序中所有场景项目的有序列表。
scene.items(QtCore.QRectF, QtCore.Qt.ItemSelectionMode, QtCore.Qt.SortOrder, QtGui.QTransform): 这返回根据模式(第二个参数)在矩形(第一个参数)内或与之相交的所有可见项目,排序(第三个参数),并应用变换(第四个参数)。
scene.items(QtCore.QPointF, QtCore.Qt.ItemSelectionMode, QtCore.Qt.SortOrder, QtGui.QTransform): 此函数根据模式(第二个参数)返回所有可见项目,该模式位于或与点(第一个参数)内部或相交,排序(第三个参数),并应用了变换(第四个参数)。
scene.items(QtGui.QPainterPath, QtCore.Qt.ItemSelectionMode, QtCore.Qt.SortOrder, QtGui.QTransform): 此函数根据模式(第二个参数)返回所有可见项目,该模式位于或与指定的路径(第一个参数)内部或相交,排序(第三个参数),并应用了变换(第四个参数)。
scene.items(QtGui.QPolygonF, QtCore.Qt.ItemSelectionMode, QtCore.Qt.SortOrder, QtGui.QTransform): 此函数根据模式(第二个参数)返回所有可见项目,该模式位于或与多边形(第一个参数)内部或相交,排序(第三个参数),并应用了变换(第四个参数)。
scene.items(x, y, w, h, QtCore.Qt.ItemSelectionMode, QtCore.Qt.SortOrder, QtGui.QTransform): 此函数根据模式(第五个参数)返回所有可见项目,该模式位于或与以x/y为起始点、宽度为w、高度为h的矩形内部或相交,排序(第六个参数),并应用了变换(第七个参数)。
scene.itemsBoundingRect(): 此函数返回场景中所有项目的边界矩形。
scene.minimumRenderSize(): 此函数返回要绘制的项目的最小视图变换大小。
scene.mouseGrabberItem(): 此函数返回当前鼠标抓取项,该项接收发送到场景的所有鼠标事件。
scene.palette(): 此函数返回与场景一起使用的QtGui.QPalette类型的默认调色板。
scene.removeItem(QtWidgets.QGraphicsItem): 此函数移除由参数指定的项目及其所有子项。
scene.render(QtGui.QPainter, QtCore.QRectF, QtCore.QRectF, QtCore.Qt.AspectRatioMode): 此函数将场景中的源矩形(第三个参数)渲染到由画家(第一个参数)和模式(第四个参数)指定的矩形中。
scene.sceneRect(): 此函数返回场景的边界矩形。
scene.selectedItems(): 此函数返回当前选定的项目列表。
scene.selectionArea(): 此函数返回此场景的选择区域。
scene.stickyFocus(): 当用户点击场景的背景或项目时,此函数返回True,表示焦点将保持不变。
scene.style(): 此函数返回用于此场景的QtWidgets.QStyle类型的样式。
scene.update(QtCore.QRectF): 此函数安排在场景中重绘由参数指定的矩形。
scene.update(x, y, w, h): 此函数安排在场景上重绘以x/y为起始点、宽度为w、高度为h的区域。
scene.views(): 这返回显示在此场景上的所有视图,作为一个视图列表。
事件
这些函数与事件相关,例如事件处理程序:
scene.contextMenuEvent(QtWidgets.QGraphicsSceneContextMenuEvent): 此事件处理程序接收上下文菜单事件。
scene.dragEnterEvent(QtWidgets.QGraphicsSceneDragDropEvent): 此事件处理程序接收场景参数中指定的拖动进入事件。
scene.dragLeaveEvent(QtWidgets.QGraphicsSceneDragDropEvent): 此事件处理程序接收场景参数中指定的拖动离开事件。
scene.dragMoveEvent(QtWidgets.QGraphicsSceneDragDropEvent): 此事件处理程序接收场景参数中指定的拖动移动事件。
scene.dropEvent(QtWidgets.QGraphicsSceneDragDropEvent): 此事件处理程序接收场景参数中指定的放下事件。
scene.event(QtCore.QEvent): 这接收场景的事件,并且如果事件被识别和处理,应返回 True。
scene.focusOutEvent(QtGui.QFocusEvent): 此事件处理程序接收场景的键盘焦点事件,当失去焦点时,这些事件通过事件参数传递。
scene.focusInEvent(QtGui.QFocusEvent): 此事件处理程序接收场景的键盘焦点事件,当获得焦点时,这些事件通过事件参数传递。
scene.helpEvent(QtWidgets.QGraphicsSceneHelpEvent): 此事件处理程序接收场景参数中指定的帮助事件。
scene.inputMethodEvent(QtGui.QInputMethodEvent): 此事件处理程序接收输入法事件。
scene.keyPressEvent(QtGui.QKeyEvent): 此事件处理程序接收场景的按键按下事件,事件通过参数传递。
scene.keyReleaseEvent(QtGui.QKeyEvent): 此事件处理程序接收场景的按键释放事件,事件通过参数传递。
scene.mouseDoubleClickEvent(QtWidgets.QGraphicsSceneMouseEvent): 此事件处理程序接收场景的鼠标双击事件,事件通过参数传递。
scene.mouseMoveEvent(QtWidgets.QGraphicsSceneMouseEvent): 此事件处理程序接收场景的鼠标移动事件,事件通过参数传递。
scene.mousePressEvent(QtWidgets.QGraphicsSceneMouseEvent): 此事件处理程序接收场景的鼠标按下事件,事件通过参数传递。
scene.mouseReleaseEvent(QtWidgets.QGraphicsSceneMouseEvent): 此事件处理程序接收场景的鼠标释放事件,事件通过参数传递。
scene.sendEvent(QtWidgets.QGraphicsItem, QtCore.QEvent): 这通过事件过滤器将事件(第二个参数)发送到项目(第一个参数)。
scene.wheelEvent(QtWidgets.QGraphicsSceneWheelEvent): 此事件处理程序接收场景的鼠标滚轮事件,事件通过参数传递。
信号
QGraphicsScene 类的可用的信号如下:
scene.changed([QtCore.QRectF]): 如果场景内容发生变化,会发出此信号,参数包含一个矩形列表。
scene.focusItemChanged(QtWidgets.QGraphicsItem, QtWidgets.QGraphicsItem, QtCore.Qt.FocusReason): 当场景中的焦点发生变化时,会发出此信号。参数包括一个之前有焦点的项目(第二个参数)、获得输入焦点的项目(第一个参数)和焦点原因(第三个参数)。
scene.sceneRectChanged(QtCore.QRectF): 当场景的矩形发生变化时,会发出此信号。新矩形通过参数传递。
scene.selectionChanged(): 当场景的选择发生变化时,会发出此信号。
QGraphicsView
此类表示一个具有显示场景小部件的视图。这是图形视图架构的一部分,并为应用程序中的场景提供图形表示。此类的声明语法如下:
graphics_view = QtWidgets.QGraphicsView()
QGraphicsView 函数
QGraphicsView 通过以下函数增强功能。
set
这些函数设置图形视图的参数/属性:
graphics_view.setAlignment(QtCore.Qt.Alignment): 这将设置图形视图中的场景对齐方式。
graphics_view.setBackgroundBrush(QtGui.QBrush): 这将为图形视图中的场景设置指定的背景画刷。
graphics_view.setCacheMode(QtWidgets.QGraphicsView.CacheMode): 这将设置描述视图哪些部分被缓存的缓存模式。可用的模式如下:
-
QtWidgets.QGraphicsView.CacheNone: 所有绘图都直接在视口中完成。 -
QtWidgets.QGraphicsView.CacheBackground: 背景被缓存。
graphics_view.setDragMode(QtWidgets.QGraphicsView.DragMode): 这将设置拖动模式。可用的模式如下:
-
QtWidgets.QGraphicsView.NoDrag—0: 鼠标事件将被忽略。 -
QtWidgets.QGraphicsView.ScrollHandDrag—1: 光标将变为指向手,拖动鼠标将滚动滚动条。 -
QtWidgets.QGraphicsView.RubberBandDrag—2: 将使用橡皮筋。
graphics_view.setForegroundBrush(QtGui.QBrush): 这将为图形视图中的场景设置指定的前景画刷。
graphics_view.setInteractive(bool): 这将设置在视图中允许的场景交互。
graphics_view.setOptimizationFlag(QtWidgets.QGraphicsView.OptimizationFlag, bool): 如果第二个参数是 True,则启用第一个参数指定的标志。
graphics_view.setOptimizationFlags(QtWidgets.QGraphicsView.OptimizationFlag | QtWidgets.QGraphicsView.OptimizationFlag): 这将设置用于图形视图性能的优化标志,标志由参数指定。
graphics_view.setRenderHint(QtGui.QPainter.RenderHint, bool): 如果第二个参数是 True,则启用第一个参数指定的渲染提示。
graphics_view.setRenderHints(QtGui.QPainter.RenderHint | QtGui.QPainter.RenderHint): 这将设置参数中指定的渲染提示,这些提示将用作此视图的默认渲染提示。
graphics_view.setResizeAnchor(QtWidgets.QGraphicsView.ViewportAnchor): 这将设置参数中指定的锚点,该锚点将描述视图在调整大小时如何定位场景。可用的锚点如下:
-
QtWidgets.QGraphicsView.NoAnchor—0: 无锚点,位置不变。 -
QtWidgets.QGraphicsView.AnchorViewCenter—1: 将锚点设置为视图的中心。 -
QtWidgets.QGraphicsView.AnchorUnderMouse—2: 将锚点设置为鼠标下方的点。
graphics_view.setRubberBandSelectionMode(QtCore.Qt.ItemSelectionMode): 这将设置描述如何使用橡皮筋拖动选择项的模式。
graphics_view.setScene(QtWidgets.QGraphicsScene): 这将参数中指定的当前图形场景设置为图形视图。
graphics_view.setSceneRect(QtCore.QRectF): 这将设置参数中指定的场景区域,该区域将使用此图形视图进行可视化。
graphics_view.setSceneRect(x, y, w, h): 这将设置从x/y开始的场景区域,宽度为w,高度为h,该区域将使用此图形视图进行可视化。
graphics_view.setTransform(QtGui.QTransform, bool): 这将设置第一个参数中指定的变换矩阵。如果第二个参数为True,则矩阵将与当前矩阵合并。
graphics_view.setTransformationAnchor(QtWidgets.QGraphicsView.ViewportAnchor): 这将设置参数中指定的变换锚点。这将描述图形视图在变换期间如何定位场景。
graphics_view.setViewportUpdateMode(QtWidgets.QGraphicsView.ViewportUpdateMode): 这将设置用于更新视口内容的模式。可用的参数如下:
-
QtWidgets.QGraphicsView.FullViewportUpdate—0: 将更新整个视口,以反映对场景可见部分所做的更改。 -
QtWidgets.QGraphicsView.MinimalViewportUpdate—1: 将更新最少的视口区域。 -
QtWidgets.QGraphicsView.SmartViewportUpdate—2: 将更新最优的视口区域。 -
QtWidgets.QGraphicsView.NoViewportUpdate—3: 视口不会随着场景的变化而更新。 -
QtWidgets.QGraphicsView.BoundingRectViewportUpdate—4: 将更新视口中所有更改的边界矩形。
是
这些函数返回与图形视图状态相关的布尔值(bool):
graphics_view.isInteractive(): 如果此视图允许在场景中进行交互,则返回True。
graphics_view.isTransformed(): 如果此视图已变换,则返回True。
功能性
这些函数返回图形视图的当前值、功能更改等:
graphics_view.alignment(): 这返回了图形视图小部件中场景的对齐方式。
graphics_view.backgroundBrush(): 这返回了在图形视图小部件中用于此场景的QtGui.QBrush类型的背景画刷。
graphics_view.cacheMode(): 这返回了QtWidgets.QGraphicsView.CacheMode类型的缓存模式。此视图的部分被缓存。
graphics_view.centerOn(QtCore.QPointF): 这将视口的内容滚动到场景坐标点,由参数指定,这将位于视图中心。
graphics_view.centerOn(QtWidgets.QGraphicsItem): 这将视口的内容滚动到场景项,由参数指定,这将位于视图中心。
graphics_view.centerOn(x, y): 这将视口的内容滚动到场景坐标x和y,这将位于视图中心。
graphics_view.dragMode(): 这返回了在鼠标拖动此场景时的QtWidgets.QGraphicsView.DragMode类型的模式。
graphics_view.drawBackground(QtGui.QPainter, QtCore.QRectF): 这使用画家(第一个参数)在坐标(第二个参数)中绘制此场景的背景。
graphics_view.drawForeground(QtGui.QPainter, QtCore.QRectF): 这使用画家(第一个参数)在坐标(第二个参数)中绘制此场景的前景。
graphics_view.ensureVisible(QtCore.QRectF, int, int): 这将视口的内容滚动到将可见的场景矩形(第一个参数),带有x边距(第二个参数)和y边距(第三个参数)。
graphics_view.ensureVisible(QtWidgets.QGraphicsItem, int, int): 这将视口的内容滚动到将可见的场景项(第一个参数),带有x边距(第二个参数)和y边距(第三个参数)。
graphics_view.ensureVisible(x, y, w, h, int, int): 这将视口的内容滚动到场景的起始位置x/y,宽度为w,高度为h,将在x边距(第五个参数)和y边距(第六个参数)内可见。
graphics_view.fitInView(QtCore.QRectF, QtCore.Qt.AspectRatioMode): 这缩放视图矩阵并滚动滚动条,使场景矩形(第一个参数)根据纵横比(第二个参数)适合视口内。
graphics_view.fitInView(QtWidgets.QGraphicsItem, QtCore.Qt.AspectRatioMode): 这缩放视图矩阵并滚动滚动条,使场景的项根据纵横比(第二个参数)紧密适合视图内。
graphics_view.fitInView(x, y, w, h, QtCore.Qt.AspectRatioMode): 这缩放视图矩阵并滚动滚动条到场景的起始位置x/y,宽度为w,高度为h,使项目根据纵横比(第五个参数)适合视口内。
graphics_view.foregroundBrush(): 这返回了用于图形视图小部件中此场景的 QtGui.QBrush 类型的前景画笔。
graphics_view.invalidateScene(QtCore.QRectF, QtWidgets.QGraphicsScene.SceneLayers): 这使矩形(第一个参数)内的层(第二个参数)无效并安排重绘。
graphics_view.itemAt(QtCore.QPointF): 这返回了参数中指定的点的项目。
graphics_view.itemAt(x, y): 这返回了由 x 和 y 坐标指定的位置的项。
graphics_view.items(): 这返回了场景中所有项目的列表,按降序堆叠顺序排列。
graphics_view.items(QtCore.QRect, QtCore.Qt.ItemSelectionMode): 这返回了所有可见项目,取决于模式(第二个参数),这些项目位于或与矩形(第一个参数)内部或相交。
graphics_view.items(QtCore.QPoint): 这返回了参数中指定的点的所有项。
graphics_view.items(QtGui.QPainterPath, QtCore.Qt.ItemSelectionMode): 这返回了所有项目,取决于模式(第二个参数),这些项目位于或与指定的路径(第一个参数)内部或相交。
graphics_view.items(QtGui.QPolygon, QtCore.Qt.ItemSelectionMode): 这返回了所有项目,取决于模式(第二个参数),这些项目位于或与多边形(第一个参数)内部或相交。
graphics_view.items(x, y): 这返回了坐标 x 和 y 处的所有项。
graphics_view.items(x, y, w, h, QtCore.Qt.ItemSelectionMode): 这返回了所有项目,取决于模式(第五个参数),这些项目位于或与以 x/y 为起点、宽度为 w 和高度为 h 的区域内部或相交。
graphics_view.optimizationFlags(): 这返回了用于调整视图性能的标志。
graphics_view.render(QtGui.QPainter, QtCore.QRectF, QtCore.QRect, QtCore.Qt.AspectRatioMode): 这使用画家(第一个参数)和模式(第四个参数)将场景中的源矩形(第三个参数)渲染到矩形(第二个参数)中。
graphics_view.renderHints(): 这返回了此视图的默认渲染提示。
graphics_view.resetCachedContent(): 这重置了缓存内容并清除了视图缓存。
graphics_view.resetTransform(): 这将视图变换重置为恒等矩阵。
graphics_view.resizeAnchor(): 这返回了在视图大小调整时将与场景位置一起使用的锚点。
graphics_view.rotate(float): 这按顺时针方向将当前视图变换旋转到参数中指定的角度度数。
graphics_view.rubberBandRect(): 这返回了使用项目选择时 QtCore.QRect 类型(在视口坐标中)的橡皮筋区域。
graphics_view.rubberBandSelectionMode(): 这返回了用于使用橡皮筋选择矩形选择项目的模式。
graphics_view.scale(float, float): 此函数通过 x(第一个参数)和 y(第二个参数)缩放视图转换。
graphics_view.scene(): 这将返回由此图形视图可视化的 QtWidgets.QGraphicsScene 类型的场景。
graphics_view.sceneRect(): 这将返回由此图形视图可视化的 QtCore.QRectF 类型的场景区域。
graphics_view.setupViewport(QtWidgets.QWidget): 在使用之前,此函数初始化一个新的视口小部件。
graphics_view.shear(float, float): 此函数将当前视图转换水平(第一个参数)和垂直(第二个参数)剪切。
graphics_view.transform(): 这将返回此图形视图的当前转换矩阵,其类型为 QtGui.QTransform。
graphics_view.transformationAnchor(): 这将返回与该图形视图转换一起使用的 QtWidgets.QGraphicsView.ViewportAnchor 类型的锚点。
graphics_view.translate(float, float): 此函数通过 x(第一个参数)和 y(第二个参数)平移视图转换。
graphics_view.updateScene([QtCore.QRectF]): 这将安排更新场景矩形,参数为一个矩形列表。
graphics_view.updateSceneRect(QtCore.QRectF): 此函数通知图形视图场景的矩形已更改,参数为新的场景矩形。
graphics_view.viewportTransform(): 这将返回一个 QtGui.QTransform 类型的矩阵,该矩阵将场景坐标映射到视口坐标。
graphics_view.viewportUpdateMode(): 这将返回视口的更新模式。
映射
这些函数与映射相关:
graphics_view.mapFromScene(QtCore.QRectF): 这将返回一个指定参数的矩形,并将其转换为视口坐标多边形。
graphics_view.mapFromScene(QtCore.QPointF): 这将返回一个指定参数的点,并将其转换为视口坐标点。
graphics_view.mapFromScene(QtGui.QPainterPath): 这将返回一个指定参数的场景坐标画家路径,并将其转换为视口坐标画家路径。
graphics_view.mapFromScene(QtGui.QPolygonF): 这将返回一个指定参数的场景坐标多边形,并将其转换为视口坐标多边形。
graphics_view.mapToScene(QtCore.QRectF): 这将返回一个指定参数的视口坐标多边形,并将其转换为场景坐标多边形。
graphics_view.mapToScene(QtCore.QPointF): 这将返回一个指定参数的视口坐标点,并将其映射到场景坐标。
graphics_view.mapToScene(QtGui.QPainterPath): 这将返回一个指定参数的视口画家路径,并将其转换为场景坐标画家路径。
graphics_view.mapToScene(QtGui.QPolygonF): 这将返回一个指定参数的视口坐标多边形,并将其转换为场景坐标多边形。
事件
这些函数与事件相关,例如事件处理器:
graphics_view.contextMenuEvent(QtGui.QContextMenuEvent): 此事件处理程序接收上下文菜单事件。
graphics_view.dragEnterEvent(QtGui.QDragEnterEvent): 当鼠标进入此场景且正在拖动时,此事件处理程序会使用事件参数被调用。
graphics_view.dragLeaveEvent(QtGui.QDragLeaveEvent): 当鼠标离开此场景且正在拖动时,此事件处理程序会使用事件参数被调用。
graphics_view.dragMoveEvent(QtGui.QDragMoveEvent): 当发生某些条件时,例如光标进入或移动到该区域内,键盘上的修饰键在场景具有焦点时被按下,或者正在拖动时,此事件处理程序会使用事件参数被调用。
graphics_view.dropEvent(QtGui.QDropEvent): 当拖动被放置到场景上时,此事件处理程序会使用事件参数被调用。
graphics_view.event(QtCore.QEvent): 此接收场景的事件,如果事件被识别并处理,则应返回True。
graphics_view.focusOutEvent(QtGui.QFocusEvent): 此事件处理程序接收场景的键盘焦点事件,当失去焦点时,这些事件会通过事件参数传递。
graphics_view.focusInEvent(QtGui.QFocusEvent): 此事件处理程序接收场景的键盘焦点事件,当获得焦点时,这些事件会通过事件参数传递。
graphics_view.inputMethodEvent(QtGui.QInputMethodEvent): 此事件处理程序接收场景的输入法事件。
graphics_view.keyPressEvent(QtGui.QKeyEvent): 此事件处理程序接收传入参数的事件的按键事件。
graphics_view.keyReleaseEvent(QtGui.QKeyEvent): 此事件处理程序接收传入参数的事件的按键释放事件。
graphics_view.mouseDoubleClickEvent(QtGui.QMouseEvent): 此事件处理程序接收传入参数的事件的鼠标双击事件。
graphics_view.mouseMoveEvent(QtGui.QMouseEvent): 此事件处理程序接收传入参数的事件的鼠标移动事件。
graphics_view.mousePressEvent(QtGui.QMouseEvent): 此事件处理程序接收传入参数的事件的鼠标按下事件。
graphics_view.mouseReleaseEvent(QtGui.QMouseEvent): 此事件处理程序接收传入参数的事件的鼠标释放事件。
graphics_view.paintEvent(QtGui.QPaintEvent): 此事件处理程序接收传入参数的事件的绘制事件。
graphics_view.resizeEvent(QtGui.QResizeEvent): 此事件处理程序接收传入参数的事件的尺寸调整事件。
graphics_view.showEvent(QtGui.QShowEvent): 此事件处理程序接收传入参数的事件的显示事件。
graphics_view.viewportEvent(QtCore.QEvent): 这是带有传入参数的事件的滚动区域的主要事件处理程序。
graphics_view.wheelEvent(QtGui.QWheelEvent): 此事件处理器接收场景的鼠标滚轮事件,事件通过参数传入。
信号
QGraphicsView 类的可用的信号如下:
graphics_view.rubberBandChanged(QtCore.QRect, QtCore.QPointF, QtCore.QPointF): 当橡皮筋矩形改变时,发出此信号。视口矩形由第一个参数指定,其中包含拖动开始位置(第二个参数)和拖动结束位置(第三个参数)。
QGraphicsItem
这是所有可以通过 QGraphicsScene 类在场景中实现的图形项的基类。使用此基类,Qt 框架提供了一套标准图形项,如 QGraphicsEllipseItem、QGraphicsLineItem、QGraphicsPathItem、QGraphicsPixmapItem、QGraphicsPolygonItem、QGraphicsRectItem、QGraphicsSimpleTextItem 和 QGraphicsTextItem。这些通常用于在应用程序中创建内部图形组件。
QGraphicsItem 函数
QGraphicsItem 类通过以下函数增强功能。
set
这些函数将参数/属性设置到图形项中:
setAcceptDrops(bool): 如果参数为 True,则为此项接受拖放事件。
setAcceptedMouseButtons(QtCore.Qt.MouseButtons): 这为此项的鼠标事件设置参数中指定的鼠标按钮。
setAcceptHoverEvents(bool): 如果参数为 True,则为此项接受悬停事件。
setAcceptTouchEvents(bool): 如果参数为 True,则为此项接受触摸事件。
setActive(bool): 如果参数为 True,则激活此项的面板。
setBoundingRegionGranularity(float): 这为此项的边界区域粒度(0.0 - 1.0)设置参数,即设备分辨率与边界区域的比率。
setCacheMode(QtWidgets.QGraphicsItem.CacheMode, QtCore.QSize): 这为此项设置缓存模式(第一个参数),并可选地设置大小(第二个参数)。可用的缓存模式如下:
-
QtWidgets.QGraphicsItem.NoCache—0: 禁用缓存。 -
QtWidgets.QGraphicsItem.ItemCoordinateCache—1: 为该项的局部坐标系启用缓存。 -
QtWidgets.QGraphicsItem.DeviceCoordinateCache—2: 为该项的设备坐标系启用缓存。
setCursor(QtGui.QCursor): 这为此项设置参数中指定的光标形状。
setData(int, object): 这将为此项的键(第一个参数)设置自定义数据为值(第二个参数)。
setEnabled(bool): 如果参数为 True,则启用此项。
setFiltersChildEvents(bool): 如果参数为 True,则设置此项以过滤所有子项的事件。
setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag, bool): 如果第二个参数为 True,则将启用此项的标志(第一个参数)。
setFlags(QtWidgets.QGraphicsItem.GraphicsItemFlag | QtWidgets.QGraphicsItem.GraphicsItemFlag): 这将为此项设置在参数中指定的标志。
setFocus(QtCore.Qt.FocusReason): 这将为此项提供键盘输入焦点。指定的参数将被传递到任何生成的焦点事件中。
setFocusProxy(QtWidgets.QGraphicsItem): 这将为此项设置焦点代理为参数中指定的项。
setGraphicsEffect(QtWidgets.QGraphicsEffect): 这将为此项设置在参数中指定的图形效果。
setGroup(QtWidgets.QGraphicsItemGroup): 这将为此项设置在参数中指定的组。
setHandlesChildEvents(bool): 如果参数为 True,此项将处理所有子事件。
setInputMethodHints(QtCore.Qt.InputMethodHints): 这将为此项设置在参数中指定的输入法提示。
setOpacity(float): 这将为此项设置局部透明度,介于 0.0(完全透明)和 1.0(完全不透明)之间。
setPanelModality(QtWidgets.QGraphicsItem.PanelModality): 这将为此项设置在参数中指定的模态。可用的模态如下:
-
QtWidgets.QGraphicsItem.NonModal—0: 面板不是模态的。 -
QtWidgets.QGraphicsItem.PanelModal—1: 面板是模态的(项)。 -
QtWidgets.QGraphicsItem.SceneModal—2: 窗口是模态的(场景)。
setParentItem(QtWidgets.QGraphicsItem): 这将为此项设置由参数指定的父项。
setPos(QtCore.QPointF): 这将为此项设置由参数指定的位置。
setPos(x, y): 这将为此项设置由 x 和 y 坐标指定的位置。
setRotation(float): 这将为此项设置围绕 z 轴的旋转,以度为单位。如果值为正,则项将顺时针旋转;如果值为负,则逆时针旋转。
setScale(float): 这将为此项设置缩放因子。
setSelected(bool): 如果参数为 True,则此项将被选中。
setToolTip("Tool tip"): 这将为此项设置在参数中指定的工具提示。
setTransform(QtGui.QTransform, bool): 这将为此项设置变换矩阵(第一个参数)。如果第二个参数为 True,则矩阵将与当前矩阵合并。
setTransformations([QGraphicsTransform]): 这将为此项设置要应用到此项的图形变换列表。
setTransformOriginPoint(QtCore.QPointF): 这将为此项设置在参数中指定的变换点。
setTransformOriginPoint(x, y): 这将为此项设置由 x 和 y 坐标指定的变换点。
setVisible(bool): 如果参数为 True,则将此项设置为可见。
setX(float): 设置此项目位置的 x 坐标,该坐标由参数指定。
setY(float): 设置此项目位置的 y 坐标,该坐标由参数指定。
setZValue(float): 设置此项目的 Z 值,该值由参数指定。Z 值是兄弟项目的堆叠顺序,其中 Z 值最高的项目位于顶部。
has/is
这些函数返回与图形项目状态相关的布尔值 (bool):
hasCursor(): 如果为此项目设置了光标,则返回 True。
hasFocus(): 如果此项目具有键盘输入焦点,则返回 True。
isActive(): 如果此项目处于活动状态,则返回 True。
isAncestorOf(QtWidgets.QGraphicsItem): 如果此项目是参数中指定的子项目的祖先,则返回 True。
isBlockedByModalPanel(): 如果此项目被模态面板阻塞,则返回 True。
isClipped(): 如果此项目被裁剪,则返回 True。
isEnabled(): 如果此项目处于启用状态,则返回 True。
isObscured(QtCore.QRectF): 如果参数中指定的矩形被此项目上方的任何碰撞项目的非透明形状遮挡,则返回 True。
isObscured(x, y, w, h): 如果从 x/y 开始,宽度为 w,高度为 h 的区域被此项目上方的任何碰撞项目的非透明形状遮挡,则返回 True。
isObscuredBy(QtWidgets.QGraphicsItem): 如果此项目的边界矩形被参数中指定的项目的非透明形状遮挡,则返回 True。
isPanel(): 如果此项目是一个面板,则返回 True。
isSelected(): 如果此项目被选中,则返回 True。
isUnderMouse(): 如果此项目位于鼠标指针下方,则返回 True。
isVisible(): 如果此项目可见,则返回 True。
isVisibleTo(QtWidgets.QGraphicsItem): 如果此项目对参数中指定的父项目可见,则返回 True。
isWidget(): 如果此项目是 QGraphicsWidget 小部件,则返回 True。
isWindow(): 如果此项目是 QGraphicsWidget 窗口,则返回 True。
functional
这些函数返回图形项目的当前值,功能更改等:
acceptDrops(): 如果项目接受拖放事件,则返回 True。
acceptedMouseButtons(): 返回此项目接受鼠标事件时 QtCore.Qt.MouseButtons 类型的鼠标按钮。
acceptHoverEvents(): 如果项目接受悬停事件,则返回 True。
acceptTouchEvents(): 如果项目接受触摸事件,则返回 True。
advance(int): 返回相位。在第一个阶段,所有项目都使用相等于 0 的相位被调用。这意味着场景中的项目即将前进一步,然后所有项目都使用相等于 1 的相位被调用。
boundingRect(): 返回描述此项目外边界的 QtCore.QRectF 类型的矩形。
boundingRegion(QtGui.QTransform): 这返回使用指定参数的项目边界区域。
boundingRegionGranularity(): 这返回项目边界区域的粒度(应该是一个介于 0 和 1 之间的数字)。
cacheMode(): 这返回 QtWidgets.QGraphicsItem.CacheMode 类型的缓存模式。
childItems(): 这返回一个包含此项目子项的列表。
childrenBoundingRect(): 这返回此项目的后代项的边界矩形。
clearFocus(): 这将从该项目中获取键盘输入焦点,并在该项目有焦点的情况下发送焦点外事件。
clipPath(): 这返回此项目的 QtGui.QPainterPath 类型的裁剪路径。
collidesWithItem(QtWidgets.QGraphicsItem, QtCore.Qt.ItemSelectionMode): 如果此项目与第一个参数中的项目碰撞,并且模式(第二个参数)与指定项目相关,则返回 True。
collidesWithPath(QtGui.QPainterPath, QtCore.Qt.ItemSelectionMode): 如果此项目与路径(第一个参数)碰撞,并且模式(第二个参数)与指定路径相关,则返回 True。
collidingItems(QtCore.Qt.ItemSelectionMode): 这返回与该项目碰撞的所有项目的列表。碰撞检测由参数中指定的模式确定。
commonAncestorItem(QtWidgets.QGraphicsItem): 这返回此项目和指定参数中的项目的最近祖先项。
contains(QtCore.QPointF): 如果此项目包含指定参数中的点,则返回 True。
cursor(): 这返回此项目的光标形状。
data(int): 这返回指定参数中指定的键的此项目的自定义数据。
deviceTransform(QtGui.QTransform): 这返回此项目的设备变换矩阵。
effectiveOpacity(): 这返回此项目的有效不透明度,可以是 0.0(完全透明)或 1.0(完全不透明)。
filtersChildEvents(): 如果此项目过滤子事件,则返回 True。
flags(): 这返回用于此项目的标志。
focusItem(): 如果此项目的后代或子项具有输入焦点,则返回 QtWidgets.QGraphicsItem 类型的项目。
focusProxy(): 这返回该项目的 QtWidgets.QGraphicsItem 类型的焦点代理。
grabKeyboard(): 这获取键盘输入。
grabMouse(): 这获取鼠标输入。
graphicsEffect(): 如果此项目存在 QtWidgets.QGraphicsEffect 类型的效果,则返回该效果。
group(): 如果该项目是组的一部分,则返回 QtWidgets.QGraphicsItemGroup 类型的该项目组。
handlesChildEvents(): 如果此项目处理子事件,则返回 True。
hide(): 此函数隐藏项目。
itemChange(QtWidgets.QGraphicsItem.GraphicsItemChange, value): 这会通知自定义项目状态的一部分已更改。更改(第一个参数)是正在更改的项目,新值(第二个参数)都传递过去。
itemTransform(QtWidgets.QGraphicsItem): 这返回一个映射从该项目到参数中指定的项目的坐标的 QtGui.QTransform 类型的转换。
moveBy(float, float): 这将项目水平(第一个参数)和垂直(第二个参数)移动。
opacity(): 这返回项目的局部不透明度,介于 0.0(完全透明)和 1.0(完全不透明)之间。
opaqueArea(): 这返回此项目不透明的 QtGui.QPainterPath 类型的区域。
paint(QtGui.QPainter, QtWidgets.QStyleOptionGraphicsItem, QtWidgets.QWidget): 这使用绘图器(第一个参数)、样式选项(第二个参数)和绘画发生的窗口(可选第三个参数)来绘制项目的内容。
panel(): 这返回此项目的 QtWidgets.QGraphicsItem 类型的面板。
panelModality(): 这返回此项目的 QtWidgets.QGraphicsItem.PanelModality 类型的模式。
parentItem(): 这返回此项目的 QtWidgets.QGraphicsItem 类型的父级项目。
parentObject(): 这返回此项目的 QtWidgets.QGraphicsObject 类型的父级对象。
parentWidget(): 这返回此项目的 QtWidgets.QGraphicsWidget 类型的父级窗口。
pos(): 这返回此项目在父级(或场景)坐标中的 QtCore.QPointF 类型的位置。
prepareGeometryChange(): 这为此项目准备几何更改。
resetTransform(): 这重置此项目的转换矩阵。
rotation(): 这返回此项目的旋转,以度为单位,沿 z 轴顺时针旋转。
scale(): 这返回此项目的缩放因子。
scene(): 这返回对此项目当前有效的 QtWidgets.QGraphicsScene 类型的场景。
sceneBoundingRect(): 这返回此项目在场景坐标中的 QtCore.QRectF 类型的边界矩形。
scenePos(): 这返回此项目在场景坐标中的位置。
sceneTransform(): 这返回此项目场景的 QtGui.QTransform 类型的转换矩阵。
scroll(float, float, QtCore.QRectF): 这通过 x(第一个参数)和 y 值(第二个参数)滚动矩形(第三个参数)的内容。
shape(): 这返回项目的 QtGui.QPainterPath 类型的形状。
show(): 这将显示此项目。
stackBefore(QtWidgets.QGraphicsItem): 这将此项目堆叠在参数中指定的兄弟项目之前。
toGraphicsObject(): 这返回将图形项目转换为 QtWidgets.QGraphicsObject 类型的图形对象。
toolTip(): 这返回此项目的工具提示。
topLevelItem(): 这返回此项目的 QtWidgets.QGraphicsItem 类型的顶级项目。
topLevelWidget(): 这返回此项目的 QtWidgets.QGraphicsWidget 类型的顶级小部件。
transform(): 这返回此项目的 QtGui.QTransform 类型的变换矩阵。
transformations(): 这返回此项目的图形变换列表。
transformOriginPoint(): 这返回此项目 QtCore.QPointF 类型的变换原点。
type(): 这以整数值返回项目的类型。
ungrabKeyboard(): 这释放键盘捕获。
ungrabMouse(): 这释放鼠标捕获。
unsetCursor(): 这取消此项目的光标。
update(QtCore.QRectF): 这安排在此项目中重绘参数指定的区域。
update(x, y, w, h): 这安排从 x/y 开始的区域的重绘,宽度为 w 和高度为 h。
updateMicroFocus(): 这将更新此项目的微焦点。
window(): 这返回此项目的 QtWidgets.QGraphicsWidget 类型的窗口。
zValue(): 这返回此项目的 z 值。
map
这些函数与图形项的映射相关:
mapFromItem(QtWidgets.QGraphicsItem, QtCore.QPointF): 这将把点(第二个参数),映射到项目(第一个参数)的坐标系中,并返回映射后的坐标。
mapFromItem(QtWidgets.QGraphicsItem, QtGui.QPolygonF): 这将把多边形(第二个参数),映射到项目(第一个参数)的坐标系中,并返回映射后的坐标。
mapFromItem(QtWidgets.QGraphicsItem, QtCore.QRectF): 这将把矩形(第二个参数),映射到项目(第一个参数)的坐标系中,并返回映射后的坐标。
mapFromItem(QtWidgets.QGraphicsItem, QtGui.QPainterPath): 这将把路径(第二个参数),映射到项目(第一个参数)的坐标系中,并返回映射后的坐标。
mapFromItem(QtWidgets.QGraphicsItem, x, y): 这将把由 x 和 y 设置的位置的点映射到项目(第一个参数)的坐标系中,并返回映射后的坐标。
mapFromItem(QtWidgets.QGraphicsItem, x, y, w, h): 这将把从 x/y 开始的区域,宽度为 w 和高度为 h,映射到项目(第一个参数)的坐标系中,并将其映射到本项目的坐标系中,并返回映射后的坐标。
mapFromParent(QtCore.QPointF): 这将把参数指定的点映射到项目的父坐标系中,并返回映射后的点。
mapFromParent(QtGui.QPolygonF): 这将参数中指定的多边形(位于项的父坐标系中)映射到该项的坐标系,并返回映射后的多边形。
mapFromParent(QtCore.QRectF): 这将参数中指定的矩形(位于项的父坐标系中)映射到该项的坐标系,并返回映射后的多边形。
mapFromParent(QtGui.QPainterPath): 这将参数中指定的路径(位于项的父坐标系中)映射到该项的坐标系,并返回映射后的路径。
mapFromParent(x, y): 这将位于 x 和 y 位置的点(位于项的父坐标系中)映射到该项的坐标系,并返回映射后的点。
mapFromParent(x, y, w, h): 这将位于 x/y 位置,宽度为 w 和高度为 h 的区域(位于项的父坐标系中)映射到该项的坐标系,并返回映射后的多边形。
mapFromScene(QtCore.QPointF): 这将参数中指定的点(位于项的场景坐标系中)映射到该项的坐标系,并返回映射后的坐标。
mapFromScene(QtGui.QPolygonF): 这将参数中指定的多边形(位于项的场景坐标系中)映射到该项的坐标系,并返回映射后的多边形。
mapFromScene(QtCore.QRectF): 这将参数中指定的矩形(位于项的场景坐标系中)映射到该项的坐标系,并返回映射后的多边形。
mapFromScene(QtGui.QPainterPath): 这将参数中指定的路径(位于项的场景坐标系中)映射到该项的坐标系,并返回映射后的路径。
mapFromScene(x, y): 这将位于 x 和 y 位置的点(位于项的场景坐标系中)映射到该项的坐标系,并返回映射后的点。
mapFromScene(x, y, w, h): 这将位于 x/y 位置,宽度为 w 和高度为 h 的区域(位于项的场景坐标系中)映射到该项的坐标系,并返回映射后的多边形。
mapRectFromItem(QtWidgets.QGraphicsItem, QtCore.QRectF): 这将位于项(第一个参数)坐标系中的矩形(第二个参数)映射到该项的坐标系,并返回新的映射矩形。
mapRectFromItem(QtWidgets.QGraphicsItem, x, y, w, h): 这将位于 x/y 位置,宽度为 w 和高度为 h 的区域(位于项的坐标系中,第一个参数)映射到该项的坐标系,并返回新的映射矩形。
mapRectFromParent(QtCore.QRectF): 这将参数中指定的矩形(在该项目的父坐标系中)映射到该项目的坐标系,并返回新的映射矩形。
mapRectFromParent(x, y, w, h): 这将起始于 x/y,宽度为 w 和高度为 h 的区域(在该项目的父坐标系中)映射到该项目的坐标系,并返回新的映射矩形。
mapRectFromScene(QtCore.QRectF): 这将参数中指定的矩形(在场景坐标系中)映射到该项目的坐标系,并返回新的映射矩形。
mapRectFromScene(x, y, w, h): 这将起始于 x/y,宽度为 w 和高度为 h 的区域(在场景坐标系中)映射到该项目的坐标系,并返回新的映射矩形。
mapRectToItem(QtWidgets.QGraphicsItem, QtCore.QRectF): 这将矩形(第二个参数,即第二个参数),映射到项目(第一个参数,即第一个参数)的坐标系,并返回新的映射矩形。
mapRectToItem(QtWidgets.QGraphicsItem, x, y, w, h): 这将起始于 x/y,宽度为 w 和高度为 h 的区域(在该项目的坐标系中)映射到项目(第一个参数)的坐标系,并返回新的映射矩形。
mapRectToParent(QtCore.QRectF): 这将参数中指定的矩形(在该项目的坐标系中)映射到该项目的父坐标系,并返回新的映射矩形。
mapRectToParent(x, y, w, h): 这将起始于 x/y,宽度为 w 和高度为 h 的区域(在该项目的坐标系中)映射到该项目的父坐标系,并返回新的映射矩形。
mapRectToScene(QtCore.QRectF): 这将参数中指定的矩形(在该项目的坐标系中)映射到场景坐标系,并返回新的映射矩形。
mapRectToScene(x, y, w, h): 这将起始于 x/y,宽度为 w 和高度为 h 的区域(在该项目的坐标系中)映射到场景坐标系,并返回新的映射矩形。
mapToItem(QtWidgets.QGraphicsItem, QtCore.QPointF): 这将点(第二个参数),映射到项目(第一个参数)的坐标系,并返回映射的点。
mapToItem(QtWidgets.QGraphicsItem, QtGui.QPolygonF): 这将多边形(第二个参数),映射到项目(第一个参数)的坐标系,并返回映射的多边形。
mapToItem(QtWidgets.QGraphicsItem, QtCore.QRectF): 将矩形(第二个参数),位于此项目的坐标系中,映射到项目(第一个参数)的坐标系中,并返回映射后的矩形。
mapToItem(QtWidgets.QGraphicsItem, QtGui.QPainterPath): 将路径(第二个参数),位于此项目的坐标系中,映射到项目(第一个参数)的坐标系中,并返回映射后的路径。
mapToItem(QtWidgets.QGraphicsItem, x, y): 将由 x 和 y 设置的位置的点(位于此项目的坐标系中)映射到项目(第一个参数)的坐标系中,并返回映射后的点。
mapToItem(QtWidgets.QGraphicsItem, x, y, w, h): 将从 x/y 开始,宽度为 w 和高度为 h 的区域(位于此项目的坐标系中)映射到项目(第一个参数)的坐标系中,并返回映射后的多边形。
mapToParent(QtCore.QPointF): 将参数中指定的点(位于此项目的坐标系中)映射到此项目父项目的坐标系中,并返回映射后的点。
mapToParent(QtGui.QPolygonF): 将参数中指定的多边形(位于此项目的坐标系中)映射到此项目父项目的坐标系中,并返回映射后的多边形。
mapToParent(QtCore.QRectF): 将参数中指定的矩形(位于此项目的坐标系中)映射到此项目父项目的坐标系中,并返回映射后的矩形
mapToParent(QtGui.QPainterPath): 将参数中指定的路径(位于此项目的坐标系中)映射到此项目父项目的坐标系中,并返回映射后的路径。
mapToParent(x, y): 将由 x 和 y 定位的点(位于此项目的坐标系中)映射到此项目父项目的坐标系中,并返回映射后的点。
mapToParent(QtWidgets.QGraphicsItem, x, y, w, h): 将从 x/y 开始,宽度为 w 和高度为 h 的区域(位于此项目的坐标系中)映射到此项目父项目的坐标系中,并返回映射后的多边形。
mapToScene(QtCore.QPointF): 将参数中指定的点(位于此项目的坐标系中)映射到场景的坐标系中,并返回映射后的点。
mapToScene(QtGui.QPolygonF): 将参数中指定的多边形(位于此项目的坐标系中)映射到场景的坐标系中,并返回映射后的多边形。
mapToScene(QtCore.QRectF): 将参数中指定的矩形(位于此项目的坐标系中)映射到场景的坐标系中,并返回映射后的矩形。
mapToScene(QtGui.QPainterPath): 此函数将位于此项目坐标系中的参数中指定的路径映射到场景坐标系,并返回映射的路径。
mapToScene(x, y): 此函数将位于此项目坐标系中的由 x 和 y 定位的点映射到场景坐标系,并返回映射的点。
mapToScene(x, y, w, h): 此函数将位于此项目坐标系中的以 x/y 为起点,宽度为 w,高度为 h 的区域映射到场景坐标系,并返回映射的多边形。
事件
这些函数与事件相关,例如事件处理器:
contextMenuEvent(QtWidgets.QGraphicsSceneContextMenuEvent): 此事件处理器接收此项目的上下文菜单事件。
dragEnterEvent(QtWidgets.QGraphicsSceneDragDropEvent): 此事件处理器接收此项目针对参数中指定事件的拖动进入事件。
dragLeaveEvent(QtWidgets.QGraphicsSceneDragDropEvent): 此事件处理器接收此项目针对参数中指定事件的拖动离开事件。
dragMoveEvent(QtWidgets.QGraphicsSceneDragDropEvent): 此事件处理器接收此项目针对参数中指定事件的拖动移动事件。
dropEvent(QtWidgets.QGraphicsSceneDragDropEvent): 此事件处理器接收此项目针对参数中指定事件的放下事件。
focusOutEvent(QtGui.QFocusEvent): 此事件处理器接收在失去焦点时带有事件参数传递的键盘焦点事件。
focusInEvent(QtGui.QFocusEvent): 此事件处理器接收在获得焦点时带有事件参数传递的键盘焦点事件。
hoverEnterEvent(QtWidgets.QGraphicsSceneHoverEvent): 此事件处理器接收此项目针对参数中指定事件的悬停进入事件。
hoverLeaveEvent(QtWidgets.QGraphicsSceneHoverEvent): 此事件处理器接收此项目针对参数中指定事件的悬停离开事件。
hoverMoveEvent(QtWidgets.QGraphicsSceneHoverEvent): 此事件处理器接收此项目针对参数中指定的事件的悬停移动事件
inputMethodEvent(QtGui.QInputMethodEvent): 此事件处理器接收此项目的输入法事件。
installSceneEventFilter(QtWidgets.QGraphicsItem): 此函数为此项目安装参数中指定的事件过滤器。
keyPressEvent(QtGui.QKeyEvent): 此事件处理器接收通过参数传递的事件的按键事件为此项目。
keyReleaseEvent(QtGui.QKeyEvent): 此事件处理器接收通过参数传递的事件的按键释放事件为此项目。
mouseDoubleClickEvent(QtWidgets.QGraphicsSceneMouseEvent): 此事件处理器接收通过参数传递的事件的鼠标双击事件为此项目。
mouseMoveEvent(QtWidgets.QGraphicsSceneMouseEvent): 此事件处理器接收此项目的鼠标移动事件,事件通过参数传入。
mousePressEvent(QtWidgets.QGraphicsSceneMouseEvent): 此事件处理器接收此项目的鼠标按下事件,事件通过参数传入。
mouseReleaseEvent(QtWidgets.QGraphicsSceneMouseEvent): 此事件处理器接收此项目的鼠标释放事件,事件通过参数传入。
removeSceneEventFilter(QtWidgets.QGraphicsItem): 这将移除为此项目指定的参数中的事件过滤器。
sceneEvent(QtCore.QEvent): 这接收此项目的事件。
sceneEventFilter(QtWidgets.QGraphicsItem, QtCore.QEvent): 这个过滤器为项目(第一个参数)和过滤事件(第二个参数)过滤事件。
wheelEvent(QtWidgets.QGraphicsSceneWheelEvent): 此事件处理器接收此项目的鼠标滚轮事件,事件通过参数传入。
摘要
在本章中,我们提供了可用于 GUI 应用程序的图形元素最常用类的描述。
在下一章中,我们将描述这些元素的各种图形效果。我们还将介绍在应用程序开发期间实现附加技术的特殊模块。
第十一章:图形效果和多媒体
本章是关于图形实现的上一章的延续。在这里,我们将描述向上一章中使用的图形元素添加一些效果的可能性。Qt 框架提供了我们在使用各种类型的图形实现(如 OpenGL、SVG 和 3D 图形)时最常用的类和模块。类也可供使用,以便您可以将效果添加到标准图形元素,如矩形或其他形状。
在本章中,我们将涵盖以下主题:
-
标准图形效果
-
标准动画和变换
-
额外模块
-
多媒体
标准图形效果
Qt 库提供了标准图形效果,这些效果可以与QGraphicsRectItem和QGraphicsLineItem等项相关使用。效果使应用程序的图形元素更具代表性,并且因此以现代风格呈现。这些效果的资源可以是图像、图片、图形元素、图像/元素的某些部分等。通常,可以使用如下设置函数将效果添加到图形项中:
graphics_item = QtWidgets.QGraphicsRectItem()
blur_effect = QtWidgets.QGraphicsBlurEffect()
graphics_item.setGraphicsEffect(blur_effect)
QGraphicsEffect
此类是所有与 Qt 一起使用的图形效果的基类。QGraphicsEffect类通过以下函数提高了功能。
设置
此函数设置与图形效果相关的参数/属性:
setEnabled(bool): 如果参数为True,则将此效果设置为启用。
is
此函数返回与这些图形效果状态相关的布尔值(bool)。
isEnabled(): 如果此效果被启用,则返回True。
功能性
这些是与图形效果的当前值、功能变化等相关联的函数:
boundingRect(): 这返回此效果的QtCore.QRectF类型的边界矩形。
boundingRectFor(QtCore.QRectF): 这返回QtCore.QRectF类型的边界矩形,该矩形依赖于参数中指定的矩形,以设备坐标形式表示此效果。
draw(QtGui.QPainter): 这用于绘制效果,并在需要绘制时被调用。
drawSource(QtGui.QPainter): 这使用参数中指定的画家直接绘制源。
sourceBoundingRect(QtCore.Qt.CoordinateSystem): 这返回映射到参数中指定的系统上的源边界矩形。
sourceChanged(QtWidgets.QGraphicsEffect.ChangeFlags): 这通知此效果的源已更改,参数中的标志描述了发生了什么变化。可用的标志如下:
-
QtWidgets.QGraphicsEffect.SourceAttached: 效果被安装到源上。 -
QtWidgets.QGraphicsEffect.SourceDetached: 效果从源上卸载。 -
QtWidgets.QGraphicsEffect.SourceBoundingRectChanged:源的边界矩形已更改。 -
QtWidgets.QGraphicsEffect.SourceInvalidated:源的可视外观已更改。
sourceIsPixmap():如果效果源是位图,则返回 True。
sourcePixmap(QtCore.Qt.CoordinateSystem, PySide2.QtCore.QPoint, QtWidgets.QGraphicsEffect.PixmapPadMode):此操作返回一个带有源绘制的 QtGui.QPixmap 类型的位图。第一个参数定义了用于源的坐标系。第二个参数是位图应该绘制的偏移量。填充模式(第三个参数)定义了位图的填充方式。可用的填充模式参数如下:
-
QtWidgets.QGraphicsEffect.NoPad—0:位图不会接收额外的填充。 -
QtWidgets.QGraphicsEffect.PadToTransparentBorder—1:位图将被填充以完全匹配透明边框。 -
QtWidgets.QGraphicsEffect.PadToEffectiveBoundingRect—2:位图将被填充以匹配此效果的有效边界矩形。
update():此操作安排此效果的重新绘制。
updateBoundingRect():当此效果的边界矩形发生变化时,此操作会发出通知。
信号
QGraphicsEffect 类中可用的信号如下:
enabledChanged(bool):当效果根据参数中传入的状态变为启用或禁用时,此信号会被发出。
QGraphicsBlurEffect
此类实现了图形元素的模糊效果。模糊效果会减少源细节。此类的声明语法如下:
blur_effect = QtWidgets.QGraphicsBlurEffect()
QGraphicsBlurEffect 类从 QGraphicsEffect 类继承,并通过以下函数改进了功能。
set
这些是与设置与模糊效果相关的参数/属性相关的函数:
blur_effect.setBlurHints(QtWidgets.QGraphicsBlurEffect.BlurHints):此操作设置此效果的模糊提示,它描述了模糊效果是如何应用的。可用的提示如下:
-
QtWidgets.QGraphicsBlurEffect.PerformanceHint:此操作将渲染性能设置为最重要的因素。 -
QtWidgets.QGraphicsBlurEffect.QualityHint:此操作将渲染质量设置为最重要的因素。 -
QtWidgets.QGraphicsBlurEffect.AnimationHint:这表示模糊半径将进行动画处理。
blur_effect.setBlurRadius(float):此操作为此效果设置模糊半径,由参数指定。较大的半径会产生更模糊的外观,而较小的半径会使外观看起来更锐利。
功能
这些是与模糊效果的当前值、功能变化等相关联的函数:
blur_effect.blurHints():此操作返回用于此模糊效果的 QtWidgets.QGraphicsBlurEffect.BlurHints 类型的提示。
blur_effect.blurRadius():此操作返回此效果的模糊半径。
信号
QGraphicsBlurEffect 类可用的信号如下:
blur_effect.blurHintsChanged(QtWidgets.QGraphicsBlurEffect.BlurHints): 当模糊提示改变时,会发出此信号,新的模糊提示通过参数传入。
blur_effect.blurRadiusChanged(float): 当模糊半径改变时,会发出此信号,新的模糊半径通过参数传入。
QGraphicsColorizeEffect
此类实现了着色功能。此效果会着色源的颜色。此类的声明语法如下:
colorize_effect = QtWidgets.QGraphicsColorizeEffect()
QGraphicsColorizeEffect类继承自QGraphicsEffect类,并通过以下函数改进了功能。
set
这些是与设置着色效果相关参数/属性的函数:
colorize_effect.setColor(QtGui.QColor): 设置用于此着色效果的色彩。
colorize_effect.setStrength(float): 设置效果强度(0.0—无效果,1.0—完全着色)。
functional
这些是与着色效果当前值、功能变化等相关联的函数:
colorize_effect.color(): 返回用于着色此效果的QtGui.QColor类型的颜色。
colorize_effect.strength(): 此函数返回效果强度。
signals
QGraphicsColorizeEffect类的可用信号如下:
colorize_effect.colorChanged(QtGui.QColor): 当效果颜色改变时,会发出此信号,新的颜色通过参数传入。
colorize_effect.strengthChanged(float): 当效果强度改变时,会发出此信号,新的强度通过参数传入。
QGraphicsDropShadowEffect
此类为提供的源提供了阴影效果。此类的声明语法如下:
shadow_effect = QtWidgets.QGraphicsDropShadowEffect()
QGraphicsDropShadowEffect类继承自QGraphicsEffect类,并通过以下函数改进了功能。
set
这些是与设置阴影效果相关参数/属性的函数:
shadow_effect.setBlurRadius(float): 设置此阴影效果的像素模糊半径。
shadow_effect.setColor(QtGui.QColor): 设置此阴影效果的色彩。
shadow_effect.setOffset(QtCore.QPointF): 通过参数设置阴影偏移。
shadow_effect.setOffset(float): 设置参数中指定的阴影偏移。
shadow_effect.setOffset(dx, dy): 通过指定偏移量的dx和dy值来设置阴影偏移。
shadow_effect.setXOffset(float): 通过参数设置像素值来设置水平阴影偏移。
shadow_effect.setYOffset(float): 通过参数设置像素值来设置垂直阴影偏移。
functional
这些是与阴影效果当前值、功能变化等相关联的函数:
shadow_effect.blurRadius(): 返回此阴影效果的像素模糊半径。
shadow_effect.color(): 此函数返回此阴影的颜色,为QtGui.QColor类型。
shadow_effect.offset(): 此函数返回QtCore.QPointF类型的阴影偏移量。
shadow_effect.xOffset(): 此函数返回水平阴影偏移量。
shadow_effect.yOffset(): 此函数返回垂直阴影偏移量。
信号
QGraphicsDropShadowEffect类的可用信号如下:
shadow_effect.blurRadiusChanged(float): 当模糊半径改变时,会发出此信号,新的模糊半径通过参数传入。
shadow_effect.colorChanged(QtGui.QColor): 当效果的颜色改变时,会发出此信号,新的颜色通过参数传入。
shadow_effect.offsetChanged(QtCore.QPointF): 当效果的偏移量改变时,会发出此信号,新的偏移量通过参数传入。
QGraphicsOpacityEffect
这是实现源不透明效果的类。此类的声明语法如下:
opacity_effect = QtWidgets.QGraphicsOpacityEffect()
QGraphicsDropShadowEffect类继承自QGraphicsEffect类,并通过以下函数增强了功能。
设置
这些是与设置与不透明度效果相关的参数/属性相关的函数:
opacity_effect.setOpacity(float): 此函数设置此效果的不透明度(0.0—完全透明,1.0—完全不透明)。
opacity_effect.setOpacityMask(QtGui.QBrush): 此函数设置参数中指定的不透明度蒙版,为此效果允许将不透明度应用于元素的部分。
功能
这些是与不透明度效果的当前值、功能变化等相关联的函数:
opacity_effect.opacity(): 此函数返回此效果的不透明度。
opacity_effect.opacityMask(): 此函数返回此效果QtGui.QBrush类型的不透明度蒙版。
信号
QGraphicsOpacityEffect类的可用信号如下:
opacity_effect.opacityChanged(float): 当不透明度改变时,会发出此信号,新的不透明度通过参数传入。
opacity_effect.opacityMaskChanged(QtGui.QBrush): 当不透明度蒙版改变时,会发出此信号,新的不透明度蒙版通过参数传入。
标准动画和转换
通过 Qt 框架的帮助,效果可以作为标准图形项的动画实现。这些类可以动画化各种项,如QGraphicsEllipseItem、QGraphicsTextItem等。QGraphicsItemAnimation类也可以用于 PySide 绑定。
QGraphicsTransform
这是一个用于构建高级图形项转换的抽象基类。QGraphicsTransform类继承自QObject类,并通过以下函数增强了功能:
applyTo(QtGui.QMatrix4x4): 此函数将此转换应用于参数中指定的矩阵。此方法需要在派生类中重新实现。
update(): 这通知与这个变换操作相关的操作已改变。
QGraphicsRotation
这个类提供了在应用程序中对图形项进行旋转的功能。这个类的声明语法如下:
graphics_rotation = QtWidgets.QGraphicsRotation()
QGraphicsRotation 从 QGraphicsTransform 类继承,并通过以下函数增强了功能。
set
这些是与设置与旋转相关的参数/属性相关的函数:
graphics_rotation.setAngle(float): 这设置这次旋转的角度。180.0 的值将使这个项目顺时针旋转 180 度,而 -180.0 的值将使这个项目逆时针旋转 180 度。
graphics_rotation.setAxis(QtGui.QVector3D): 这设置旋转轴,参数指定为 3D 空间中的向量。该向量可以是 (0, 0, 1),围绕 z 轴旋转(默认),或者 (1, 0, 0),这将使项目围绕 x 轴旋转。
graphics_rotation.setAxis(QtCore.Qt.Axis): 这设置由参数指定的旋转轴。
graphics_rotation.setOrigin(QtGui.QVector3D): 这设置旋转在 3D 空间中的原点。
functional
这些是与当前旋转值的返回值相关的函数:
graphics_rotation.angle(): 这返回了这次旋转的角度(以度为单位)。
graphics_rotation.axis(): 这返回了这次旋转的 QtGui.QVector3D 类型的轴。
graphics_rotation.origin(): 这返回了这次旋转的 QtGui.QVector3D 类型的原点。
signals
QGraphicsRotation 类的可用的信号如下:
graphics_rotation.angleChanged(): 当旋转角度改变时,会发出此信号。
graphics_rotation.axisChanged(): 当旋转轴改变时,会发出此信号。
graphics_rotation.originChanged(): 当旋转的原点改变时,会发出此信号。
QGraphicsScale
这个类提供了图形项的缩放变换。这个类的声明语法如下:
graphics_scale = QtWidgets.QGraphicsScale()
QGraphicsScale 从 QGraphicsTransform 类继承,并通过以下函数增强了功能。
set
这些是与设置与缩放相关的参数/属性相关的函数:
graphics_scale.setOrigin(QtGui.QVector3D): 这设置缩放在 3D 空间中的原点。
graphics_scale.setXScale(float): 这设置由参数指定的水平缩放因子。默认值是 1.0。如果因子是 0.0,则项目将折叠成一个单独的点。如果因子是负值,则项目将在水平方向上镜像。
graphics_scale.setYScale(float): 这设置由参数指定的垂直缩放因子。默认值是 1.0。如果因子是 0.0,则项目将折叠成一个单独的点。如果因子是负值,则项目将在垂直方向上翻转。
graphics_scale.setZScale(float): 这设置参数中指定的深度缩放因子。默认值为 1.0。如果因子为 0.0,项目将折叠成一个点。如果因子是负值,项目将翻转成端到端。
功能
这些是与缩放当前值返回相关的函数:
graphics_scale.origin(): 这返回此缩放的 QtGui.QVector3D 类型的原点。
graphics_scale.xScale(): 这返回水平缩放因子。
graphics_scale.yScale(): 这返回垂直缩放因子。
graphics_scale.zScale(): 这返回深度缩放因子。
信号
QGraphicsScale 类的可用的信号如下:
graphics_scale.originChanged(): 当缩放的原点改变时,会发出此信号。
graphics_scale.scaleChanged(): 当缩放改变时,会发出此信号。
graphics_scale.xScaleChanged(): 当水平缩放改变时,会发出此信号。
graphics_scale.yScaleChanged(): 当垂直缩放改变时,会发出此信号。
graphics_scale.zScaleChanged(): 当深度缩放改变时,会发出此信号。
QGraphicsItemAnimation
在 PySide Python 绑定中,此类实现了与图形项目相关的类的动画支持。此类包括对项目接收动画最有用的操作。此类的声明语法如下:
item_animation = QtWidgets.QGraphicsItemAnimation()
QGraphicsItemAnimation 类通过以下函数增强了功能。
设置
这些是与设置与项目动画相关的参数/属性相关的函数:
item_animation.setItem(QtWidgets.QGraphicsItem): 这将设置在此动画中使用的项目。
item_animation.setPosAt(float, QtCore.QPointF): 这将项目在步骤(第一个参数)的位置设置为点(第二个参数)。
item_animation.setRotationAt(float, float): 这将在步骤(第一个参数)处设置项目的旋转到角度(第二个参数)。
item_animation.setScaleAt(float, float, float): 这将在步骤(第一个参数)处设置项目的缩放,具有水平(第二个参数)和垂直(第三个参数)缩放因子。
item_animation.setShearAt(float, float, float): 这将在步骤(第一个参数)处设置项目的剪切,具有水平(第二个参数)和垂直(第三个参数)剪切因子。
item_animation.setStep(float): 这设置此动画的当前步骤,指定在参数中。变换将在这一步执行。
item_animation.setTimeLine(QtCore.QTimeLine): 这设置由参数指定的时间线,用于控制此动画的速率。
item_animation.setTranslationAt(float, float, float): 这将在步骤(第一个参数)处设置项目的平移,具有水平(第二个参数)和垂直(第三个参数)坐标。
功能性
这些是与项目动画当前值、功能变化等相关联的函数:
item_animation.clear(): 这将清除用于此动画的变换,保留项目和时线。
item_animation.horizontalScaleAt(float): 这将返回在参数指定的步骤中此项目的水平缩放。
item_animation.horizontalShearAt(float): 这将返回在参数指定的步骤中此项目的水平剪切。
item_animation.item(): 这将返回在此动画上操作的类型为 QtWidgets.QGraphicsItem 的项目。
item_animation.matrixAt(float): 这将返回在参数指定的步骤中用于变换项目的 QtGui.QMatrix 类型的矩阵。
item_animation.posAt(float): 这将返回在参数指定的步骤中项目的 QtCore.QPointF 类型的位置。
item_animation.posList(): 这将返回所有显式插入的位置列表。
item_animation.reset(): 这将重置项目的动画到起始位置和变换。
item_animation.rotationAt(float): 这将返回在参数指定的步骤中此项目旋转的角度。
item_animation.rotationList(): 这将返回所有显式插入的旋转列表。
item_animation.scaleList(): 这将返回所有显式插入的缩放列表。
item_animation.shearList(): 这将返回所有显式插入的剪切列表。
item_animation.timeLine(): 这将返回此动画的 QtCore.QTimeLine 类型的时线。
item_animation.translationList(): 这将返回所有显式插入的平移列表。
item_animation.verticalScaleAt(float): 这将返回在参数指定的步骤中项目的垂直缩放。
item_animation.verticalShearAt(float): 这将返回在参数指定的步骤中项目的垂直剪切。
item_animation.xTranslationAt(float): 这将返回在参数指定的步骤中项目的水平平移。
item_animation.yTranslationAt(float): 这将返回在参数指定的步骤中项目的垂直平移。
其他模块
除了我们已描述的图形类之外,Qt 还提供了对 OpenGL 的支持,这体现在 QtGui 模块中的一系列类中。此外,Qt 库还有用于在 GUI 应用程序中处理图形的附加模块。实现图形支持的模块,如 QtSvg、QtCharts、QtDataVisualization 以及 3D 模块,如 Qt3DCore、Qt3DInput、Qt3DLogic、Qt3DRender、Qt3DExtras 和 Qt3DAnimation,在开发中常用。
现在,让我们考虑 QtSvg 模块。如果你想要了解其他模块,建议你阅读文档(PySide2—doc.qt.io/qtforpython/index.html 和 PyQt5—www.riverbankcomputing.com/static/Docs/PyQt5/)。
QtSvg
QtSvg 模块实现了 SVG 图像的处理。SVG 是一种实现二维矢量图形的语言。为了在应用程序中使用,此模块需要使用以下语句导入:
首先,我们有 PySide2 的 import 语句,如下所示:
from PySide2 import QtSvg
然后,我们有 PyQt5 的 import 语句,如下所示:
from PyQt5 import QtSvg
QtSvg 模块包括以下类。
QSvgRenderer
此类使用绘图设备(如 QPaintDevice)从 SVG 文件中绘制内容。声明语法如下:
svg_renderer = QtSvg.QSvgRenderer()
QSvgRenderer 类通过以下函数提高了功能。
set
这些是与设置与 SVG 渲染器相关的参数/属性相关的函数:
svg_renderer.setCurrentFrame(int): 这设置动画中的当前帧。
svg_renderer.setFramesPerSecond(int): 设置每秒要显示的帧数。
svg_renderer.setViewBox(QtCore.QRect): 设置由整数值参数指定的矩形,该矩形将成为文档的可视区域。
svg_renderer.setViewBox(QRectF): 这将设置由浮点值参数指定的矩形,该矩形将成为文档的可视区域。
functional
这些是与 SVG 渲染器当前值返回、功能变化等相关联的函数:
svg_renderer.animated(): 如果包含动画元素,则返回 True。
svg_renderer.animationDuration(): 这返回动画中使用的帧数。
svg_renderer.boundsOnElement(str): 返回参数中指定的 ID 的项的 QtCore.QRectF 类型的边界矩形。
svg_renderer.currentFrame(): 返回动画中的当前帧数。
svg_renderer.defaultSize(): 返回 SVG 文件内容的默认大小。
svg_renderer.elementExists(str): 如果参数中指定的 ID 在 SVG 文件中存在,则返回 True。
svg_renderer.framesPerSecond(): 返回每秒要显示的帧数。
svg_renderer.isValid(): 如果当前文档有效,则返回 True。
svg_renderer.load("Path/to/file.svg"): 加载参数中指定的 SVG 文件,如果内容成功解析,则返回 True。
svg_renderer.load(QtCore.QXmlStreamReader): 加载参数中指定的内容中的 SVG,如果内容成功解析,则返回 True。
svg_renderer.load(QtCore.QByteArray): 加载参数中指定的 SVG 格式内容,如果内容成功解析,则返回 True。
svg_renderer.render(QtGui.QPainter): 这使用参数中指定的画家渲染当前文档或动画文档的当前帧。
svg_renderer.render(QtGui.QPainter, str, QtCore.QRectF): 这使用画家(第一个参数)在边界(第三个参数)上渲染具有 ID(第二个参数)的元素。
svg_renderer.render(QtGui.QPainter, QtCore.QRectF): 这使用画家(第一个参数)在边界(第二个参数)上渲染当前文档。
svg_renderer.viewBox(): 这返回文档的可视区域,作为QtCore.QRect。
svg_renderer.viewBoxF(): 这返回文档的可视区域,作为QtCore.QRectF。
信号
QSvgRenderer类的可用信号如下:
svg_renderer.repaintNeeded(): 当文档渲染需要更新时发出此信号。
QSvgGenerator
此类是 SVG 绘图创建的只写绘图设备。声明语法如下:
svg_generator = QtSvg.QSvgGenerator()
QSvgGenerator类通过以下函数改进了功能。
设置
这些是与设置与 SVG 生成器相关的参数/属性相关的函数:
svg_generator.setDescription(str): 这为生成的 SVG 绘图设置参数中指定的描述。
svg_generator.setFileName("Path/to/file.svg"): 这设置用于生成 SVG 绘图的文件名,指定在参数中。
svg_generator.setOutputDevice(QtCore.QIODevice): 这设置用于生成 SVG 绘图的输出设备,指定在参数中。
svg_generator.setResolution(int): 这设置生成输出的分辨率,以每英寸点数(dpi)为单位,用于计算 SVG 绘图的物理大小。
svg_generator.setSize(QtCore.QSize): 这将设置参数中指定的尺寸,用于生成 SVG 绘图。
svg_generator.setTitle(str): 这设置用于生成 SVG 绘图的标题,指定在参数中。
svg_generator.setViewBox(QtCore.QRect): 这使用参数中指定的整数值设置视图框,用于生成 SVG 绘图。
svg_generator.setViewBox(QtCore.QRectF): 这使用参数中指定的浮点值设置视图框,用于生成 SVG 绘图。
功能
这些是与 SVG 生成器当前值的返回、功能变化等相关联的函数:
svg_generator.description(): 这返回生成的 SVG 绘图的描述。
svg_generator.fileName(): 这返回生成的 SVG 绘图的文件名。
svg_generator.outputDevice(): 这返回用于 SVG 绘图的QtCore.QIODevice类型的输出设备。
svg_generator.resolution(): 这返回生成的输出的分辨率,以 dpi 为单位。
svg_generator.size(): 这返回生成的 SVG 绘图的QtCore.QSize类型的大小。
svg_generator.title(): 这返回生成的 SVG 绘图的标题。
svg_generator.viewBox(): 这返回生成的 SVG 绘图的QtCore.QRect类型的视图框。
svg_generator.viewBoxF(): 这返回生成的 SVG 绘图的QtCore.QRectF类型的视图框。
QGraphicsSvgItem
此类用于渲染 SVG 文件的内容。这可以使用上一章中描述的QGraphicsView类将内容渲染到图形视图中。声明语法如下:
svg_item = QtSvg.QGraphicsSvgItem()
QGraphicsSvgItem类通过以下函数改进了功能。
设置
这些是与设置与 SVG 元素相关的参数/属性相关的函数:
svg_item.setElementId(str): 这将设置由参数指定的元素的 XML ID。
svg_item.setMaximumCacheSize(QtCore.QSize): 这将设置此元素的设备坐标缓存大小的最大值,指定在参数中。
svg_item.setSharedRenderer(QtSvg.QSvgRenderer): 这将渲染器设置为共享。渲染器可以在多个元素上使用。
功能性
这些是与 SVG 元素当前值返回相关的函数:
svg_item.elementId(): 这返回当前渲染元素的 XML ID。
svg_item.maximumCacheSize(): 这返回此元素的设备坐标缓存的最大大小。
svg_item.renderer(): 这返回用于此 SVG 元素的QtSvg.QSvgRenderer类型的当前渲染器。
QSvgWidget
此类使用小部件显示 SVG 文件。声明语法如下:
svg_widget = QtSvg.QSvgWidget()
QSvgWidget类通过以下函数改进了功能。
功能性
这些是与 SVG 小部件当前值返回相关的函数:
svg_widget.load("Path/to/file.svg"): 这将加载由参数指定的 SVG 文件,并更新小部件。
svg_widget.load(QtCore.QByteArray): 这将加载由参数指定的 SVG 格式的内容,并更新小部件。
svg_widget.renderer(): 这返回用于显示 SVG 小部件内容的QtSvg.QSvgRenderer类型的渲染器。
多媒体
Qt 框架为 GUI 应用程序提供音频、视频、收音机和相机功能的多媒体支持。可以帮助你实现这一点的模块是QtMultimedia和QtMultimediaWidgets。QtMultimedia包括用于多媒体的低级别工作的类,而QtMultimediaWidgets可以表示媒体对象的窗口小部件。QtMultimedia模块的QMediaPlayer类可以组织播放媒体源。
Qt 多媒体
QtMultimedia 模块实现了处理多媒体功能,如音频、视频、广播和摄像头。在应用程序中使用此模块时,需要使用以下语句导入。
我们有 PySide2 的 import 语句,如下所示:
from PySide2 import QtMultimedia
我们还有 PyQt5 的 import 语句,如下所示:
from PyQt5 import QtMultimedia
QtMultimedia 模块包括 QAudio、QSound、QRadioTuner 和 QVideoWindowControl 等类。让我们考虑可用的摄像头功能,因为这项技术结合了所有媒体功能。
QMediaObject
这是 QtMultimedia 模块中多媒体对象的基本类。此类提供了其他可以在应用程序中使用的多媒体类继承的基本功能。此类的声明如下:
media_object = QtMultimedia.QMediaObject()
QMediaObject 类通过以下函数提高功能。
add
此函数与向媒体对象添加属性相关:
media_object.addPropertyWatch(QtCore.QByteArray): 这使媒体对象能够监视属性名称。
set
此函数与设置与媒体对象相关的参数/属性相关:
media_object.setNotifyInterval(int): 这设置参数中指定的间隔,以毫秒为单位(默认为 1000),用于更新属性。
is
这些是返回与这些媒体对象状态相关的布尔值 (bool) 的函数:
media_object.isAvailable(): 如果服务可用,则返回 True。
media_object.isMetaDataAvailable(): 如果与该媒体对象关联的元数据可用,则返回 True。
functional
这些是与媒体对象当前值的返回、功能变化等相关联的函数:
media_object.availability(): 这返回由该对象提供的功能可用性,作为 QtMultimedia.QMultimedia.AvailabilityStatus 类型。
media_object.availableMetaData(): 这返回可用于媒体对象元数据的键列表。
media_object.bind(QtCore.QObject): 这将参数中指定的对象绑定到该媒体对象实例。
media_object.metaData(str): 这返回与参数中指定的元数据键关联的值。
media_object.notifyInterval(): 这返回更新属性的间隔。
media_object.removePropertyWatch(QtCore.QByteArray): 这将从属性列表中删除属性名称。
media_object.service(): 这返回提供此多媒体功能的媒体服务。
media_object.unbind(QtCore.QObject): 这将参数中指定的对象从该媒体对象中解绑。
signals
QMediaObject 类的可用的信号如下:
media_object.availabilityChanged(bool): 当此媒体对象的可用状态相对于参数中传入的可用性发生变化时,发出此信号。
media_object.availabilityChanged(QtMultimedia.QMultimedia.AvailabilityStatus): 当此媒体对象的服务可用性相对于传入参数的可用性发生变化时,发出此信号。
media_object.metaDataAvailableChanged(bool): 当此媒体对象的元数据相对于传入参数的可用状态发生变化时,发出此信号。
media_object.metaDataChanged(): 当此媒体对象的元数据发生变化时,发出此信号。
media_object.metaDataChanged(str, object): 当此媒体对象的元数据元素值(第二个参数)的键(第一个参数)发生变化时,发出此信号。
media_object.notifyIntervalChanged(int): 当此媒体对象的通告间隔周期发生变化时,发出此信号,间隔以毫秒为单位,通过参数传入。
QCamera
此类实现了可用系统摄像头设备的接口。在应用程序中实现摄像头功能展示了几乎所有的多媒体机会。以下多媒体类将深入探讨可以与摄像头设备一起使用的各种功能。此类的声明语法如下:
camera = QtMultimedia.QCamera()
QCamera 类通过以下函数提高功能。
设置
这些是与设置摄像头相关参数/属性的函数:
camera.setCaptureMode(QtMultimedia.QCamera.CaptureModes): 为此摄像头设置捕获模式,并配置摄像头捕获的内容,如视频或静态图像。可用的捕获模式如下:
-
QtMultimedia.QCamera.CaptureViewfinder: 仅配置为显示取景器。 -
QtMultimedia.QCamera.CaptureStillImage: 配置为捕获静态帧。 -
QtMultimedia.QCamera.CaptureVideo: 配置为视频捕获。
camera.setViewfinder(QtMultimediaWidgets.QVideoWidget): 将基于视频小部件的摄像头设置为指定的取景器。
camera.setViewfinder(QtMultimediaWidgets.QGraphicsVideoItem): 这将基于视频项设置摄像头,并指定了取景器。
camera.setViewfinder(QtMultimedia.QAbstractVideoSurface): 将参数中指定的视频表面设置为摄像头的取景器。
camera.setViewfinderSettings(QtMultimedia.QCameraViewfinderSettings): 设置参数中指定的取景器设置。
是
此函数返回与摄像头状态相关的布尔值 (bool):
camera.isCaptureModeSupported(QtMultimedia.QCamera.CaptureModes): 如果在参数中指定的捕获模式受支持,则返回 True。
功能性
这些是与当前摄像头值的返回、功能变化等相关的函数:
camera.availableDevices(): 返回从默认服务提供商可用的摄像头设备列表。
camera.captureMode(): 这返回了该相机的 QtMultimedia.QCamera.CaptureModes 类型的捕获模式,以及相机的捕获配置,例如视频或静态图像。
camera.deviceDescription(QtCore.QByteArray): 这返回了该相机设备的描述。
camera.error(): 这返回了该相机设备的 QtMultimedia.QCamera.Error 类型的错误状态。可能发生的错误如下:
-
QtMultimedia.QCamera.NoError—0: 无错误。 -
QtMultimedia.QCamera.CameraError—1: 发生错误。 -
QtMultimedia.QCamera.InvalidRequestError—2: 系统资源不支持请求的功能。 -
QtMultimedia.QCamera.ServiceMissingError—3: 没有相机服务可用。 -
QtMultimedia.QCamera.NotSupportedFeatureError—4: 该功能不受支持。
camera.errorString(): 这返回了该相机设备的错误状态描述字符串。
camera.exposure(): 这返回了该相机的曝光控制对象。
camera.focus(): 这返回了该相机的焦点控制对象。
camera.imageProcessing(): 这返回了该相机的图像处理控制对象。
camera.load(): 这打开该相机设备。相机的状态变为 QCamera.LoadedStatus。它用于读取和更改支持的相机设置和功能。
camera.lockStatus(): 这返回了请求的相机设置锁定状态的 QtMultimedia.QCamera.LockStatus 类型。可能返回的锁定状态如下:
-
QtMultimedia.QCamera.Unlocked—0: 未锁定。 -
QtMultimedia.QCamera.Searching—1: 正在聚焦或计算曝光和白平衡。 -
QtMultimedia.QCamera.Locked—2: 准备捕获。
camera.lockStatus(QtMultimedia.QCamera.LockType): 这返回了指定参数的锁定类型的锁定状态。可用的锁定类型如下:
-
QtMultimedia.QCamera.NoLock: 无锁定。 -
QtMultimedia.QCamera.LockExposure: 锁定曝光。 -
QtMultimedia.QCamera.LockWhiteBalance: 锁定白平衡。 -
QtMultimedia.QCamera.LockFocus: 锁定焦点。
camera.requestedLocks(): 这返回了请求的锁定类型。
camera.searchAndLock(): 这锁定所有支持的相机设置。
camera.searchAndLock(QtMultimedia.QCamera.LockTypes): 这将根据参数指定的请求锁定相机。
camera.start(): 这启动了该相机设备。
camera.state(): 这返回了该相机对象的 QtMultimedia.QCamera.State 类型的当前状态。可能返回的状态如下:
-
QtMultimedia.QCamera.UnloadedState—0: 初始相机状态。 -
QtMultimedia.QCamera.LoadedState—1: 相机已加载并准备好配置。 -
QtMultimedia.QCamera.ActiveState—2: 相机已准备好捕获。
camera.status(): 这返回了该相机对象的 QtMultimedia.QCamera.Status 类型的当前状态。可能返回的状态如下:
-
QtMultimedia.QCamera.UnavailableStatus—0: 相机不可用。 -
QtMultimedia.QCamera.UnloadedStatus—1: 相机未加载。 -
QtMultimedia.QCamera.LoadingStatus—2: 相机正在加载。 -
QtMultimedia.QCamera.UnloadingStatus—3: 相机正在卸载。 -
QtMultimedia.QCamera.LoadedStatus—4: 相机已加载并准备好配置。 -
QtMultimedia.QCamera.StandbyStatus—5: 相机处于节能待机模式。 -
QtMultimedia.QCamera.StartingStatus—6: 相机正在启动。 -
QtMultimedia.QCamera.StoppingStatus—7: 相机正在停止。 -
QtMultimedia.QCamera.ActiveStatus—8: 相机已启动并可产生数据。
camera.stop(): 这停止相机。相机状态从ActiveState变为LoadedState。
camera.supportedLocks(): 这返回支持此相机设备的锁类型。
camera.supportedViewfinderFrameRateRanges(QtMultimedia.QCameraViewfinderSettings): 这返回支持此相机设备的取景器帧率范围列表。
camera.supportedViewfinderPixelFormats(QtMultimedia.QCameraViewfinderSettings): 这返回支持此相机设备的取景器像素格式列表。
camera.supportedViewfinderResolutions(QtMultimedia.QCameraViewfinderSettings): 这返回支持此相机设备的取景器分辨率列表。
camera.supportedViewfinderSettings(QtMultimedia.QCameraViewfinderSettings): 这返回支持此相机设备的取景器设置列表。
camera.unload(): 这通过将相机状态更改为UnloadedStatus来关闭相机并释放相关资源。
camera.unlock(): 这将解锁所有相机锁。
camera.unlock(QtMultimedia.QCamera.LockTypes): 这将解锁参数中指定的相机设置。
camera.viewfinderSettings(): 这返回由相机使用的QtMultimedia.QCameraViewfinderSettings类型的取景器设置。
信号
QCamera类的可用信号如下:
camera.captureModeChanged(QtMultimedia.QCamera.CaptureModes): 当捕获模式改变时,会发出此信号。
camera.error(): 当错误状态发生变化时,会发出此信号。
camera.error(QtMultimedia.QCamera.Error): 当错误状态变为参数中传递的值时,会发出此信号。
camera.locked(): 当所有请求的相机设置都锁定时,会发出此信号。
camera.lockFailed(): 当至少一个请求的相机设置锁定失败时,会发出此信号。
camera.lockStatusChanged(QtMultimedia.QCamera.LockStatus, QtMultimedia.QCamera.LockChangeReason): 当所有请求的相机锁的整体状态(第一个参数)在没有原因(第二个参数)的情况下发生变化时,会发出此信号。可用的更改原因参数如下:
-
QtMultimedia.QCamera.UserRequest—0: 锁定状态因用户请求而改变。 -
QtMultimedia.QCamera.LockAcquired—1:锁定状态成功更改为Locked。 -
QtMultimedia.QCamera.LockFailed—2:无法获取请求的锁定。 -
QtMultimedia.QCamera.LockLost—3:无法维持请求的锁定;状态更改为Unlocked。 -
QtMultimedia.QCamera.LockTemporaryLost—4:锁定丢失,但相机正在努力重新获取它。
camera.stateChanged(QtMultimedia.QCamera.State):当参数中指定的相机状态改变时,会发出此信号。
camera.statusChanged(QtMultimedia.QCamera.Status):当参数中指定的相机状态改变时,会发出此信号。
QCameraFocusZone
此类提供了有关用于自动对焦相机的区域的信息。将使用的区域和区域位置取决于相机的功能。这可以用于在相机框架的焦点区域周围绘制矩形,或用于更改区域颜色。该类的声明如下:
camera_focus_zone = QtMultimedia.QCameraFocusZone()
QCameraFocusZone 类通过以下函数增强了功能。
set
此函数与设置与相机焦点区域相关的参数/属性相关:
camera_focus_zone.setStatus(QtMultimedia.QCameraFocusZone.FocusZoneStatus):此函数设置参数中指定的此相机焦点区域的状态。可用的焦点区域参数如下:
-
QtMultimedia.QCameraFocusZone.Invalid—0:区域无效。 -
QtMultimedia.QCameraFocusZone.Unused—1:区域未使用但可用。 -
QtMultimedia.QCameraFocusZone.Selected—2:区域用于自动对焦,但不在焦点上。 -
QtMultimedia.QCameraFocusZone.Focused—3:区域用于自动对焦,并且处于焦点上。
is
此函数返回与这些相机焦点区域状态相关的布尔值 (bool):
camera_focus_zone.isValid():如果相机焦点区域具有有效的区域和状态,则返回 True。
functional
这些是与相机焦点区域的当前值相关的函数:
camera_focus_zone.area():此函数返回相机框架的 QtCore.QRectF 类型区域,该区域包含此焦点区域。
camera_focus_zone.status():此函数返回此相机焦点区域的 QtMultimedia.QCameraFocusZone.FocusZoneStatus 类型的当前状态。
QCameraImageCapture
这是一个用于从相机设备记录媒体内容的类。该类的声明如下:
camera_image_capture = QtMultimedia.QCameraImageCapture()
QCameraImageCapture 类通过以下函数增强了功能。
set
这些是与设置与相机图像捕获相关的参数/属性相关的函数:
camera_image_capture.setBufferFormat(QtMultimedia.QVideoFrame.PixelFormat):此函数设置参数中指定的将使用的缓冲图像捕获格式。
camera_image_capture.setCaptureDestination(QtMultimedia.QCameraImageCapture.CaptureDestinations): 设置将使用的参数中指定的捕获目标。可用的捕获目标如下:
-
QtMultimedia.QCameraImageCapture.CaptureToFile: 将捕获到文件。 -
QtMultimedia.QCameraImageCapture.CaptureToBuffer: 将捕获到缓冲区。
camera_image_capture.setEncodingSettings(QtMultimedia.QImageEncoderSettings): 这将设置参数中指定的图像编码设置。
is
这些是返回与这些相机图像捕获状态相关的布尔值(bool)的函数:
camera_image_capture.isAvailable(): 如果图像捕获准备就绪,则返回True。
camera_image_capture.isCaptureDestinationSupported(QtMultimedia.QCameraImageCapture.CaptureDestinations): 如果参数中指定的图像捕获目标受支持,则返回True。
camera_image_capture.isReadyForCapture(): 如果服务准备捕获图像,则返回True。
functional
这些是与当前相机图像捕获的返回值、功能变化等相关联的函数:
camera_image_capture.availability(): 返回此功能QtMultimedia.QMultimedia.AvailabilityStatus类型的可用性。
camera_image_capture.bufferFormat(): 返回使用的QtMultimedia.QVideoFrame.PixelFormat类型的缓冲区图像捕获格式。
camera_image_capture.cancelCapture(): 这将取消不完整的捕获请求。
camera_image_capture.capture("Full/Path/to/the/folder/filename.jpg"): 捕获图像并将其保存到参数中指定的文件。
camera_image_capture.captureDestination(): 返回使用的QtMultimedia.QCameraImageCapture.CaptureDestinations类型的图像捕获目标。
camera_image_capture.encodingSettings(): 返回使用的QtMultimedia.QImageEncoderSettings类型的图像编码设置。
camera_image_capture.error(): 返回QtMultimedia.QCameraImageCapture.Error类型的错误状态。
camera_image_capture.errorString(): 返回错误状态作为字符串描述。
camera_image_capture.imageCodecDescription(str): 返回参数中指定的图像编解码器的描述。
camera_image_capture.supportedBufferFormats(): 返回支持的缓冲区图像捕获格式列表。
camera_image_capture.supportedImageCodecs(): 返回支持的图像编解码器列表。
signals
QCameraImageCapture类的可用信号如下:
camera_image_capture.bufferFormatChanged(QtMultimedia.QVideoFrame.PixelFormat): 当传递给参数的缓冲区格式,用于缓冲区图像捕获时,会发出此信号。
camera_image_capture.captureDestinationChanged(QtMultimedia.QCameraImageCapture.CaptureDestinations): 当传入参数的捕获目标更改时,发出此信号。
camera_image_capture.imageAvailable(int, QtMultimedia.QVideoFrame): 当带有请求 ID(第一个参数)的帧(第二个参数)可用时,发出此信号。
camera_image_capture.imageCaptured(int, QtGui.QImage): 当带有请求 ID(第一个参数)的帧(第二个参数)被捕获时,发出此信号。
camera_image_capture.imageExposed(int): 当在参数中指定的带有请求 ID 的帧曝光时,发出此信号。
camera_image_capture.imageMetadataAvailable(int, str, object): 当带有请求 ID(第一个参数)的图像的元数据可用时,发出此信号,包括元数据的键(第二个参数)和值(第三个参数)。
camera_image_capture.imageSaved(int, str): 当带有请求 ID(第一个参数)的帧被保存到文件名(第二个参数)时,发出此信号。
camera_image_capture.readyForCaptureChanged(bool): 当相机准备参数按指定方式更改时,发出此信号,以指示捕获状态。
QCameraInfo
此类表示有关可用相机设备的一般信息。此类的声明语法如下:
camera_info = QtMultimedia.QCameraInfo()
QCameraInfo 类通过以下函数增强了功能:
camera_info.availableCameras(QtMultimedia.QCamera.Position): 此函数返回位于参数中指定位置的可用相机列表。可用于此函数的位置如下:
-
QtMultimedia.QCamera.UnspecifiedPosition—0: 相机位置未指定。 -
QtMultimedia.QCamera.BackFace—1: 相机位于设备屏幕的对面。 -
QtMultimedia.QCamera.FrontFace—2: 相机位于设备屏幕的同侧。
camera_info.defaultCamera(): 此函数返回默认相机。
camera_info.description(): 此函数返回有关相机的描述。
camera_info.deviceName(): 此函数返回相机的名称,作为唯一标识符。
camera_info.isNull(): 如果 QCameraInfo 为空或无效,则返回 True。
camera_info.orientation(): 此函数返回该相机传感器的物理方向角度。
camera_info.position(): 此函数返回该相机在硬件系统上的 QtMultimedia.QCamera.Position 类型的物理位置。
QCameraViewfinderSettings
此类提供了可以通过 QCamera 类设置的取景器设置。此类的声明如下:
viewfinder_settings = QtMultimedia.QCameraViewfinderSettings()
QCameraViewfinderSettings 类通过以下函数增强了功能。
set
这些是与设置取景器设置相关的参数/属性设置函数:
viewfinder_settings.setMaximumFrameRate(float): 这将设置取景器的最大帧率,参数指定以每秒帧数的形式。
viewfinder_settings.setMinimumFrameRate(float): 这将设置取景器的最小帧率,参数指定以每秒帧数的形式。
viewfinder_settings.setPixelAspectRatio(QtCore.QSize): 这将设置取景器的像素宽高比,格式由参数指定。
viewfinder_settings.setPixelAspectRatio(int, int): 这将设置取景器的像素宽高比,水平(第一个参数)和垂直(第二个参数)元素。
viewfinder_settings.setPixelFormat(QtMultimedia.QVideoFrame.PixelFormat): 这将设置取景器的像素格式,格式由参数指定。
viewfinder_settings.setResolution(QtCore.QSize): 这将设置取景器的分辨率,格式由参数指定。
viewfinder_settings.setResolution(w, h): 这将设置取景器由 w(宽度)和 h(高度)指定的分辨率。
is
此函数返回与这些取景器设置状态相关的布尔值 (bool):
viewfinder_settings.isNull(): 如果取景器设置是 null,则返回 True。
functional
这些是与取景器设置当前值、功能变化等相关联的函数:
viewfinder_settings.maximumFrameRate(): 这返回取景器的最大帧率,以每秒帧数的形式。
viewfinder_settings.minimumFrameRate(): 这返回取景器的最小帧率,以每秒帧数的形式。
viewfinder_settings.pixelAspectRatio(): 这返回取景器的 QtCore.QSize 类型的像素宽高比。
viewfinder_settings.pixelFormat(): 这返回取景器 QtMultimedia.QVideoFrame.PixelFormat 类型的像素格式。
viewfinder_settings.resolution(): 这返回取景器的 QtCore.QSize 类型的分辨率。
viewfinder_settings.swap(QtMultimedia.QCameraViewfinderSettings): 这将交换此取景器的设置与参数指定的取景器设置。
QtMultimediaWidgets
QtMultimediaWidgets 模块实现了构建的多媒体对象的可视化。为了在应用程序中使用此模块,需要使用以下语句导入。
我们有 PySide2 的 import 语句,如下所示:
from PySide2 import QtMultimediaWidgets
我们还有 PyQt5 的 import 语句,如下所示:
from PyQt5 import QtMultimediaWidgets
QtMultimediaWidgets 模块包括 QCameraViewfinder 和 QGraphicsVideoItem 等类。
QVideoWidget
此类表示由媒体对象产生的视频小部件。此类的声明语法如下:
video_widget = QtMultimedia.QVideoWidget()
QVideoWidget 类通过以下函数提高了功能。
set
这些是与视频小部件相关的设置参数/属性的函数:
video_widget.setAspectRatioMode(QtCore.Qt.AspectRatioMode): 这将设置由该参数指定的模式,表示视频如何缩放到其纵横比。
video_widget.setBrightness(int): 这将设置由该参数指定的亮度值,用于在此视频小部件中显示的视频。有效值介于 -100 和 100 之间。
video_widget.setContrast(int): 这将设置由该参数指定的对比度值,用于在此视频小部件中显示的视频。有效值介于 -100 和 100 之间。
video_widget.setFullScreen(bool): 如果参数为 True,则显示的视频将处于全屏模式。
video_widget.setHue(int): 这将设置由该参数指定的色调值,用于在此视频小部件中显示的视频。有效值介于 -100 和 100 之间。
video_widget.setMediaObject(QtMultimedia.QMediaObject): 这将设置由该参数指定的媒体对象,该对象将由该视频小部件显示。
video_widget.setSaturation(int): 这将设置由该参数指定的饱和度值,用于在此视频小部件中显示的视频。有效值介于 -100 和 100 之间。
functional
这些是与视频小部件当前值返回相关的函数:
video_widget.aspectRatioMode(): 这将返回 QtCore.Qt.AspectRatioMode 类型的纵横比模式。
video_widget.brightness(): 这将返回显示的视频的亮度。
video_widget.contrast(): 这将返回显示的视频的对比度。
video_widget.hue(): 这将返回显示的视频的色调。
video_widget.mediaObject(): 这将返回由该视频小部件显示的媒体对象。
video_widget.saturation(): 这将返回显示的视频的饱和度。
events
这些是与事件相关的函数,例如事件处理程序:
video_widget.event(QtCore.QEvent): 这接收视频小部件的事件,如果事件被识别并处理,则应返回 True。
video_widget.hideEvent(QtGui.QHideEvent): 这是一个事件处理程序,旨在接收视频小部件的隐藏事件,事件通过参数传递。
video_widget.moveEvent(QtGui.QMoveEvent): 这是一个事件处理程序,旨在接收视频小部件的移动事件,事件通过参数传递。
video_widget.paintEvent(QtGui.QPaintEvent): 这是一个事件处理程序,旨在接收视频小部件的绘制事件,事件通过参数传递。
video_widget.resizeEvent(QtGui.QResizeEvent): 这是一个事件处理程序,旨在接收视频小部件的调整大小事件,事件通过参数传递。
video_widget.showEvent(QtGui.QShowEvent): 这是一个事件处理程序,旨在接收视频小部件的显示事件,事件通过参数传递。
signals
QVideoWidget 类的可用信号如下:
video_widget.brightnessChanged(int):当传入参数的亮度调整发生变化时,会发出此信号。
video_widget.contrastChanged(int):当传入参数的对比度调整发生变化时,会发出此信号。
video_widget.fullScreenChanged(bool):当视频小部件的全屏模式发生变化时,会发出此信号,模式的有效性通过参数传入。
video_widget.hueChanged(int):当传入参数的色调调整发生变化时,会发出此信号。
video_widget.saturationChanged(int):当传入参数的饱和度调整发生变化时,会发出此信号。
相机示例
为了在 GUI 应用程序中演示多媒体功能,我们将使用具有简单功能(如捕获图像)的相机。在应用程序中使用相机是最受欢迎和解释最详尽的多媒体形式。首先,在App/App_PySide2/和App/App_PyQt5/目录中创建u_media.py文件。然后,在这些目录中创建camera/文件夹,并在其中创建一个captures/文件夹以保存捕获的图像。路径将是App/App_PySide2/camera/captures/和App/App_PyQt5/camera/captures/。将以下行插入到u_media.py文件中:
- 在 PyQt5 的情况下,将以下内容插入到
u_media.py文件的import部分:
...
import os
from PyQt5 import QtMultimedia, QtMultimediaWidgets
from PyQt5 import QtWidgets, QtCore, QtGui
from u_style import UBut1
...
- 在 PySide2 的情况下,将以下内容插入到
u_media.py文件的import部分:
...
import os
from PySide2 import QtMultimedia, QtMultimediaWidgets
from PySide2 import QtWidgets, QtCore, QtGui
from u_style import UBut1
...
- 使用继承自
QVideoWidget的QCameraViewfinder类创建UMedia类:
...
class UMedia(QtMultimediaWidgets.QCameraViewfinder):
def __init__(self, parent=None):
super(UMedia, self).__init__(parent)
self.setWindowTitle("U Camera")
win_icon = QtGui.QIcon("Icons/python1.png")
self.setWindowIcon(win_icon)
self.setWindowOpacity(1)
self.camera = QtMultimedia.QCamera()
self.camera.setViewfinder(self)
self.camera.start()
self.cambut1 = UBut1(self, pad=10)
self.cambut1.setText("Capture")
self.cambut1.setVisible(False)
self.cambut1.clicked.connect(self.img_capture)
self.vc_grid = QtWidgets.QGridLayout()
self.vc_grid.addWidget(self.cambut1, 0, 0, 1, 1)
self.vc_grid.setAlignment(QtCore.Qt.AlignTop)
self.setLayout(self.vc_grid)
...
...
在这个类中,我们已经添加了相机实例,设置了取景器,添加了一个按钮,并使用网格布局排列了所有元素。
- 将捕获图像的函数添加到此类中:
...
...
def img_capture(self):.
image_capture = QtMultimedia.QCameraImageCapture(
self.camera)
image_capture.setCaptureDestination(
QtMultimedia.QCameraImageCapture.CaptureToFile)
self.camera.setCaptureMode(
QtMultimedia.QCamera.CaptureStillImage)
filename = os.path.dirname(os.path.abspath(__file__))
camera_path = os.path.join(filename, "camera/captures/")
image_capture.capture(os.path.normpath(camera_path))
...
...
如果按钮被点击,将会调用此函数。当前相机帧将被捕获并保存到captures/文件夹中。
- 在
img_capture()函数之后,将进入事件处理程序添加到UMedia类中:
...
...
def enterEvent(self, event):
self.cambut1.setVisible(True)
...
...
如果鼠标指针进入小部件区域,按钮将显示出来。
- 为此小部件添加离开事件处理程序:
...
...
def leaveEvent(self, event):
self.cambut1.setVisible(False)
...
如果鼠标指针离开小部件的区域,按钮将不可见。
- 尽可能使用
subprocesses模块使用此文件。将以下行添加到u_media.py文件中:
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
uap_vc = UMedia()
uap_vc.show()
sys.exit(app.exec_())
如果此文件以应用程序窗口或使用subprocess模块启动,则此指令将被实现。如果此文件的类作为另一个应用程序的一部分使用,则不会使用此指令。
现在,在u_app.py文件中插入以下行:
- 在
UApp类结束时,添加以下函数:
...
...
def video_camera(self):
subprocess.Popen(["python", r"u_media.py"])
...
...
此函数将作为子进程运行u_media.py文件。
- 在
UApp类的__init__()函数结束时,暂时添加以下行以调用video_camera函数:
...
def __init__(self, parent=None):
...
self.video_camera()
...
...
这将在应用程序启动时调用带有子进程的函数。
- 最后,在
u_app.py文件的末尾,我们可以添加对subprocessPython 标准库模块的import,如下所示:
if __name__ == "__main__":
import sys, subprocess
...
现在,我们可以运行 u_app.py 文件,并尝试从摄像头设备捕获图像,如下面的截图所示:

当我们点击捕获按钮时,当前帧将被捕获并保存为图像文件到 captures/ 文件夹。需要注意的是,摄像头(视频和音频)功能取决于个人设备的性能以及已安装编解码器的可用性。因此,建议您收集有关可用于应用程序开发的设备和编解码器的信息。可以使用提供更多与摄像头设备和图像/视频处理相关功能的第三方包,如 OpenCV,在应用程序中实现摄像头功能。
摘要
本章完成了我们对基本图形的考察。接下来的章节将扩展这一功能,包括特殊任务。Qt 库拥有最广泛的模块、类和工具集,可用于处理图形,因为它就是这种库的形式。一般来说,框架中代表的大部分类都与这个相关。了解可用于 GUI 开发的 Qt 库中的基本图形原理也非常重要。
下一章将继续介绍 Qt 类,并涵盖基本对话框窗口。
第十二章:文件、打印机和其他对话框
任何具有 GUI 的应用程序都是为了产生操作而创建的。为了以用户友好的方式完成此操作,它需要具备一些基本功能,例如打开和保存文件的能力,在处理某些内容时通知用户,或者在出现错误时通知用户。为了在应用程序中实现这一点,我们可以使用各种打开和保存文件并通知用户事件已发生的对话框窗口。此外,如果用户的任务与文本处理相关,他们可能希望将文本打印成纸质形式或保存到文件中,例如 PDF。在本章中,我们将介绍 Qt 库提供的基本对话框窗口,并在应用程序中演示一些简单的打印实现,包括以下内容:
-
对话框窗口
-
消息框
-
字体和颜色对话框
-
文件
-
打印机
对话框窗口
对话框窗口最常用于实现用户与应用程序进程之间的通信。这些对话框窗口可以打开和保存文件,显示错误消息,允许用户在打印前更改打印机的设置,选择颜色和字体,等等。Qt 库为应用程序提供了最流行的对话框窗口。对话框窗口是一种可以是模态或非模态的小部件。模态对话框窗口在可视化时阻止其他应用程序窗口的输入。相比之下,非模态对话框窗口独立于应用程序窗口提供其功能。在此,我们将介绍对话框窗口的基类,即QDialog。此外,我们还将检查其他类,例如QDialogButtonBox,它构建按钮框。
QDialog
此类是 Qt 中使用的对话框窗口的基类。几乎所有功能对话框都继承了这个类。其声明语法如下:
dialog = QtWidgets.QDialog()
QDialog类通过以下各节中描述的函数增强了功能。
设置
这些函数将参数或属性设置到对话框窗口中:
dialog.setModal(bool): 如果参数为True,则设置此对话框窗口为模态。
dialog.setResult(int): 此操作将对话框窗口的结果代码设置为参数中指定的代码。
dialog.setSizeGripEnabled(bool): 如果参数为True,则设置QSizeGrip类型的大小调整手柄以调整顶级窗口的大小。
dialog.setVisible(bool): 如果参数为True,则设置此对话框窗口为可见。
是
此函数返回与该对话框窗口状态相关的布尔值(bool):
dialog.isSizeGripEnabled(): 如果此对话框窗口启用了大小调整手柄,则返回True。
功能性
这些函数返回对话框窗口的当前值,通知您有关功能更改的信息,等等:
dialog.accept(): 此操作接受对话框,并将结果代码设置为Accepted,以隐藏模态对话框窗口。
dialog.done(int): 这关闭对话框,并根据参数中指定的代码设置结果代码。
dialog.exec(): 这将显示并执行模态对话框,并返回对话框结果代码。
dialog.exec_(): 这将显示并执行模态对话框,并返回对话框结果代码。
dialog.open(): 这将打开并显示模态对话框窗口。
dialog.reject(): 当模态对话框隐藏时,此操作拒绝对话框并将结果代码设置为Rejected。
dialog.result(): 这返回模态对话框的结果代码,例如Accepted或Rejected。
events
这些函数与事件相关,例如事件处理程序:
dialog.closeEvent(QtGui.QCloseEvent): 当接收到对话框窗口关闭请求时,此事件处理程序会使用事件参数被调用。
dialog.contextMenuEvent(QtGui.QContextMenuEvent): 此事件处理程序接收对话框窗口的上下文菜单事件。
dialog.eventFilter(QtCore.QObject, QtCore.QEvent): 如果对话框窗口被安装为对象的(第一个参数)事件过滤器,则此事件处理程序将过滤事件。
dialog.keyPressEvent(QtGui.QKeyEvent): 此事件处理程序接收带有参数传递的事件的对话框窗口按键事件。
dialog.resizeEvent(QtGui.QResizeEvent): 此事件处理程序接收带有参数传递的事件的对话框窗口大小调整事件。
dialog.showEvent(QtGui.QShowEvent): 此事件处理程序接收带有参数传递的事件的对话框窗口显示事件。
signals
这些是QDialog类的可用信号:
dialog.accepted(): 当对话框被用户接受,或者通过调用accept()和done()函数时,会发出此信号。
dialog.finished(int): 当用户或通过调用accept()、done()和reject()函数设置对话框的结果代码时,会发出此信号。
dialog.rejected(): 当对话框被用户拒绝,或者通过调用reject()和done()函数时,会发出此信号。
消息框
消息框用于通知用户应用程序中发生的事件。这些可以是带有消息、错误和其他事件的窗口。这些小部件是对话框窗口,它们提供与这些事件相关的功能。
QMessageBox
此类通过询问与过程相关的问题并接收答案来实现用户与应用程序之间的通信。该框使用模态对话框窗口表示形式构建。此类的声明语法如下:
mesage_box = QtWidgets.QMessageBox()
QMessageBox类继承自QDialog类,并通过以下各节中描述的函数增强了功能。
add
这些函数向消息框添加元素:
message_box.addButton(QtWidgets.QMessageBox.StandardButton): 这将在消息框中添加一个标准按钮,并返回一个按钮。
message_box.addButton(QtWidgets.QAbstractButton, QtWidgets.QMessageBox.ButtonRole): 这将在消息框中添加一个按钮(第一个参数)并带有角色(第二个参数)。按钮角色如下:
-
QtWidgets.QMessageBox.Ok: 带有AcceptRole的确定按钮。 -
QtWidgets.QMessageBox.Open: 带有AcceptRole的打开按钮。 -
QtWidgets.QMessageBox.Save: 带有AcceptRole的保存按钮。 -
QtWidgets.QMessageBox.Cancel: 带有RejectRole的取消按钮。 -
QtWidgets.QMessageBox.Close: 带有RejectRole的关闭按钮。 -
QtWidgets.QMessageBox.Discard: 带有DestructiveRole的丢弃或不要保存(平台相关)按钮。 -
QtWidgets.QMessageBox.Apply: 带有ApplyRole的应用按钮。 -
QtWidgets.QMessageBox.Reset: 带有ResetRole的重置按钮。 -
QtWidgets.QMessageBox.RestoreDefaults: 带有ResetRole的恢复默认按钮。 -
QtWidgets.QMessageBox.Help: 带有HelpRole的帮助按钮。 -
QtWidgets.QMessageBox.SaveAll: 带有AcceptRole的全部保存按钮。 -
QtWidgets.QMessageBox.Yes: 带有YesRole的是按钮。 -
QtWidgets.QMessageBox.YesToAll: 带有YesRole的全部是按钮。 -
QtWidgets.QMessageBox.No: 带有NoRole的否按钮。 -
QtWidgets.QMessageBox.NoToAll: 带有NoRole的全部否按钮。 -
QtWidgets.QMessageBox.Abort: 带有RejectRole的中止按钮。 -
QtWidgets.QMessageBox.Retry: 带有AcceptRole的重试按钮。 -
QtWidgets.QMessageBox.Ignore: 带有AcceptRole的忽略按钮。 -
QtWidgets.QMessageBox.NoButton: 这是一个无效的按钮。
message_box.addButton(str, QtWidgets.QMessageBox.ButtonRole): 这将在消息框中添加一个带有文本(第一个参数)和角色(第二个参数)的按钮,并返回一个推按钮。
set
这些函数设置消息框的参数或属性:
message_box.setCheckBox(QtWidgets.QCheckBox): 这将在消息框对话框中设置参数中指定的复选框。
message_box.setDefaultButton(QtWidgets.QPushButton): 这将为消息框设置参数中指定的默认按钮。
message_box.setDefaultButton(QtWidgets.QMessageBox.StandardButton): 这将为消息框设置参数中指定的默认按钮。
message_box.setDetailedText(str): 这将设置消息框中指定的参数详细文本。详细文本是纯文本,将在详细信息区域显示。
message_box.setEscapeButton(QtWidgets.QAbstractButton): 这将设置参数中指定的按钮,当按下 Esc 键时将被激活。
message_box.setEscapeButton(QtWidgets.QMessageBox.StandardButton): 这将设置参数中指定的按钮,当按下 Esc 键时将被激活。
message_box.setIcon(QtWidgets.QMessageBox.Icon): 这将设置与消息框一起使用的图标。可用的图标如下:
-
QtWidgets.QMessageBox.NoIcon—0: 消息框不显示图标。 -
QtWidgets.QMessageBox.Information—1: 显示信息标志的图标。 -
QtWidgets.QMessageBox.Warning—2: 显示警告标志的图标。 -
QtWidgets.QMessageBox.Critical—3: 显示临界问题标志的图标。 -
QtWidgets.QMessageBox.Question—4: 显示问题标志的图标。
message_box.setIconPixmap(QtGui.QPixmap): 这为消息框的图标设置参数中指定的位图。
message_box.setInformativeText(str): 这设置参数中指定的信息文本,它将是消息框中消息的完整描述。
message_box.setStandardButtons(QtWidgets.QMessageBox.StandardButtons): 这将设置参数中指定的标准按钮,这些按钮将在消息框中使用。
message_box.setText("Message Box Text"): 这设置参数中指定的文本,该文本将在消息框中显示。
message_box.setTextFormat(QtCore.Qt.TextFormat): 这为消息框中将显示的文本设置参数中指定的文本格式。
message_box.setTextInteractionFlags(QtCore.Qt.TextInteractionFlags): 这设置参数中指定的文本交互标志,它将描述标签与用户输入的交互。
message_box.setWindowModality(QtCore.Qt.WindowModality): 这为消息框设置参数中指定的模式。
message_box.setWindowTitle(str): 这为这个对话框窗口消息框设置参数中指定的标题。
功能性
这些函数返回消息框的当前值,通知您关于功能的变化,等等:
message_box.about(QtWidgets.QWidget, str, str): 这显示一个带有标题(第二个参数)和文本(第三个参数)关于第一个参数的简单框。
message_box.aboutQt(QWidget, str): 这显示一个带有标题(第二个参数)关于 Qt 的简单框。
message_box.button(QtWidgets.StandardButton): 这返回与参数中指定的按钮对应的QtWidgets.QAbstractButton类型的按钮。
message_box.buttonRole(QtWidgets.QAbstractButton): 这返回参数中指定的按钮的QtWidgets.QMessageBox.ButtonRole类型的按钮角色。
message_box.buttons(): 这返回添加到消息框中的所有按钮的列表。
message_box.checkBox(): 这返回消息框上可用的QtWidgets.QCheckBox类型的复选框;否则返回0。
message_box.clickedButton(): 这返回被点击的QtWidgets.QAbstractButton类型的按钮。
message_box.critical(QtWidgets.QWidget, str, str, QtWidgets.QMessageBox.StandardButton, QtWidgets.QMessageBox.StandardButton): 这将打开一个带有标题(第二个参数)、一些文本(第三个参数)的临界消息框,文本位于指定的小部件(第一个参数)之前,并且包含第四个和第五个参数指定的按钮。
message_box.defaultButton(): 这返回消息框的 QtWidgets.QPushButton 类型的默认按钮。
message_box.detailedText(): 这返回在详细信息区域显示的纯文本。
message_box.escapeButton(): 这返回当用户按下 Esc 键时将被激活的按钮。
message_box.icon(): 这返回与消息框一起使用的 QtWidgets.QMessageBox.Icon 类型的图标。
message_box.iconPixmap(): 这返回当前 QtGui.QPixmap 类型的图标位图。
message_box.information(QtWidgets.QWidget, str, str, QtWidgets.QMessageBox.StandardButton, QtWidgets.QMessageBox.StandardButton): 这将在指定的窗口(第一个参数)前打开一个带有标题(第二个参数)、一些文本(第三个参数)的信息消息框,并使用第四个和第五个参数指定的按钮。
message_box.informativeText(): 这返回信息文本,例如消息框中消息的完整描述。
message_box.open(QtCore.QObject, str): 这将一个信号连接到一个槽,接收器(第一个参数)和成员(第二个参数)。
message_box.question(QtWidgets.QWidget, str, str, QtWidgets.QMessageBox.StandardButton, QtWidgets.QMessageBox.StandardButton): 这将在指定的窗口(第一个参数)前打开一个带有标题(第二个参数)、一些文本(第三个参数)的问题消息框,并使用第四个和第五个参数指定的按钮。
message_box.removeButton(QtWidgets.QAbstractButton): 这将从消息框中移除指定的参数中的按钮。
message_box.standardButton(QtWidgets.QAbstractButton): 这返回与参数指定的按钮相对应的 QtWidgets.QMessageBox.StandardButton 类型的按钮。
message_box.standardButtons(): 这返回与消息框一起使用的 QtWidgets.QMessageBox.StandardButtons 类型的标准按钮。
message_box.standardIcon(QtWidgets.QMessageBox.Icon): 这返回用于消息框标准图标的 QtGui.QPixmap 类型的位图。
message_box.text(): 这返回在消息框中显示的文本。
message_box.textFormat(): 这返回用于消息框中文本的 QtCore.Qt.TextFormat 类型的格式。
message_box.textInteractionFlags(): 这返回用于消息框文本交互的 QtCore.Qt.TextInteractionFlags 类型的标志。
message_box.warning(QtWidgets.QWidget, str, str, QtWidgets.QMessageBox.StandardButton, QtWidgets.QMessageBox.StandardButton): 这将在指定的窗口(第二个参数)前打开一个带有标题(第二个参数)、一些文本(第三个参数)的警告消息框,并使用第四个和第五个参数指定的按钮。
事件
这些函数与事件相关,例如事件处理器:
message_box.changeEvent(QtCore.QEvent): 这处理消息框的状态变化。
message_box.closeEvent(QtGui.QCloseEvent): 当窗口系统收到消息框的关闭请求时,会调用带有事件参数的事件处理器。
message_box.event(QtCore.QEvent): 这接收发送给对象的的事件,如果事件被识别并处理,则应返回True。
message_box.keyPressEvent(QtGui.QKeyEvent): 此事件处理器接收传递给参数的消息框的按键事件。
message_box.resizeEvent(QtGui.QResizeEvent): 此事件处理器接收传递给参数的消息框的尺寸变化事件。
message_box.showEvent(QtGui.QShowEvent): 此事件处理器接收传递给参数的消息框的显示事件。
signals
QMessageBox类有以下可用信号:
message_box.buttonClicked(QtWidgets.QAbstractButton): 当在消息框内部点击按钮时,会发出此信号。
QErrorMessage
此类显示错误消息对话框窗口。应用程序中可能会发生错误,此窗口会通知用户这些事件。此类的声明语法如下:
error_message = QtWidgets.QErrorMessage()
QErrorMessage继承自QDialog类,并通过以下章节中描述的函数增强了其功能。
functional
这些函数返回错误消息对话框的当前值,通知您有关功能的变化,等等:
error_message.qtHandler(): 这会返回一个QtWidgets.QErrorMessage类型的对象,该对象输出默认的 Qt 消息。
error_message.showMessage(str): 这会显示参数中指定的消息。
error_message.showMessage(str, str): 这会显示一个消息(第一个参数),并带有请求的消息类型(第二个参数)。
events
这些函数与事件相关,例如事件处理器:
error_message.changeEvent(QtCore.QEvent): 这处理错误消息对话框的状态变化。
字体和颜色对话框
Qt 框架为应用程序提供了标准对话框,用于选择字体和颜色。它们可以用来更改某些文本的字体或元素的色彩。
QFontDialog
此类实现了字体选择对话框。所选字体可用于文本字段、标签以及其他应用程序元素。此类的声明语法如下:
font_dialog = QtWidgets.QFontDialog()
QFontDialog继承自QDialog类,并通过以下章节中描述的函数增强了其功能:
set
这些函数设置字体对话框的参数或属性:
font_dialog.setCurrentFont(QtGui.QFont): 这会将参数中指定的字体设置为字体对话框中的高亮字体。
font_dialog.setOption(QtWidgets.QFontDialog.FontDialogOption, bool): 如果第二个参数为True,则设置字体对话框选项。可用的选项如下:
-
QtWidgets.QFontDialog.NoButtons: 无按钮的字体对话框 -
QtWidgets.QFontDialog.DontUseNativeDialog: 作为 Qt 标准实现的字体对话框 -
QtWidgets.QFontDialog.ScalableFonts: 带有可缩放字体的字体对话框 -
QtWidgets.QFontDialog.NonScalableFonts: 带有不可缩放字体的字体对话框 -
QtWidgets.QFontDialog.MonospacedFonts: 带有等宽字体的字体对话框 -
QtWidgets.QFontDialog.ProportionalFonts: 带有比例字体的字体对话框
font_dialog.setOptions(QtWidgets.QFontDialog.FontDialogOptions): 这将设置将用于字体对话框的选项。
功能
这些函数返回字体对话框的当前值,通知您有关功能更改等更多信息:
font_dialog.currentFont(): 此函数返回QtGui.QFont类型的当前字体。
font_dialog.getFont(QtWidgets.QWidget): 此函数返回字体并执行模态字体对话框,指定对话框的父窗口。
font_dialog.getFont(QtGui.QFont, QtWidgets.QWidget, str, QtWidgets.QFontDialog.FontDialogOptions): 此函数返回字体并执行模态字体对话框。如果用户点击 OK 按钮,则返回所选字体。如果用户点击取消,则返回初始字体(第一个参数)。它由父窗口小部件(第二个参数)、对话框窗口的标题(第三个参数)和选项(第四个参数)构成。
font_dialog.open(QtCore.QObject, str): 这将信号连接到槽,其中接收器(第一个参数)和成员(第二个参数)。
font_dialog.options(): 此函数返回用于字体对话框的QtWidgets.QFontDialog.FontDialogOptions类型的选项。
font_dialog.selectedFont(): 通过点击 OK 按钮或以其他方式接受时,此函数返回QtGui.QFont类型的所选字体。
font_dialog.testOption(QtWidgets.QFontDialog.FontDialogOption): 如果参数中指定的字体对话框选项被启用,则此函数返回True;否则,它返回False。
事件
此函数与事件相关:
font_dialog.changeEvent(QtCore.QEvent): 这处理字体对话框的状态变化。
信号
QFontDialog类的可用信号如下:
font_dialog.currentFontChanged(QtGui.QFont): 当字体对话框的当前字体更改时,会发出此信号,并通过参数传递新字体。
font_dialog.fontSelected(QtGui.QFont): 当在字体对话框中选择字体时,会发出此信号,并通过参数传递所选字体。
QColorDialog
此类创建一个用于选择颜色的对话框窗口。所选颜色可用于着色文本、应用程序窗口或其他元素。此类的声明语法如下:
color_dialog = QtWidgets.QColorDialog()
QColorDialog类继承自QDialog类,并通过以下各节中描述的函数增强了其功能。
设置
这些函数设置颜色对话框的参数和属性:
color_dialog.setCurrentColor(QtGui.QColor): 这设置将在颜色对话框中高亮显示的颜色(在参数中指定)。
color_dialog.setCustomColor(int, QtGui.QColor): 这设置在索引(第一个参数)处的自定义颜色(第二个参数)。
color_dialog.setOption(QtWidgets.QColorDialog.ColorDialogOption, bool): 如果第二个参数为 True,则设置颜色对话框选项。可用的选项如下:
-
QtWidgets.QColorDialog.NoButtons: 无按钮的颜色对话框。 -
QtWidgets.QColorDialog.DontUseNativeDialog: 作为 Qt 标准的颜色对话框。 -
QtWidgets.QColorDialog.ShowAlphaChannel: 可以选择颜色的 alpha 成分。
color_dialog.setOptions(QtWidgets.QFontDialog.FontDialogOptions): 这设置将用于颜色对话框的选项。
color_dialog.setStandardColor(int, QtGui.QColor): 这在索引(第一个参数)处设置标准颜色(第二个参数)。
功能
这些函数返回颜色对话框的当前值,通知您有关功能性的更改,等等:
color_dialog.currentColor(): 这返回 QtGui.QColor 类型的当前颜色。
color_dialog.customColor(int): 这返回在参数中指定的索引处的 QtGui.QColor 类型的自定义颜色。
color_dialog.customCount(): 这返回颜色对话框支持的自定义颜色的数量。
color_dialog.getFont(QtGui.QColor, QtWidgets.QWidget, str, QtWidgets.QColorDialog.ColorDialogOptions): 这返回颜色并执行模态颜色对话框。当用户点击“确定”按钮时,它返回所选颜色。如果用户点击“取消”,则返回初始颜色(第一个参数)。它是通过父小部件(第二个参数)、对话框窗口的标题(第三个参数)和选项(第四个参数)构建的。
color_dialog.open(QtCore.QObject, str): 这将信号连接到具有接收器(第一个参数)和成员(第二个参数)的槽。
color_dialog.options(): 这返回用于此颜色对话框的 QtWidgets.QColorDialog.ColorDialogOptions 类型的选项。
color_dialog.selectedColor(): 通过点击或按下“确定”按钮或以其他方式接受,返回 QtGui.QColor 类型的所选颜色。
color_dialog.standardColor(int): 这返回在参数中指定的索引处的 QtGui.QColor 类型的标准颜色。
color_dialog.testOption(QtWidgets.QColorDialog.ColorDialogOption): 如果参数中指定的颜色对话框选项被启用,则返回 True;否则,返回 False。
事件
这些函数与以下事件相关:
color_dialog.changeEvent(QtCore.QEvent): 这处理颜色对话框的状态变化。
信号
QColorDialog 类可用的信号如下:
-
color_dialog.currentColorChanged(QtGui.QColor): 当颜色对话框的当前颜色发生变化时,会发出此信号,新颜色通过参数传递。 -
color_dialog.colorSelected(QtGui.QColor): 当在颜色对话框中选择颜色时,会发出此信号,所选颜色通过参数传递。
文件
在本节中,我们将描述提供在应用程序中打开或保存文件功能的对话框窗口。此外,我们还将涵盖文件的读取和写入。几乎所有的 GUI 应用程序都可以操作或具有操作各种文件的能力。在 Qt 库中,此文件对话框窗口可以通过QFileDialog类实现。
QFileDialog
此类创建一个对话框窗口,用于在应用程序中进行基本的文件操作,例如打开文件、以指定名称保存文件或打开包含文件的目录。此类在应用程序中的声明语法如下:
file_dialog = QtWidgets.QFileDialog()
QFileDialog类继承自QDialog类,并通过以下各节中描述的函数增强了其功能。
设置
这些函数用于设置文件对话框的参数或属性:
file_dialog.setAcceptMode(QtWidgets.QFileDialog.AcceptMode): 这将对话框的接受模式设置为参数中指定的模式,这解释了文件对话框用于打开或保存文件。可用的模式如下:
-
QtWidgets.QFileDialog.AcceptOpen—0: 打开文件的对话框。 -
QtWidgets.QFileDialog.AcceptSave—1: 保存文件的对话框。
file_dialog.setDefaultSuffix(str): 这将为文件设置默认后缀,该后缀由参数指定,例如.txt或.py扩展名。
file_dialog.setDirectory(str): 这将文件对话框的当前目录设置为参数中指定的目录。
file_dialog.setDirectory(QtCore.QDir): 这将文件对话框的当前目录设置为参数中指定的目录。
file_dialog.setDirectoryUrl(QtCore.QUrl): 这将文件对话框的当前目录 URL 设置为参数中指定的 URL。
file_dialog.setFileMode(QtWidgets.QFileDialog.FileMode): 这将文件对话框的文件模式设置为参数中指定的模式。它描述了可以选择的文件的数量和类型。可用的模式如下:
-
QtWidgets.QFileDialog.AnyFile—0: 任何文件名。 -
QtWidgets.QFileDialog.ExistingFile—1: 如果存在,则单个文件名。 -
QtWidgets.QFileDialog.Directory—2: 目录名。 -
QtWidgets.QFileDialog.ExistingFiles—3: 如果存在,则一个或多个文件名。
file_dialog.setFilter(QtCore.QDir.Filters): 这将用于定义要显示的文件类型的过滤器设置为参数中指定的过滤器。
file_dialog.setHistory([str]): 这将文件对话框的浏览历史设置为参数中指定的路径列表。
file_dialog.setIconProvider(QtWidgets.QFileIconProvider): 这设置与文件对话框一起使用的图标提供者,该提供者由参数指定。
file_dialog.setItemDelegate(QtWidgets.QAbstractItemDelegate): 这设置用于在文件对话框视图中的项目渲染的项代理,该代理由参数指定。
file_dialog.setLabelText(QtWidgets.QFileDialog.DialogLabel, str): 这设置将显示在标签(第一个参数)中的文本(第二个参数)。
file_dialog.setMimeTypeFilters([str]): 这设置参数中指定的过滤器,作为文件对话框中将使用的多用途互联网邮件扩展(MIME)类型的列表。
file_dialog.setNameFilter(str): 这设置参数中指定的过滤器,作为文件对话框中将使用的文件类型。
file_dialog.setNameFilters([str]): 这设置参数中指定的过滤器,作为文件对话框中将使用的文件类型的列表。
file_dialog.setOption(QtWidgets.QFileDialog.Option, bool): 如果第二个参数是True,则设置将用于文件对话框的选项(第一个参数)。
file_dialog.setOptions(QtWidgets.QFileDialog.Options): 这设置将用于文件对话框的选项。
file_dialog.setProxyModel(QtCore.QAbstractProxyModel): 这设置视图的模型为参数中指定的代理模型。
file_dialog.setSidebarUrls([QtCore.QUrl]): 这设置文件对话框侧边栏的 URL,该 URL 由参数指定。
file_dialog.setSupportedSchemes([str]): 这设置文件对话框允许用户导航的 URL 方案。
file_dialog.setViewMode(QtWidgets.QFileDialog.ViewMode): 这设置用于在文件对话框中显示目录和文件的视图模式,该模式由参数指定。可用的模式如下:
-
QtWidgets.QFileDialog.Detail—0: 目录中每个项目的图标、名称和详细信息。 -
QtWidgets.QFileDialog.List—1: 目录中每个项目的图标和名称。
functional
这些函数返回文件对话框的当前值,通知您有关功能更改等:
file_dialog.acceptMode(): 这返回文件对话框的QtWidgets.QFileDialog.AcceptMode类型的接受模式。
file_dialog.defaultSuffix(): 如果未指定其他后缀,则返回添加为文件名扩展名的默认后缀。
file_dialog.directory(): 这返回与文件对话框一起显示的QtCore.QDir类型的目录。
file_dialog.directoryUrl(): 这返回与文件对话框一起显示的目录的QtCore.QUrl类型的 URL。
file_dialog.fileMode(): 这返回与对话框一起使用的QtWidgets.QFileDialog.FileMode类型的文件模式。
file_dialog.filter(): 这返回用于在此对话框中显示文件时使用的QtCore.QDir.Filters类型的过滤器。
file_dialog.getExistingDirectory(QtWidgets.QWidget, str, str, QtWidgets.QFileDialog.Options): 这将创建一个模态文件对话框,包含父窗口(第一个参数)、标题(第二个参数)、工作目录(第三个参数)和选项(第四个参数)。它返回所选的目录。可用的选项如下:
-
QtWidgets.QFileDialog.ShowDirsOnly: 文件对话框只显示目录。 -
QtWidgets.QFileDialog.DontUseNativeDialog: 文件对话框使用 Qt 标准对话框。 -
QtWidgets.QFileDialog.DontResolveSymlinks: 文件对话框不会解析符号链接。 -
QtWidgets.QFileDialog.DontConfirmOverwrite: 如果选中了现有文件,文件对话框不会要求确认覆盖。 -
QtWidgets.QFileDialog.ReadOnly: 模态对话框为只读。 -
QtWidgets.QFileDialog.HideNameFilterDetails: 文件对话框隐藏文件名过滤器详情。 -
QtWidgets.QFileDialog.DontUseCustomDirectoryIcons: 文件对话框使用默认目录图标。
file_dialog.getExistingDirectoryUrl(QtWidgets.QWidget, str, QtCore.QUrl, QtWidgets.QFileDialog.Options, [str]): 这将创建一个模态文件对话框,包含父窗口(第一个参数)、标题(第二个参数)、工作本地/远程目录(第三个参数)、选项(第四个参数)以及限制 URL 的受支持方案(第五个参数)。它返回所选的QtCore.QUrl类型的目录。
file_dialog.getOpenFileName(QtWidgets.QWidget, str, str, str, str, QtWidgets.QFileDialog.Options): 这将创建一个模态文件对话框,包含父窗口(第一个参数)、标题(第二个参数)、工作目录(第三个参数)、文件过滤器(第四个参数)以及这些文件的选定过滤器(第五个参数)和选项(第六个参数)。它返回所选的文件。
file_dialog.getOpenFileNames(QtWidgets.QWidget, str, str, str, str, QtWidgets.QFileDialog.Options): 这将创建一个模态文件对话框,包含父窗口(第一个参数)、标题(第二个参数)、工作目录(第三个参数)、文件过滤器(第四个参数)以及这些文件的选定过滤器(第五个参数)和选项(第六个参数)。它返回一个或多个选定的文件。
file_dialog.getOpenFileUrl(QtWidgets.QWidget, str, QtCore.QUrl, str, str, QtWidgets.QFileDialog.Options, [str]): 这将创建一个模态文件对话框,包含父窗口(第一个参数)、标题(第二个参数)、工作本地/远程目录(第三个参数)、文件过滤器(第四个参数)以及这些文件的选定过滤器(第五个参数)、选项(第六个参数)以及限制 URL 的受支持方案(第七个参数)。它返回所选的文件。
file_dialog.getOpenFileUrls(QtWidgets.QWidget, str, QtCore.QUrl, str, str, QtWidgets.QFileDialog.Options, [str]): 这创建一个模态文件对话框,具有父对象(第一个参数)、标题(第二个参数)、工作本地/远程目录(第三个参数)、用于这些文件的过滤器(第四个参数)、用于这些文件的选定过滤器(第五个参数)、选项(第六个参数)以及用于限制 URL 的支持方案(第七个参数)。它返回一个或多个选定的文件。
file_dialog.getSaveFileName(QtWidgets.QWidget, str, str, str, str, QtWidgets.QFileDialog.Options): 这创建一个模态文件对话框,具有父对象(第一个参数)、标题(第二个参数)、工作目录(第三个参数)、用于这些文件的过滤器(第四个参数)、用于这些文件的选定过滤器(第五个参数)和选项(第六个参数)。它返回一个文件名,并且这个文件名不应已经存在。
file_dialog.getSaveFileUrl(QtWidgets.QWidget, str, QtCore.QUrl, str, str, QtWidgets.QFileDialog.Options, [str]): 这创建一个模态文件对话框,具有父对象(第一个参数)、标题(第二个参数)、工作本地/远程目录(第三个参数)、用于这些文件的过滤器(第四个参数)、用于这些文件的选定过滤器(第五个参数)、选项(第六个参数)以及用于限制 URL 的支持方案(第七个参数)。它返回一个文件名。
file_dialog.history(): 这返回文件对话框的浏览历史记录,作为一个路径列表。
file_dialog.iconProvider(): 这返回文件对话框的 QtWidgets.QFileIconProvider 类型的图标提供者。
file_dialog.itemDelegate(): 这返回用于在文件对话框的视图中渲染项的 QtWidgets.QAbstractItemDelegate 类型的项代理。
file_dialog.labelText(QtWidgets.QFileDialog.DialogLabel): 这返回文件对话框中指定参数的标签显示的文本。
file_dialog.mimeTypeFilters(): 这返回文件对话框的 MIME 类型过滤器。
file_dialog.nameFilters(): 这返回文件对话框的文件类型过滤器。
file_dialog.open(QtCore.QObject, str): 这将一个信号连接到一个槽,其中接收器(第一个参数)是一个成员(第二个参数)。
file_dialog.options(): 这返回用于文件对话框的 QtWidgets.QFileDialog.Options 类型的选项。
file_dialog.proxyModel(): 这返回与文件对话框一起使用的 QtCore.QAbstractProxyModel 类型的代理模型。
file_dialog.restoreState(QtCore.QByteArray): 这将文件对话框的布局、历史记录和当前目录恢复到参数中指定的状态。
file_dialog.saveState(): 这保存文件对话框的布局、历史记录和当前目录。
file_dialog.selectFile(str): 这将选择文件对话框参数中指定的文件名。
file_dialog.selectMimeTypeFilter(str): 这将选择文件对话框参数中指定的 MIME 类型过滤器。
file_dialog.selectNameFilter(str): 这将选择文件对话框参数中指定的文件类型过滤器。
file_dialog.selectUrl(QtCore.QUrl): 这将选择文件对话框参数中指定的 URL。
file_dialog.selectedFiles(): 这将返回文件对话框中选定的文件,作为包含绝对路径的字符串列表。
file_dialog.selectedMimeTypeFilter(): 这将返回文件对话框中选定的文件的 MIME 类型。
file_dialog.selectedNameFilter(): 这将返回文件对话框中选定的过滤器。
file_dialog.selectedUrls(): 这将返回文件对话框中选定的文件 URL 列表。
file_dialog.sidebarUrls(): 这将返回当前侧边栏的 URL 列表。
file_dialog.supportedSchemes(): 这将返回支持的 URL 方案列表。
file_dialog.testOption(QtWidgets.QFileDialog.Option): 如果参数中指定的选项已启用文件对话框,则返回True;否则,返回False。
file_dialog.viewMode(): 这将返回与文件对话框一起使用的QtWidgets.QFileDialog.ViewMode类型的视图模式。
事件
此函数与事件相关:
file_dialog.changeEvent(QtCore.QEvent): 这处理文件对话框的状态变化。
信号
QFileDialog类的可用信号如下:
file_dialog.currentChanged(str): 当文件对话框中的当前文件在本地操作中更改时,会发出此信号。新文件路径作为参数传递。
file_dialog.currentUrlChanged(QtCore.QUrl): 当文件对话框中的当前文件更改时,会发出此信号。新文件的 URL 作为参数传递。
file_dialog.directoryEntered(str): 当用户在文件对话框中进入目录进行本地操作时,会发出此信号,目录作为参数传递。
file_dialog.directoryUrlEntered(QtCore.QUrl): 当用户在文件对话框中进入目录时,会发出此信号,目录的 URL 作为参数传递。
file_dialog.fileSelected(str): 当文件对话框中的选择更改并且对话框被接受时,会发出此信号,选定的文件作为参数传递。
file_dialog.filesSelected([str]): 当文件对话框中的选择更改并且对话框被接受时,会发出此信号,选定的文件列表作为参数传递。
file_dialog.filterSelected(str): 当在文件对话框中选择过滤器时,会发出此信号。选定的过滤器作为参数传递。
file_dialog.urlSelected(QtCore.QUrl): 当文件对话框中的选择发生变化并且对话框被接受时,会发出此信号,所选 URL 作为参数传递。
file_dialog.urlsSelected(QtCore.QUrl): 当文件对话框中的选择发生变化并且对话框被接受时,会发出此信号,所选 URL 列表作为参数传递。
文件对话框示例
为了在我们的应用程序中实现文件对话框,我们将使用 Python 标准库工具打开和读取选定的文件。此外,应用程序文本字段的文本将被保存到文件对话框指定的文件中。为此,我们需要在u_app.py文件中使用以下行添加files()函数:
- 在
UApp类底部添加一个名为files()的函数:
...
...
def files(self, action):
fd = QtWidgets.QFileDialog()
if action.text() == "Open":
fdf = fd.getOpenFileNames(
self, caption="Open Files",
directory=QtCore.QDir.homePath())
...
...
...
此函数将使用QFileDialog类的getOpenFileNames()静态方法来实现打开可用文件的文件对话框。
- 现在将调用
files()函数的信号添加到UApp类的__init__()函数底部:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.mb1.triggered.connect(self.files) # Calling files function.
...
...
...
顶部面板菜单使用triggered()信号调用与文件操作相关的函数。我们可以通过在应用程序顶部的文件选项中选择“打开”来运行u_app.py文件。文件对话框窗口将类似于以下截图:

- 现在我们需要添加 Python 标准库工具来打开和读取此文件对话框返回的文件。
要实现这一点,请将以下行添加到files()函数中:
...
...
def files(self, action):
...
if action.text() == "Open":
...
if len(fdf[0]) > 0:
self.text_edit.clear()
for of in fdf[0]:
self.tabwid.setCurrentIndex(2)
try:
openf = open(of, 'r')
self.text_edit.append(str(openf.read()))
continue
except Exception
pass
try:
openf = open(of, 'rb')
self.text_edit.append(str(openf.read()))
except Exception:
pass
...
...
...
当点击“打开”按钮时,文件对话框将返回带有路径的所选文件或文件。Python 标准库有一个名为open()的内置函数,该函数用于打开文件进行读写。此open()函数将为所选文件列表中的每个循环打开文件,读取该文件,并将内容追加到应用程序的文本字段中。结果如下:

- 现在将以下行添加到
files函数中,以实现使用文件对话框保存文件的功能:
...
...
def files(self, action):
...
if action.text() == "Open":
...
if action.text() == "Save":
fdf = fd.getSaveFileName(self,
caption="Save Files",
directory=QtCore.QDir.homePath())
if fdf[0] != "":
self.tabwid.setCurrentIndex(2)
try:
open(fdf[0], 'w').write(
self.text_edit.toPlainText())
success = True
except Exception:
pass
if success != True:
try:
open(fdf[0], 'wb').write(
self.text_edit.toPlainText())
success = True
except Exception:
pass
if success == True:
self.info_message(fpath=fdf[0],
txt="File saved as", types="info")
else:
self.info_message(fpath=fdf[0],
txt="File don`t saved",
types="critical")
...
...
当选择“保存”选项时,将显示类似的文件对话框。我们可以选择目录和文件名,并将文本字段的文本保存到该文件中。我们可以在App/App_PySide2/和App/App_PyQt5/中的saved_files/文件夹内创建文件夹以保存文件。
- 将
info_message()函数添加到UApp类底部,以通知用户文件已保存:
...
...
def info_message(self, fpath='', txt='', types="info"):
message_box = QtWidgets.QMessageBox(self)
message_box.setStyleSheet("color: #FFFFFF;")
message_box.setFont(QtGui.QFont("Verdana", 12, 77))
message_box.setWindowTitle("Save files")
if types == "info":
message_box.setIcon(
QtWidgets.QMessageBox.Information)
if types == "critical":
message_box.setIcon(
QtWidgets.QMessageBox.Critical)
message_box.addButton(QtWidgets.QMessageBox.Ok)
message_txt = "%s\n%s" %(txt, fpath)
message_box.setText(message_txt)
message_box.exec_()
...
此函数创建了一个消息框,当文件以路径保存时,将通知用户。保存文件的结果如下:

此消息框继承了应用程序的样式,并具有自定义的可能性。
QPrinter
许多应用程序允许用户打印创建的文档或内容。Qt 库提供了一个基本的对话框来打印创建的内容。QPrinter类也可用,它提供了与默认系统打印机设备的自定义和操作,以及其他功能,如打印机设置。要了解此类的功能,建议您查看官方 Qt 文档。在此,我们将描述和实现QPrintDialog和QPrintPreviewDialog类。这两个类都包含在QtPrintSupport模块中。要在应用程序中使用这些类,我们需要将以下内容添加到u_app.py文件中。
在PyQt5的u_app.py文件中添加此import语句:
...
from PyQt5 import QtPrintSupport
...
此外,将以下import语句添加到PySide2的u_app.py文件中:
...
from PySide2 import QtPrintSupport
...
QPrintDialog
此类提供了一个用于选择和配置选项以及打印内容的对话框。我们可以更改打印文档的设置,例如副本数量。此类在应用程序中的声明语法如下:
print_dialog = QtPrintSupport.QPrintDialog()
如下节所述,QPrintDialog类通过以下功能增强了功能。
set
这些函数设置打印对话框的参数和属性:
print_dialog.setOption(QtPrintSupport.QAbstractPrintDialog.PrintDialogOption, bool): 如果第二个参数为True,则使用此打印对话框启用(第一个参数指定的)选项。
print_dialog.setOptions(QtPrintSupport.QAbstractPrintDialog.PrintDialogOptions): 此函数设置参数中指定的选项,这些选项将与此打印对话框一起启用。
functional
这些函数返回打印对话框的当前值,通知您有关功能更改的信息,等等:
print_dialog.open(QtCore.QObject, str): 此函数将信号连接到槽,其中接收器(第一个参数)和成员(第二个参数)。
print_dialog.options(): 此函数返回用于此打印对话框的QtPrintSupport.QAbstractPrintDialog.PrintDialogOptions类型的选项。
print_dialog.testOption(QtPrintSupport.QAbstractPrintDialog.PrintDialogOption): 如果参数指定的选项为此打印对话框启用,则返回True;否则返回False。
signals
以下是与QPrintDialog类相关的信号:
print_dialog.accepted(QtPrintSupport.QPrinter): 当传入参数的打印机接受打印对话框中设置的值时,会发出此信号。
QPrintPreviewDialog
此类创建了一个用于在打印前预览内容的对话框。我们可以更改文档设置,例如副本数量。此类的声明语法如下:
print_preview = QtPrintSupport.QPrintPreviewDialog()
如下节所述,QPrintPreviewDialog类通过以下功能增强了功能。
functional
这些函数返回打印预览的当前值,通知您有关功能更改的信息,等等:
print_preview.open(QtCore.QObject, str): 这将一个信号连接到一个槽,其中接收器(第一个参数)和成员(第二个参数)。
print_preview.printer(): 这返回与打印预览对话框一起使用的当前 QtPrintSupport.QPrinter 类型的打印机。
信号
这个信号与 QPrintPreviewDialog 类一起可用:
print_preview.paintRequested(QtPrintSupport.QPrinter): 当预览对话框生成一组预览页面时,会发出此信号,打印机实例通过参数传入。
一个 QPrinter 示例
让我们在应用程序中实现打印机支持。首先,在应用程序顶部面板中添加选择选项,例如 打印 和 打印预览。为此,我们需要向 u_window.py 文件的 UWindow 类添加新选项:
- 将以下选项添加到顶部面板文件部分的菜单中:
...
class UWindow(UWin):
def __init__(self, parent=None):
...
self.mb1.addAction("Print")
self.mb1.addAction("Print Preview")
...
...
文件菜单部分的这些选项将打印文本或打开打印文档的预览。要使用这些打印机对话框,我们需要使用 QPrinter 类声明打印机。这将用于使用系统打印机打印文档,或者以另一种方式,例如打印到 PDF 文件。
- 我们需要向
u_app.py文件中添加以下行。
将 QPrinter 类添加到 UApp 类的 __init__ 函数底部:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.print_device = QtPrintSupport.QPrinter()
...
...
这在应用程序中创建了 QPrinter 类的实例。
- 现在将打印和打印预览对话框添加到
UApp类的files函数中:
...
...
def files(self, action):
...
if action.text() == "Save":
...
if action.text() == "Print":
print_dialog = QtPrintSupport.QPrintDialog(
self.print_device)
if print_dialog.exec_() == QtWidgets.QDialog.Accepted:
self.text_edit.print_(print_dialog.printer())
if action.text() == "Print Preview":
print_dialog = QtPrintSupport.QPrintPreviewDialog(
self.print_device)
print_dialog.setWindowTitle("Print Preview")
print_dialog.setWindowIcon(
QtGui.QIcon("Icons/python1.png"))
print_dialog.paintRequested.connect(
self.text_edit.print_)
print_dialog.exec_()
...
...
当选择文件部分选项时,triggered() 信号会调用带有 action 参数的 files() 函数,该参数将是所选选项的文本。我们可以运行 u_app.py 文件,并应该看到以下结果:

选择 打印预览 和 打印 选项将显示打印和预览要打印文本的对话框。
摘要
在本章中,我们探讨了在 GUI 应用程序中实现对话框的基本原则。这里并未涵盖 Qt 中所有的对话框。例如 QInputDialog、QProgressDialog(带有进度条的对话框)和 QWizard(在应用程序中创建向导框架的对话框),都可以使用。对于打印,有 QPageSetupDialog,用于配置与页面相关的选项。此外,可以通过不表示对话框窗口的类扩展打印功能,这些类非常有用,例如 QPrinterInfo 和 QPrintPreviewWidget。
在下一章中,我们将介绍布局,即安排应用程序中项目的方式。
第十三章:创建布局
本章将最终确定我们对于在应用程序中排列和定位项目相关概念的理解。如果元素具有固定的大小和位置,并且需要调整窗口大小,则这些元素不会相应地调整大小,并且会出现图形表示错误。此外,如果应用程序将用于具有不同分辨率(如现实生活中那样)的设备,则图形可视化的结果将会有所不同(并且这往往偏向于不良的一侧)。为项目构建布局是使应用程序独立于窗口大小和原生设备分辨率的基本工具之一。布局在具有 GUI 的应用程序中扮演着几何管理器的角色。
在先前的应用程序开发示例中,已经使用了布局,并且我们对这个机制有一些了解。本章将完成我们对以下主题的理解:
-
布局
-
Box 布局
-
网格布局
-
表格布局
-
堆叠布局
布局
正如我们在示例中所见,布局是排列应用程序中项目的一种方便方式,例如小部件的排列和根据设备分辨率、可用空间、大小等自动调整大小。在本节中,我们将介绍 Qt 库中布局的基本知识。
QLayout
这是一个用于实现 Qt 框架布局的抽象基类。本章中所有布局都继承了这个类的功能;QLayout 包含在 QtWidgets 模块中,并且可以在自定义类中重实现。重实现的语法如下:
...
class ULayout(QtWidgets.QLayout):
def __init__(self, parent=None):
super(ULayout, self).__init__(parent)
...
QLayout 类通过以下函数增强了功能。
添加
这些函数向布局中添加元素:
addChildLayout(QtWidgets.QLayout): 这将添加由参数指定的子布局作为此布局的子布局。
addChildWidget(QtWidgets.QWidget): 这将添加由参数指定的管理小部件到这个布局中。
addItem(QtWidgets.QLayoutItem): 这将添加由参数指定的一项到这个布局中。
addWidget(QtWidgets.QWidget): 这将添加由参数指定的小部件到这个布局中。
设置
这些函数设置布局的参数/属性:
setAlignment(QtWidgets.QWidget, QtCore.Qt.Alignment): 这将为小部件(第一个参数)设置对齐(第二个参数)。
setAlignment(QtWidgets.QLayout, QtCore.Qt.Alignment): 这将设置布局(第一个参数)的对齐(第二个参数)。
setContentsMargins(QtCore.QMargins): 这将设置由参数指定的边距,这些边距将用于围绕此布局。
setContentsMargins(int, int, int, int): 这将设置围绕此布局使用的左(第一个参数)、上(第二个参数)、右(第三个参数)和下(第四个参数)边的边距。
setEnabled(bool): 如果参数为 True,则启用此布局。
setMenuBar(QtWidgets.QWidget): 这将参数中指定的菜单栏控件设置在父控件的顶部。
setSizeConstraint(QtWidgets.QLayout.SizeConstraint): 这为此布局设置参数中指定的调整大小模式。可用的调整大小模式如下:
-
QtWidgets.QLayout.SetDefaultConstraint—0: 将控件的最低大小设置为minimumSize()。 -
QtWidgets.QLayout.SetNoConstraint—1: 控件不受约束。 -
QtWidgets.QLayout.SetMinimumSize—2: 将控件的最低大小设置为minimumSize()。 -
QtWidgets.QLayout.SetFixedSize—3: 将控件设置为sizeHint(),并且不能调整大小。 -
QtWidgets.QLayout.SetMaximumSize—4: 将控件的最大大小设置为maximumSize()。 -
QtWidgets.QLayout.SetMinAndMaxSize—5: 将控件的最大和最小大小设置为maximumSize()和minimumSize()。
setSpacing(int): 这设置此布局内控件之间的间距。
is
此函数返回一个与布局状态相关的布尔值(bool):
isEnabled(): 如果此布局启用,则返回True。否则,返回False。
functional
这些函数与布局的当前值、功能变化等相关:
activate(): 这将重新执行此布局的父控件的布局。
alignmentRect(QtCore.QRect): 这返回一个QtCore.QRect类型的矩形,当此布局的几何形状设置为参数中指定的矩形时,该矩形将被覆盖。
closestAcceptableSize(QtWidgets.QWidget, QtCore.QSize): 这返回一个大小,该大小满足对控件(第一个参数)的所有约束,并且接近指定的(第二个参数)大小。
contentsMargins(): 这返回围绕此布局的QtCore.QMargins类型的边距。
contentsRect(): 这返回布局几何形状的QtCore.QRect类型的矩形,带有内容边距。
count(): 这返回此布局中的项数。
getContentsMargins(): 这返回围绕布局的左、上、右和底部边距。
indexOf(QtWidgets.QWidget): 这返回在布局中找到的、由参数指定的控件的索引。
indexOf(QtWidgets.QLayoutItem): 这返回在布局中找到的、由参数指定的项的布局索引。
itemAt(int): 这返回在参数指定的索引处的QtWidgets.QLayoutItem类型的项。
menuBar(): 如果存在菜单栏,则返回此布局的QtWidgets.QWidget类型的菜单栏。
parentWidget(): 这返回此布局的QtWidgets.QWidget类型的父控件。如果是子布局,则返回父布局的父控件。
removeItem(QtWidgets.QLayoutItem): 这将从布局中删除由参数指定的布局项。
removeWidget(QtWidgets.QWidget): 这个函数从布局中移除指定的参数中的小部件。
replaceWidget(QtWidgets.QWidget, QtWidgets.QWidget, QtCore.Qt.FindChildOptions): 使用选项(第三个参数)替换一个小部件(第一个参数)为另一个小部件(第二个参数),并返回一个包含新小部件的QtWidgets.QLayoutItem类型项。
sizeConstraint(): 这个函数返回QtWidgets.QLayout.SizeConstraint类型的调整模式,用于此布局。
spacing(): 这个函数返回此布局内部小部件之间的间距。
takeAt(int): 这个函数返回参数中指定的索引处的QtWidgets.QLayoutItem类型项,并移除它。
update(): 这个函数更新此布局以适应父小部件。
events
这些是与事件相关的函数,例如事件处理程序:
childEvent(QtCore.QChildEvent): 这个事件处理程序接收布局的子事件,事件通过参数传入。
widgetEvent(QtCore.QEvent): 这个事件处理程序接收布局的父小部件调整大小事件,事件通过参数传入。
QLayoutItem
这个类使用 Qt 库创建了一个布局实现的抽象项。本章将描述的布局以及QLayout类可以使用此功能,并在自定义布局构造中操作这些项;QLayoutItem包含在QtWidgets模块中,可以在自定义类中重实现。重实现的语法如下:
...
class ULayoutItem(QtWidgets.QLayoutItem):
def __init__(self, parent=None):ss.
super(ULayoutItem, self).__init__(parent)
...
QLayoutItem类通过以下函数增强了功能。
set
这些函数设置布局项的参数/属性:
setAlignment(QtCore.Qt.Alignment): 这个函数为此布局项设置参数中指定的对齐方式。
setGeometry(QtCore.QRect): 这个函数为这个布局项设置参数中指定的几何形状。
has/is
这些函数返回与这个布局项的状态相关的布尔值bool:
hasHeightForWidth(): 如果这个布局项的首选高度依赖于其宽度,则此函数返回True。
isEmpty(): 如果这个布局项为空,则返回True;如果它包含任何小部件,则返回False。
functional
这些函数与布局项的当前值、功能变化等相关:
alignment(): 这个函数返回此布局项的QtCore.Qt.Alignment类型的对齐方式。
controlTypes(): 这个函数返回此布局项的QtWidgets.QSizePolicy.ControlTypes类型的控件类型。
expandingDirections(): 这个函数返回QtCore.Qt.Orientations类型的方向,以便这个布局项可以利用更多空间。
geometry(): 这个函数返回被此布局项覆盖的QtCore.QRect类型的矩形。
heightForWidth(int): 这个函数返回与参数中指定的宽度相关的布局项的首选高度。
invalidate(): 这个函数使这个布局项的缓存信息无效。
layout(): 如果此项具有相对布局,则返回QtWidgets.QLayout类型的布局。
maximumSize(): 这个函数返回此布局项的QtCore.QSize类型的最大尺寸。
minimumHeightForWidth(int): 这个函数返回相对于参数中指定的宽度的此小部件的最小高度。
minimumSize(): 这个函数返回此布局项的QtCore.QSize类型的最小尺寸。
sizeHint(): 这个函数返回此布局项的QtCore.QSize类型的首选尺寸。
spacerItem(): 如果此项是间隔项(空白空间),则返回一个QtWidgets.QSpacerItem类型的间隔项。
widget(): 如果此项管理小部件,则返回QtWidgets.QWidget类型的小部件。
QSizePolicy
这个类可以用来设置布局中小部件的缩放策略。小部件的尺寸策略描述了它将被如何缩放以及如何被布局引擎处理。通常,这个策略属性用于布局中的小部件。可以通过使用带有与尺寸策略相关的参数的setSizePolicy()函数来添加策略。这个类的声明语法如下:
size_policy = QtWidgets.QSizePolicy()
QSizePolicy类通过以下函数增强了功能。
set
这些函数设置尺寸策略的参数/属性:
size_policy.setControlType(QtWidgets.QSizePolicy.ControlType): 这个函数设置应用尺寸策略的相关小部件的控制类型。可用的控制类型如下:
-
QtWidgets.QSizePolicy.DefaultType: 默认类型;指定为None。 -
QtWidgets.QSizePolicy.ButtonBox: 这是一个QtWidgets.QDialogButtonBox实例。 -
QtWidgets.QSizePolicy.CheckBox: 这是一个QtWidgets.QCheckBox实例。 -
QtWidgets.QSizePolicy.ComboBox: 这是一个QtWidgets.QComboBox实例。 -
QtWidgets.QSizePolicy.Frame: 这是一个QtWidgets.QFrame实例。 -
QtWidgets.QSizePolicy.GroupBox: 这是一个QtWidgets.QGroupBox实例。 -
QtWidgets.QSizePolicy.Label: 这是一个QtWidgets.QLabel实例。 -
QtWidgets.QSizePolicy.Line: 这是一个QtWidgets.QFrame.HLine或QtWidgets.QFrame.VLine实例。 -
QtWidgets.QSizePolicy.LineEdit: 这是一个QtWidgets.QLineEdit实例。 -
QtWidgets.QSizePolicy.PushButton: 这是一个QtWidgets.QPushButton实例。 -
QtWidgets.QSizePolicy.RadioButton: 这是一个QtWidgets.QRadioButton实例。 -
QtWidgets.QSizePolicy.Slider: 这是一个QtWidgets.QAbstractSlider实例。 -
QtWidgets.QSizePolicy.SpinBox: 这是一个QtWidgets.QAbstractSpinBox实例。 -
QtWidgets.QSizePolicy.TabWidget: 这是一个QtWidgets.QTabWidget实例。 -
QtWidgets.QSizePolicy.ToolButton: 这是一个QtWidgets.QToolButton实例。
size_policy.setHeightForWidth(bool): 如果参数为True,则设置首选高度取决于小部件的宽度。
size_policy.setHorizontalPolicy(QtWidgets.QSizePolicy.Policy): 这将为这个大小策略设置参数中指定的水平策略。可用的策略如下:
-
QtWidgets.QSizePolicy.Fixed: 小部件有一个固定大小策略;它永远不会增长或缩小。 -
QtWidgets.QSizePolicy.Minimum: 小部件可以被扩展,但不能小于最小sizeHint()。 -
QtWidgets.QSizePolicy.Maximum: 小部件可以被缩小,但不能大于最大sizeHint()。 -
QtWidgets.QSizePolicy.Preferred: 小部件的sizeHint()是首选的。 -
QtWidgets.QSizePolicy.Expanding: 小部件的sizeHint()是一个合理的尺寸。小部件可以被扩展。 -
QtWidgets.QSizePolicy.MinimumExpanding: 小部件的sizeHint()是最小且足够的。 -
QtWidgets.QSizePolicy.Ignored: 忽略小部件的sizeHint()。
此外,以下标志可以一起使用,与 | 运算符结合:
-
QtWidgets.QSizePolicy.GrowFlag—1: 小部件可以比大小提示增长更多。 -
QtWidgets.QSizePolicy.ExpandFlag—2: 小部件可以占用尽可能多的空间。 -
QtWidgets.QSizePolicy.ShrinkFlag—4: 小部件可以比大小提示缩小更多。 -
QtWidgets.QSizePolicy.IgnoreFlag—8: 忽略大小提示。小部件将获得尽可能多的空间。
size_policy.setHorizontalStretch(int): 这将为这个大小策略设置参数中指定的水平拉伸因子。
size_policy.setRetainSizeWhenHidden(bool): 如果参数为 True,则确定此布局在隐藏时将保留小部件的大小。
size_policy.setVerticalPolicy(QtWidgets.QSizePolicy.Policy): 这将为这个大小策略设置参数中指定的垂直策略。可用的策略在前面的小点中描述。
size_policy.setVerticalStretch(int): 这将为这个大小策略设置参数中指定的垂直拉伸因子。
size_policy.setWidthForHeight(bool): 如果参数为 True,则设置首选宽度取决于此小部件的高度。
has
这些函数返回与这个大小策略状态相关的布尔值 (bool):
size_policy.hasHeightForWidth(): 如果小部件的首选高度取决于其宽度,则返回 True。
size_policy.hasWidthForHeight(): 如果小部件的首选宽度取决于其高度,则返回 True。
functional
这些函数与大小策略的当前值、功能变化等相关:
size_policy.controlType(): 返回与将要应用大小策略的小部件关联的 QtWidgets.QSizePolicy.ControlType 类型的控制类型。
size_policy.expandingDirections(): 这返回小部件可以比 sizeHint() 函数中指示的更多空间的方向,类型为 QtCore.Qt.Orientations。
size_policy.horizontalPolicy(): 这返回了此大小策略的 QtWidgets.QSizePolicy.Policy 类型的水平策略。
size_policy.horizontalStretch(): 这返回了在此大小策略中使用的水平拉伸因子。
size_policy.retainSizeWhenHidden(): 如果此布局在隐藏时保留小部件的大小,则返回 True。默认值为 False。
size_policy.transpose(): 这交换了水平/垂直策略/拉伸。
size_policy.transposed(): 这返回了QtWidgets.QSizePolicy类型的交换大小策略,带有水平/垂直策略/拉伸。
size_policy.verticalPolicy(): 这返回了此大小策略的 QtWidgets.QSizePolicy.Policy 类型的垂直策略。
size_policy.verticalStretch(): 这返回了此大小策略的垂直拉伸因子。
盒式布局
在应用程序的小部件中排列项的最简单方法是使用 box layout 构造。盒式布局按水平或垂直排列项。水平排列时,项将成行排列,垂直排列时,项将成列排列。提供基本功能的是 QBoxLayout 类。
QBoxLayout
这是盒式布局的基本类。它可以按行/列排列方式水平/垂直排列项。盒式布局的方向,如从左到右(行)或从上到下(列),需要在类的声明中通过相关参数定义。声明语法如下:
box_layout = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.LeftToRight)
QBoxLayout 继承了 QLayout 类,并通过以下函数增强了其功能:
add
这些函数将元素添加到布局中:
box_layout.addLayout(QtWidgets.QLayout, int): 这会将布局(第一个参数)添加到这个盒式布局中,使用拉伸因子(第二个参数)。
box_layout.addSpacerItem(QtWidgets.QSpacerItem): 这将指定的参数中的间隔项添加到盒式布局中。
box_layout.addSpacing(int): 这会在布局中添加一个不可拉伸的空间,大小由参数指定。
box_layout.addStretch(int): 这会在布局中添加一个可拉伸的空间,拉伸因子由参数指定。
box_layout.addStrut(int): 这为盒式布局的垂直维度添加了由参数指定的限制。
box_layout.addWidget(QtWidgets.QWidget, int, QtCore.Qt.Alignment): 这会将小部件(第一个参数)添加到这个盒式布局中,使用拉伸因子(第二个参数)和对齐(第三个参数)。
insert
这些函数将元素插入布局中:
box_layout.insertItem(int, QtWidgets.QLayoutItem): 这在索引(第一个参数)处将项(第二个参数)插入到此布局中。
box_layout.insertLayout(int, QtWidgets.QLayout, int): 这在索引(第一个参数)处将布局(第二个参数)插入到此布局中,并带有拉伸因子(第三个参数)。
box_layout.insertSpacerItem(int, QtWidgets.QSpacerItem): 这将在索引(第一个参数)处插入一个间隔项(第二个参数)到这个布局中。
box_layout.insertSpacing(int, int): 这将在索引(第一个参数)处插入一个具有特定大小(第二个参数)的非拉伸空间到这个布局中。
box_layout.insertStretch(int, int): 这将在索引(第一个参数)处插入一个具有特定大小(第二个参数)的可拉伸空间到这个布局中。
box_layout.insertWidget(int, QtWidgets.QWidget, int, QtCore.Qt.Alignment): 这将在索引(第一个参数)处插入一个小部件(第二个参数),并带有拉伸因子(第三个参数)和对齐方式(第四个参数)。
设置
这些函数设置布局的参数/属性:
box_layout.setDirection(QtWidgets.QBoxLayout.Direction): 这将为这个框布局设置参数中指定的方向。可用的方向如下:
-
QtWidgets.QBoxLayout.LeftToRight—0: 从左到右。 -
QtWidgets.QBoxLayout.RightToLeft—1: 从右到左。 -
QtWidgets.QBoxLayout.TopToBottom—2: 从上到下。 -
QtWidgets.QBoxLayout.BottomToTop—3: 从下到上。
box_layout.setSpacing(int): 这将为这个框布局内的小部件之间的间距设置。
box_layout.setStretch(int, int): 这将为这个布局在索引(第一个参数)处设置拉伸因子(第二个参数)。
box_layout.setStretchFactor(QtWidgets.QWidget, int): 这将为这个框布局中的小部件(第一个参数)设置拉伸因子(第二个参数)。
box_layout.setStretchFactor(QtWidgets.QLayout, int): 这将为这个框布局中的布局(第一个参数)设置拉伸因子(第二个参数)。
功能性
这些函数与布局的当前值、功能变化等相关:
box_layout.direction(): 这返回用于这个框布局的 QtWidgets.QBoxLayout.Direction 类型的方向。
box_layout.stretch(int): 这返回指定索引位置处的拉伸因子。
QHBoxLayout
这个类可以用来构建可以水平排列项的布局,将小部件放置在行内。它是实现框布局的附加类,可用于水平排列。当构建一个简单的应用程序窗口,其中一些元素将排列在顶部或底部,或者有额外的窗口/小部件,其元素将具有相似的方向时,非常有用。这个布局可用的方向是 RightToLeft 和 LeftToRight(默认)。这个类的声明语法如下:
hbox_layout = QtWidgets.QHBoxLayout()
QHBoxLayout 继承了 QBoxLayout,具有在水平布局中可用和可实现的特性和函数。
QVBoxLayout
这个类可以用来构建可以垂直排列项的布局,将小部件放置在列内。它是一个用于实现框布局的附加类,可用于垂直排列。当构建一个简单的应用程序窗口,其中包含将排列在左侧或右侧的元素,或者包含具有类似方向的额外窗口/小部件时,它非常有用。此布局的可用方向是 TopToBottom(默认)和 BottomToTop。此类的声明语法如下:
vbox_layout = QtWidgets.QVBoxLayout()
QVBoxLayout 继承了 QBoxLayout,具有在垂直布局中可用和可实现的特性和功能。
QGridLayout
这个类以网格形式排列项。网格意味着每个项都将相对于单元格定位在指定的行和列。这是一个非常有用且流行的布局,用于构建具有不同位置、方向和大小的元素的应用程序,这些元素相对于应用程序窗口。此类的声明语法如下:
grid_layout = QtWidgets.QGridLayout()
QGridLayout 函数
QGridLayout 继承了 QLayout 类,并通过以下函数增强了其功能。
add
这些函数向网格布局添加元素:
grid_layout.addItem(QtWidgets.QLayoutItem, int, int, int, int, QtCore.Qt.Alignment): 这会将布局项(第一个参数)添加到由行(第二个参数)和列(第三个参数)指定的位置。它将占用一定数量的行(第四个参数)和列(第五个参数),并且它还有一个对齐(第六个参数)。
grid_layout.addLayout(QtWidgets.QLayout, int, int, QtCore.Qt.Alignment): 这会将布局(第一个参数)添加到由行(第二个参数)和列(第三个参数)指定的位置,并使用对齐(第四个参数)。
grid_layout.addLayout(QtWidgets.QLayout, int, int, int, int, QtCore.Qt.Alignment): 这会将布局(第一个参数)添加到由行(第二个参数)和列(第三个参数)指定的位置。它将占用一定数量的行(第四个参数)和列(第五个参数),并使用对齐(第六个参数)。
grid_layout.addWidget(QtWidgets.QWidget, int, int, QtCore.Qt.Alignment): 这会将小部件(第一个参数)添加到由行(第二个参数)和列(第三个参数)指定的位置,并使用对齐(第四个参数)。
grid_layout.addWidget(QtWidgets.QWidget, int, int, int, int, QtCore.Qt.Alignment): 这会将小部件(第一个参数)添加到由行(第二个参数)和列(第三个参数)指定的位置。它将占用一定数量的行(第四个参数)和列(第五个参数),并使用对齐(第六个参数)。
set
这些函数设置网格布局的参数/属性:
grid_layout.setColumnMinimumWidth(int, int): 这为此网格布局中的列(第一个参数)设置像素(第二个参数)的最小宽度。
grid_layout.setColumnStretch(int, int): 这为此网格布局中的列(第一个参数)设置拉伸因子(第二个参数)。
grid_layout.setDefaultPositioning(int, QtCore.Qt.Orientation): 这设置布局定位模式,将此布局扩展到列/行数(第一个参数)。如果方向(第二个参数)是 QtCore.Qt.Horizontal,它将通过列扩展。如果方向是 QtCore.Qt.Vertical,它将通过行扩展。
grid_layout.setHorizontalSpacing(int): 这为此网格布局中的小部件设置指定参数的水平间距。
grid_layout.setOriginCorner(QtCore.Qt.Corner): 这为此网格布局设置指定参数的起始角落。
grid_layout.setRowMinimumHeight(int, int): 这为此网格布局中的行(第一个参数)设置像素(第二个参数)的最小高度。
grid_layout.setRowStretch(int, int): 这为此网格布局中的行(第一个参数)设置拉伸因子(第二个参数)。
grid_layout.setVerticalSpacing(int): 这为此网格布局中的小部件设置指定参数的垂直间距。
functional
这些函数与网格布局的当前值相关:
grid_layout.cellRect(int, int): 这返回单元格的几何形状,以 QtCore.QRect 类型表示,其中指定了行(第一个参数)和列(第二个参数)。
grid_layout.columnCount(): 这返回此网格布局中的列数。
grid_layout.columnMinimumWidth(int): 这返回指定参数的列的最小宽度,用于此网格布局。
grid_layout.columnStretch(int): 这返回指定参数的列的拉伸因子。
grid_layout.getItemPosition(int): 这返回在此网格布局中具有指定参数索引的项的位置。
grid_layout.horizontalSpacing(): 这返回水平排列的小部件之间的间距。
grid_layout.itemAtPosition(int, int): 这返回占据行(第一个参数)和列(第二个参数)的 QtWidgets.QLayoutItem 类型的项。
grid_layout.originCorner(): 这返回用于此网格布局原点的 QtCore.Qt.Corner 类型的角落。
grid_layout.rowCount(): 这返回此网格布局中的行数。
grid_layout.rowMinimumHeight(int): 这返回指定参数的最小高度,用于此网格布局的列。
grid_layout.rowStretch(int): 这返回指定参数的行的拉伸因子。
grid_layout.verticalSpacing():这返回垂直排列的小部件之间的间距。
QGridLayout 示例
在本书的前几章中,我们在主应用窗口中排列了元素,并使用QGridLayout类添加了额外的小部件。因此,没有必要提供这个类的示例,因为它们之前已经展示过了。
让我们添加一些属性到布局中,以展示所描述的功能,例如添加内容边距和修改布局周围的间距,使它们更具代表性:
- 在
u_app.py文件中的UApp类中,添加以下行:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.layfr1.setContentsMargins(0, 0, 0, 0)
...
self.layfr2_1.setSpacing(3)
...
self.layfr2.setSpacing(3)
self.layfr2.setContentsMargins(3, 3, 3, 3)
...
...
为每个边的内容边距将添加到布局中,并且布局的元素间距为3像素。这不会造成太大的变化,结果将看起来像这样:

这是一个可选的示例。您可以尝试一些其他功能。根据您的判断使用它们。
QFormLayout
这个类为各种带有项的表单提供布局构造。表单布局包括与这些输入相关联的输入小部件和标签。这个表单有两个列。第一列通常由标签组成,第二列是一个输入小部件。这些类似的表单布局为您提供了以简单表单表示排列项的可能性。 这个类的声明语法如下:
form_layout = QtWidgets.QFormLayout()
QFormLayout 函数
QFormLayout继承自QLayout类,并通过以下函数增强了其功能。
add
这些函数向表单布局添加元素:
form_layout.addRow(QtWidgets.QWidget):这将在表单布局中添加一个由参数指定的小部件的行。添加的小部件将占据该行的两列。
form_layout.addRow(QtWidgets.QLayout):这将在表单布局中添加一个由参数指定的布局的行。添加的布局将占据该行的两列。
form_layout.addRow(QtWidgets.QWidget, QtWidgets.QWidget):这将在表单布局中添加一行,包含两列。第一个小部件(第一个参数)将占据第一列,第二个小部件(第二个参数)将占据第二列。
form_layout.addRow(QtWidgets.QWidget, QtWidgets.QLayout):这将在表单布局中添加一行,包含两列。小部件(第一个参数)将占据第一列,布局(第二个参数)将占据第二列。
form_layout.addRow(str, QtWidgets.QWidget):这将在表单布局中添加一行,包含两列。一个带有文本的标签(第一个参数)将自动添加并占据第一列,而一个小部件(第二个参数)将占据第二列。
form_layout.addRow(str, QtWidgets.QLayout):这将在表单布局中添加一行,包含两列。一个带有文本的标签(第一个参数)将自动添加并占据第一列,一个布局(第二个参数)将占据第二列。
insert
这些函数将元素插入到表单布局中:
form_layout.insertRow(int, QtWidgets.QWidget): 这将在表单布局中插入一行,包含两列,在索引(第一个参数)处。添加的控件(第二个参数)将占据该行的两列。
form_layout.insertRow(int, QtWidgets.QLayout): 这将在表单布局中插入一行,包含两列,在索引(第一个参数)处。添加的布局(第二个参数)将占据该行的两列。
form_layout.insertRow(int, QtWidgets.QWidget, QtWidgets.QWidget): 这将在表单布局中插入一行,包含两列,在索引(第一个参数)处。第一个控件(第二个参数)将占据第一列,第二个控件(第三个参数)将占据第二列。
form_layout.insertRow(int, QtWidgets.QWidget, QtWidgets.QLayout): 这将在表单布局中插入一行,包含两列,在索引(第一个参数)处。控件(第二个参数)将占据第一列,布局(第三个参数)将占据第二列。
form_layout.insertRow(int, str, QtWidgets.QWidget): 这将在表单布局中插入一行,包含两列,在索引(第一个参数)处。将自动添加带有文本的标签(第二个参数),并占据第一列,控件(第三个参数)将占据第二列。
form_layout.insertRow(int, str, QtWidgets.QLayout): 这将在表单布局中插入一行,包含两列,在索引(第一个参数)处。将自动添加带有文本的标签(第二个参数),并占据第一列,布局(第三个参数)将占据第二列。
set
这些函数设置表单布局的参数/属性:
form_layout.setFieldGrowthPolicy(QtWidgets.QFormLayout.FieldGrowthPolicy): 这将设置表单布局中字段的增长策略。可用的策略如下:
-
QtWidgets.QFormLayout.FieldsStayAtSizeHint—0: 字段永远不会超过有效大小提示。 -
QtWidgets.QFormLayout.ExpandingFieldsGrow—1: 具有扩展或MinimumExpanding属性的字段将扩展以填充可用空间。否则,它们永远不会超过有效大小提示。 -
QtWidgets.QFormLayout.AllNonFixedFieldsGrow—2: 具有大小策略的字段将扩展以填充可用空间。
form_layout.setFormAlignment(QtCore.Qt.Alignment): 这将设置表单布局内容的对齐方式。
form_layout.setHorizontalSpacing(int): 这将设置表单布局中控件之间的水平间距,以参数指定的值为准。
form_layout.setItem(int, QtWidgets.QFormLayout.ItemRole, QtWidgets.QLayoutItem): 这将设置行(第一个参数)中的项目,其角色(第二个参数)为项目(第三个参数)。
form_layout.setLabelAlignment(QtCore.Qt.Alignment): 这将此表单布局中标签的水平对齐方式设置为参数中指定的对齐方式。
form_layout.setLayout(int, QtWidgets.QFormLayout.ItemRole, QtWidgets.QLayout): 这将为表单布局中的行(第一个参数)设置子布局(第三个参数),用于此表单布局的角色(第二个参数)。
form_layout.setRowWrapPolicy(QtWidgets.QFormLayout.RowWrapPolicy): 这将为此布局的表单设置行换行策略,策略由参数指定。可用的策略如下:
-
QtWidgets.QFormLayout.DontWrapRows—0: 行不换行。 -
QtWidgets.QFormLayout.WrapLongRows—1: 有足够的水平空间来容纳最宽的标签,其余空间用于字段。 -
QtWidgets.QFormLayout.WrapAllRows—2: 字段始终位于其标签下方。
form_layout.setVerticalSpacing(int): 这将为此表单布局中的小部件设置参数中指定的垂直间距。
form_layout.setWidget(int, QtWidgets.QFormLayout.ItemRole, QtWidgets.QWidget): 这将为行(第一个参数)设置小部件(第三个参数),用于角色(第二个参数)。可用的项目角色如下:
-
QtWidgets.QFormLayout.LabelRole—0: 标签小部件。 -
QtWidgets.QFormLayout.FieldRole—1: 字段小部件。 -
QtWidgets.QFormLayout.SpanningRole—2: 一个跨越标签和字段列的小部件。
functional
这些函数与表单布局的当前值、功能变化等相关:
form_layout.fieldGrowthPolicy(): 这返回 QtWidgets.QFormLayout.FieldGrowthPolicy 类型的增长策略。
form_layout.formAlignment(): 这返回用于此表单布局的 QtCore.Qt.Alignment 类型的对齐方式。
form_layout.getItemPosition(int): 这检索由参数中的索引指定的项目的行和角色。
form_layout.getLayoutPosition(QtWidgets.QLayout): 这检索参数中指定的子布局的行和角色。
form_layout.getWidgetPosition(QtWidgets.QWidget): 这检索参数中指定的小部件的行和角色。
form_layout.horizontalSpacing(): 这返回在此表单布局中水平排列的小部件之间的间距。
form_layout.itemAt(int, QtWidgets.QFormLayout.ItemRole): 这返回行(第一个参数)中具有项目角色的布局项(第二个参数)。
form_layout.labelAlignment(): 这返回此表单布局中标签的 QtCore.Qt.Alignment 类型的水平对齐方式。
form_layout.labelForField(QtWidgets.QWidget): 这返回与参数中指定的小部件关联的标签。
form_layout.labelForField(QtWidgets.QLayout): 这返回与参数中指定的布局关联的标签。
form_layout.removeRow(int): 这将从表单布局中删除参数中指定的行。
form_layout.removeRow(QtWidgets.QWidget): 这将从此表单布局中移除与指定小部件关联的行。
form_layout.removeRow(QtWidgets.QLayout): 这将从此表单布局中移除与指定布局关联的行。
form_layout.rowCount(): 这返回此表单布局中的行数。
form_layout.rowWrapPolicy(): 这返回此布局中 QtWidgets.QFormLayout.RowWrapPolicy 类型的行包装策略。
form_layout.takeRow(int): 这将从此表单布局中移除指定参数的行,但不删除它。
form_layout.takeRow(QtWidgets.QWidget): 这将从此表单布局中移除指定的小部件,但不删除它。
form_layout.takeRow(QtWidgets.QLayout): 这将从此表单布局中移除指定的布局,但不删除它。
form_layout.verticalSpacing(): 这返回垂直排列的小部件之间的间距。
QFormLayout 示例
让我们看看这个应用程序将使用的表单布局的示例。让我们在应用程序顶部面板的 Options 部分创建 Settings 选项:
- 要完成这个任务,请创建两个名为
u_settings.py的文件,一个位于App/App_PySide2/,另一个位于App/App_PyQt5/,并在其中添加以下代码:
- 将以下内容添加到
App_PySide2/u_settings.py文件中的import部分:
...
from PySide2 import QtWidgets, QtCore, QtGui
from u_style import ULineEd, UBut1
...
- 将以下内容添加到
App_PyQt5/u_settings.py文件中的import部分:
...
from PyQt5 import QtWidgets, QtCore, QtGui
from u_style import ULineEd, UBut1
...
- 将打开并读取
settings.txt文件的USets类添加到该文件中:
...
class USets(QtWidgets.QWidget):
def __init__(self, parent=None):
super(USets, self).__init__(parent)
self.setWindowTitle("U App settings")
win_icon = QtGui.QIcon("Icons/python1.png")
color_icon = QtGui.QIcon("Icons/colors.png")
self.setWindowIcon(win_icon)
rstop = open("settings.txt", "r")
rstyle = rstop.read().split(" ")
rstop.close()
...
...
...
这个类继承自 QWidget 类,它将在应用程序中作为独立窗口显示。
- 将用于应用程序第一种背景颜色的第一个行编辑字段以及打开颜色对话框的按钮添加到
USets类的__init__()函数中:
...
...
...
self.bgle1 = ULineEd(self, tmrgl=30, tmrgt=20,
tmrgr=0, tmrgb=20)
self.bgle1.setText(rstyle[0])
self.bgle1.setMinimumWidth(270)
self.bgb1 = UBut1(self.bgle1, pad=1)
self.bgb1.setIcon(color_icon)
...
...
...
我们已经创建了一个第一行编辑字段的实例,其中包含来自 settings.txt 文件的第一种颜色的文本,以及一个调用颜色对话框窗口的按钮。
- 将用于应用程序第二个背景颜色的第二个行编辑字段以及打开颜色对话框的按钮添加到
USets类的__init__()函数中:
...
...
...
self.bgle2 = ULineEd(self, tmrgl=30, tmrgt=20,
tmrgr=0, tmrgb=20)
self.bgle2.setText(rstyle[1])
self.bgb2 = UBut1(self.bgle2, pad=1)
self.bgb2.setIcon(color_icon)
...
...
...
我们已经创建了一个第二行编辑字段的实例,其中包含来自 settings.txt 文件的第二种颜色的文本,以及一个调用颜色对话框窗口的按钮。
- 将用于应用程序第一种附加颜色(用于文本和悬停效果)的第三个行编辑字段以及打开颜色对话框的按钮添加到
USets类的__init__()函数中:
...
...
...
self.colle1 = ULineEd(self, tmrgl=30, tmrgt=20,
tmrgr=0, tmrgb=20)
self.colle1.setText(rstyle[2])
self.colb1 = UBut1(self.colle1, pad=1)
self.colb1.setIcon(color_icon)
...
...
...
我们已经添加了一个第三行编辑字段的实例,其中包含来自 settings.txt 文件的第三种颜色的文本,以及一个调用颜色对话框窗口的按钮。
- 将用于应用程序第二种附加颜色(用于文本和悬停效果)的第四个行编辑字段以及打开颜色对话框的按钮添加到
USets类的__init__()函数中:
...
...
...
self.colle2 = ULineEd(self, tmrgl=30, tmrgt=20,
tmrgr=0, tmrgb=20)
self.colle2.setText(rstyle[3])
self.colb2 = UBut1(self.colle2, pad=1)
self.colb2.setIcon(color_icon)
...
...
...
我们添加了一个实例的第三个行编辑字段,其文本为settings.txt文件中的第三个颜色,并添加了一个按钮来调用颜色对话框窗口。
- 将
Reset和Save按钮添加到此小部件:
...
...
...
self.lbinfo = QtWidgets.QLabel(self)
self.lbinfo.setText("""These settings will be saved and\n
application will be restarted""")
self.breset = UBut1(self, fixw=95, fixh=59)
self.breset.setText("Reset")
self.bsave = UBut1(self, fixw=95, fixh=59)
self.bsave.setText("Save")
...
...
...
建议固定按钮的大小。为了最佳布局构造,这是必需的。
- 为标签和按钮添加水平框布局:
...
...
...
hlay = QtWidgets.QHBoxLayout()
hlay.addWidget(self.lbinfo)
hlay.addWidget(self.breset)
hlay.addWidget(self.bsave)
...
...
...
这将是主表单布局的一个补充。
- 添加带有文本标签(自动创建)和行编辑字段的表单布局:
...
...
...
form_layout = QtWidgets.QFormLayout()
form_layout.addRow("Background color 1", self.bgle1)
form_layout.addRow("Background color 2", self.bgle2)
form_layout.addRow("Color 1", self.colle1)
form_layout.addRow("Color 2", self.colle2)
...
...
...
这演示了应用程序中的表单布局构造。每一行都有一个标签和一个行编辑字段。
- 在将此布局添加到小部件时,为表单布局和水平布局添加垂直布局:
...
...
...
vlay = QtWidgets.QVBoxLayout()
vlay.addLayout(form_layout)
vlay.addLayout(hlay)
self.setLayout(vlay)
...
...
...
我们将两个布局合并为一个。这证明了我们可以创建任何嵌套布局构造。
- 在
__init__()函数的末尾,添加信号:
...
...
...
self.bgb1.clicked.connect(self.b1_fd)
self.bgb2.clicked.connect(self.b2_fd)
self.colb1.clicked.connect(self.b3_fd)
self.colb2.clicked.connect(self.b4_fd)
...
...
...
如果点击相应的按钮,这些信号将调用表单布局每一行的颜色对话框窗口。
- 现在添加将调用打开颜色对话框的功能,当按钮被点击时:
...
...
def b1_fd(self):
self.color_fd(le=self.bgle1)
def b2_fd(self):
self.color_fd(le=self.bgle2)
def b3_fd(self):
self.color_fd(le=self.colle1)
def b4_fd(self):
self.color_fd(le=self.colle2)
...
...
每个功能都会调用颜色对话框窗口,并可选择为应用程序窗口的背景和元素的文本颜色:
- 添加打开颜色对话框并将所选颜色设置为相关行编辑字段的文本的函数:
...
...
def color_fd(self, le=None):
fd = QtWidgets.QColorDialog()
fd.setWindowIcon(QtGui.QIcon("Icons/python1.png"))
if fd.exec_() == QtWidgets.QDialog.Accepted:
fc = fd.selectedColor()
color = "rgba(%s,%s,%s,%s)" % (fc.red(), fc.green(),
fc.blue(), fc.alpha())
le.setText(color)
...
此功能将显示颜色对话框窗口。如果选择了喜欢的颜色,并且通过点击 Ok、Accept 或其他类似按钮接受对话框,它将设置相应行编辑字段中的文本为 RGBA 颜色。
- 如果我们将此小部件作为窗口单独从应用程序中使用,我们可以添加文件的底部部分:
...o
if __name__ == "__main__":
import sys
sapp = QtWidgets.QApplication(sys.argv)
uset = USets()
uset.show()
sys.exit(sapp.exec_())
...
现在我们需要在u_app.py文件中添加行以从应用程序运行此设置小部件:
- 在
UApp类的__init__()函数底部,添加以下信号:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.mb3.triggered.connect(self.settings)
...
...
...
使用第三个菜单部分的triggered()信号,我们将调用settings()函数。
- 然后,添加顶部面板
Options部分的函数:
...
...
def options(self, action):
if action.text() == "Settings":
from u_settings import USets
self.sets = USets()
self.sets.show()
self.sets.bsave.clicked.connect(self.sets_but)
self.sets.breset.clicked.connect(self.to_default)
...
...
在options()函数中,我们为Settings选项创建了一个指令。我们导入了u_settings.py模块的USets类,然后创建了此类的实例并显示了此窗口。此外,我们还添加了Save和Reset按钮的两个clicked()信号。
- 添加点击
Save按钮的函数:
...
...
def sets_but(self):
colors = "%s %s %s %s" % (self.sets.bgle1.text(),
self.sets.bgle2.text(),
self.sets.colle1.text(),
self.sets.colle2.text())
save_open = open("settings.txt", "w")
save_open.write(colors)
save_open.close()
self.new_app()
...
...
此功能将使用 Python 标准库的open()函数将所选颜色的字符串写入settings.txt文件。
- 添加点击
Reset按钮的函数:
...
...
def to_default(self):
u_defaults.txt_file(state=True)
self.new_app()
...
...
此功能将恢复应用程序的默认颜色。
- 添加将运行新应用程序的功能:
...
...
def new_app(self):
self.sets.hide()
subprocess.Popen(["python", r"u_app.py"])
sys.exit(0)
...
...
此功能将以子进程的形式打开新的主应用程序窗口并退出前一个窗口。
现在将以下行添加到u_style.py文件:
- 我们需要将文件顶部的
color变量所在的行更改为以下内容:
...
setfile = open("settings.txt", "r")
colread = setfile.read().split(" ")
if len(colread) == 4:
color = colread
else:
color = ["", "", "", ""]
setfile.close()
...
- 现在,我们需要为应用程序添加默认颜色设置,这些设置将在应用程序启动时安装。为此,在
App/App_PySide2/和App/App_PyQt5/目录中创建u_defaults.py文件。
然后,我们可以将这些行添加到这些文件中:
...
import os
def txt_file(state=False):
colors = "rgba(0,41,59,140) rgba(0,41,59,255)
rgba(1,255,217,140) rgba(1,255,217,255)"
if os.path.exists("settings.txt") is state:
wstyle = open("settings.txt", "w")
wstyle.write(colors)
wstyle.close()
...
注意,colors变量必须包含一个由空格分隔的颜色值的字符串。
- 我们需要将这些行添加到
u_app.py文件中,以便应用程序能够正常运行。在u_app.py文件的顶部,在所有导入之前,我们需要添加以下行:
...
import u_defaults
u_defaults.txt_file(state=False)
...
如果这个应用程序是第一次启动,背景和文本将使用默认颜色。如果我们运行u_app.py文件,我们将看到一个简单的带有表单、垂直框和水平框布局的小部件:

因此,当我们选择颜色或在行编辑字段中输入 RGBA 值时,它们将被保存在简单的文本文件中。实际上,这不是保存和保留默认设置(不仅仅是设置)的可靠方式。这个应用程序的这部分只是允许我们玩颜色。此外,字体设置、元素大小等设置也可以以类似的方式添加。使用哪些设置由用户自行决定。
我们可以通过颜色选择来演示,应用程序将看起来像这样:

应用程序现在的颜色是白色。
QStackedLayout
此外,Qt 库提供了堆叠布局。此类创建一个将项目作为小部件堆栈排列的布局。默认情况下,一次只可见一个小部件;其他小部件被隐藏。与堆叠布局类似的是之前在应用程序中实现的标签小部件。QStackedWidget类也可用,可以用作堆叠布局的顶级类。此类的声明语法如下:
stacked_layout = QtWidgets.QStackedLayout()
QStackedLayout 函数
QStackedLayout继承自QLayout类,并通过以下功能增强了其功能。
set
这些功能设置堆叠布局的参数/属性:
stacked_layout.setCurrentIndex(int): 这将设置参数中指定的将在当前堆叠布局中可见和激活的小部件的索引。
stacked_layout.setCurrentWidget(QtWidgets.QWidget): 这将设置参数中指定的将在当前堆叠布局中可见和激活的小部件。
stacked_layout.setStackingMode(QtWidgets.QStackedLayout.StackingMode): 这将为此堆叠布局设置参数中指定的堆叠模式。可用的模式如下:
-
QtWidgets.QStackedLayout.StackOne—0: 只有一个小部件可见。 -
QtWidgets.QStackedLayout.StackAll—1: 所有小部件都可见,当前小部件被提升并激活。
功能性
这些函数与堆叠布局的当前值、功能变化等相关:
stacked_layout.currentIndex(): 这个函数返回当前在这个堆叠布局中可见的小部件的索引。
stacked_layout.currentWidget(): 这个函数返回当前在这个堆叠布局中可见的QtWidgets.QWidget类型的小部件。
stacked_layout.insertWidget(int, QtWidgets.QWidget): 这个函数将小部件(第二个参数)插入到这个堆叠布局的索引位置(第一个参数)。
stacked_layout.stackingMode(): 这个函数返回这个堆叠布局的QtWidgets.QStackedLayout.StackingMode类型的当前堆叠模式。
stacked_layout.widget(int): 这个函数返回参数指定的索引位置的小部件。
信号
这些信号对QStackedLayout类可用:
stacked_layout.currentChanged(int): 当堆叠布局中的当前小部件改变时,会发出这个信号,新的当前小部件索引通过参数传递。
stacked_layout.widgetRemoved(int): 当小部件从堆叠布局中移除时,会发出这个信号,小部件的索引通过参数传递。
摘要
本章完成了关于学习 Qt 框架中帮助我们构建具有 GUI 的基本应用程序的类和属性的书籍部分。在应用程序中,布局是一种非常重要的机制,用于以用户友好的方式排列项目。请注意,布局不是元素或项目,并且它们在 GUI 应用程序的窗口和控件的后台提供功能。当我们多次在布局之间进行嵌套时,我们需要记住这一点。此外,本章前面描述的抽象基类允许我们为应用程序构建各种特殊布局。
下一章将开始介绍关于应用程序功能特性的书籍章节。我们将探索一组非常小的相关工具,这些工具是从 Python 提供的巨大工具集中挑选出来的,可用于实现应用程序中的各种目的。我们将介绍数据库及其实现。
第十四章:数据库实现
所有应用程序都操作数据;这是技术世界中任何过程的本质。可重用数据存储为操作提供了巨大的机会,因为如果从应用程序先前操作中存储的数据未被使用,每次运行应用程序时,应用程序都将重新启动其进程。与我们在这本书中构建的 Qt 应用程序相关,在启动时,应用程序将是空的,不会显示任何以前的信息。从某种意义上说,它是一个纯实时应用程序,可以用于网络操作,如抓取,或用于简单的通信和监控。然而,总是需要保存一些东西以备以后使用。在第十三章中实现的示例,创建布局,非常原始,不能让我们以更方便的方式重用数据。因此,本章将介绍更方便的重用数据的方法。
在本章中,我们将探讨用于处理各种类型数据存储的各种工具,例如文件、SQL 和 NoSQL。这些工具将主要是第三方包,但尽可能提供基于 Qt 库的模块和类。本章不涵盖 SQL 语言,因为它是在应用程序中数据库的实现。
本章将涵盖以下主题:
-
文件存储
-
CSV
-
SQL
-
NoSQL
文件存储
在第十三章创建布局中,我们演示了如何将数据保存到文本文件,并在普通任务中(如保存应用程序的颜色设置)稍后重用它。Python 标准库有一些其他工具可以保存各种信息。保存文本文件和从这些文件中检索字符串是做这件事的一种简单但有限的方法。在某些情况下,保存对象并在特定任务中检索它们更可取。Python 标准库包括pickle和shelve等模块,可以帮助对象的序列化和反序列化,以及如何写入和读取它们。使用 Python 和 Qt 库的绑定,这些模块可以轻松地在我们应用程序中实现。我们将在下一节中讨论这个问题。
pickle 模块
Python 标准库中的pickle模块具有用于序列化和反序列化 Python 对象的二进制协议。这个工具可以将对象保存到文件中,以便在应用程序中执行各种任务时检索。可以保存的 Python 对象包括列表、元组、字典等。任何 Python 对象都可以保存到文件中,但保存字典等可以让我们使用具有键和值的数据结构。请注意,只有 dict、list、tuple 等可序列化对象的 pickleable 对象才能被 pickle。因此,让我们按照以下步骤将pickle模块功能添加到我们的应用程序中:
-
在
App/App_PySide2/和App/App_PyQt5/目录中创建一个data/文件夹。我们需要在u_tools.py文件中添加以下行,这些行将代表在应用程序中处理数据的各种方法。为了在我们的应用程序中使用pickle模块,我们需要添加一个带有导入语句的行。在
u_tools.py文件的import部分添加以下语句:
...
import pickle
...
此模块包括dump()和load()函数,用于序列化或反序列化 Python 对象。这些函数将对象写入文件对象,然后从文件中加载对象。
- 在
u_tools.py文件的UTools类中添加pickle_dump()函数,该函数用于序列化对象,代码如下:
...
class UTools(object):
def __init__(self):
...
def pickle_dump(self, obj=None, filename=None,
proto=1, fimps=None):
fobj = open(filename, 'wb')
if fimps is not None:
pickle.dump(obj, fobj, proto, fimps)
else:
pickle.dump(obj, fobj)
fobj.close()
...
此函数将以二进制模式打开文件进行写入并转储对象,并将与相关 Python 版本相关的参数包含在内。
- 现在我们需要添加
pickle_load()函数,该函数将反序列化对象,添加到UTools类中,如下所示:
...
...
def pickle_load(self, filename=None, fimps=None,
enc="ASCII", err="strict"):
fobj = open(filename, 'rb')
if fimps is not None:
pl = pickle.load(fobj, fimps, encoding=enc,
errors=err)
else:
pl = pickle.load(fobj)
fobj.close()
return pl
...
此函数将以二进制模式打开文件进行读取,并从文件中加载对象,参数与您使用的 Python 版本相关。我们现在需要在应用程序文件中进行一些更改,以便更容易地进行打开和数据保存操作。打开u_window.py文件并在顶部面板中添加一些行。
- 在顶部面板的数据部分添加以下新的选择选项:
...
class UWindow(UWin):
def __init__(self, parent=None):
...
self.mb3 = UMenu(self.menubar)
self.mb3.addAction("Pickle")
self.mb3.addAction("Shelve")
self.mb3.addAction("CSV")
self.mb3.addAction("Pandas")
self.mb3.addAction("SQLite")
self.mb3.addAction("PostgreSQL")
self.mb3.addAction("MySQL")
self.mb3.addAction("MongoDB")
self.mb3.addAction("CouchDB")
self.mb3.setTitle("&Data")
...
self.mb4.setTitle("&Options")
...
self.mb5.setTitle("&Help")
...
self.menubar.addMenu(self.mb5)
...
这些额外的选择选项将在本章的后续内容中使用。我们现在需要更改u_app.py文件中的UApp类,以便能够使用转储和加载操作。
- 现在,在
UApp类的__init__()函数中插入Save按钮,并将其连接到用于保存数据的槽,如下所示:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.push_but1 = UBut1(self.frame2)
self.push_but1.setText("Save")
self.push_but2 = UBut1(self.frame2)
self.push_but2.setText("Ok")
...
self.layfr2_1 = QtWidgets.QGridLayout()
self.layfr2_1.addWidget(self.push_but1, 0, 0, 1, 1)
self.layfr2_1.addWidget(self.push_but2, 0, 1, 1, 1)
...
self.mb1.triggered.connect(self.files)
self.mb3.triggered.connect(self.data)
self.mb4.triggered.connect(self.options)
self.push_but1.clicked.connect(self.save_data)
# self.push_but2.clicked.connect()
...
self.actx = ""
...
...
在__init__()函数的底部,我们添加了一个空字符串变量,如果工具之前未打开,将用于保存数据。
- 现在添加
data()函数,该函数将用于加载序列化的对象,添加到UApp类中,如下所示:
...
...
def data(self, action):
self.text_edit.clear()
self.actx = action.text()
if self.actx == "Pickle":
try:
txtdata = self.pickle_load(
filename=r"data/u_data.py")
self.text_edit.append(str(txtdata))
self.stat_bar.showMessage(self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
此函数的说明将使用该函数从文件加载数据,或者将错误设置到应用程序的状态栏中。加载数据将被附加到text edit字段。
- 现在添加以下
save_data()函数:
...
...
def save_data(self):
self.error = ''
uname = self.line_ed1.text()
umail = self.line_ed2.text()
upass = self.line_ed3.text()
udata = self.text_edit.toPlainText()
if (uname != '') and (umail != '') and (upass != ''):
if self.actx == "Pickle":
self.user_data1(uname, umail, upass, udata)
else:
self.user_data1(uname, umail, upass, udata)
if self.error != '':
self.stat_bar.showMessage(
self.actx + ' ' + str(self.error))
else:
self.stat_bar.showMessage(
self.actx + " saved")
...
...
此函数将为文件、数据库等提供保存操作。它还将检查所使用的行编辑字段是否为空,并调用user_data1()函数。
- 接下来,在
UApp类的末尾添加user_data1()函数,如下所示:
...
...
def user_data1(self, uname, umail, upass, udata):
try:
dictd = {"User Name": uname,
"User email": umail,
"User password": upass,
"User data": udata}
self.pickle_dump(obj=dictd,
filename=r"data/u_data.py")
except Exception as err:
self.error = err
...
此函数将使用 UTools 类的 pickle_dump() 函数将数据保存到文件。pickle 模块还提供 dumps() 和 loads() 函数,分别返回字节对象而不是写入文件,并分别读取对象。可以使用 pickle.Pickler() 和 pickle.Unpickler() 类来序列化和反序列化数据。Python 标准库的 pickletools 模块通过添加分析序列化数据的额外函数扩展了 pickle 模块的功能。pickle 模块对于数据持久化在机器学习模型中以及将这些模型实现为应用程序等任务非常有用。
shelve 模块
shelve 模块使用 pickle 和 dbm 模块创建类似字典的对象,这些对象可以保存到文件中并相应地打开。因此,让我们将 shelve_open() 函数添加到 u_tools.py 文件中的 UTools 类:
- 首先,将以下模块添加到
u_tools.py文件的导入部分:
...
import shelve
...
- 将
shelve_open()函数添加到u_tools.py文件中的UTools类,如下所示:
...
class UTools(object):
def __init__(self):
...
def shelve_open(self, filename=None, flag='c',
proto=None, writeback=False):
return shelve.open(filename, flag, proto, writeback)
...
此函数将数据写入和从数据库中读取。可以通过在应用程序中使用此函数来指定参数。现在,在 u_app.py 文件中的 UApp 类中,我们需要添加 shelve 工具以打开和保存文件。
- 将
shelve模块功能添加到UApp类的data()函数中,如下所示:
...
...
def data(self, action):
...
if self.actx == "Pickle":
...
if self.actx == "Shelve":
try:
db = self.shelve_open(filename="data/u_data")
self.text_edit.append("%s\n%s\n%s\n%s" % (
db.get("User Name"),
db.get("User email"),
db.get("User password"),
db.get("User data")))
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
UTools 类的 shelve_open() 函数将用于连接数据库。get() 方法将从数据库的指定字段获取数据。
- 接下来,将以下选项添加到
save_data()函数中:
...
...
def save_data(self):
...
if self.actx == "Pickle":
...
elif self.actx == "Shelve":
self.user_data2(uname, umail, upass, udata)
...
...
...
...
此指令将使用其参数中指定的数据调用 user_data2() 函数。
- 现在将
user_data2()函数添加到UApp类的末尾,如下所示:
...
...
def user_data2(self, uname, umail, upass, udata):
try:
db = self.shelve_open(filename="data/u_data")
db["User Name"] = uname
db["User email"] = umail
db["User password"] = upass
db["User data"] = udata
db.close()
except Exception as err:
self.error = err
...
此函数将数据写入数据库。
shelve_open() 函数的对象提供类似于以下字典方法的方法:
-
db.keys():此操作返回对象的所有键。 -
db.values():此操作返回对象的所有值。 -
db.items():此操作返回包含键/值对的元组的可迭代对象。 -
db.get(key):此操作返回与参数中的键相关联的值。 -
db.update({key: value}):此操作向数据库对象添加元素。
以下标志也可用:
-
r:只读。 -
w:读写。 -
c:读写;如果文件不存在,则创建(这是默认标志)。 -
n:读写;如果文件不存在,则创建;如果文件存在,则重写。
如您所见,pickle和shelve模块提供了一些组织数据的方法。它们在处理机器学习算法的应用程序中也很有用。然而,实际上可能存在需要更广泛方法并使用常用工具和数据库的任务。在接下来的章节中,我们将尝试描述这些常用工具。
CSV
逗号分隔值(CSV)文件是一种使用逗号分隔值并以纯文本文件形式存储数据的文本文件。这是一种非常流行的文件类型,通常用作机器学习和数据科学中数据源。CSV 文件允许我们创建和操作大型数据集,这些数据集通常包含数十亿个值。与 Microsoft Excel 和 LibreOffice Calc 等流行办公应用程序一起使用的数据表以类似的电子表格形式出现,这些应用程序可以打开 CSV 文件,但 Python 标准库有一个用于创建和操作 CSV 文件的模块。我们还将探讨一些特殊工具,例如 pandas。
csv 模块
Python 标准库包括用于操作 CSV 文件的csv模块。为了向您展示如何有效地使用此模块,我们将提供一个写入和读取 CSV 文件的示例:
- 首先,将以下行添加到
u_tools.py文件的import部分:
...
import csv
import os
...
- 在
import部分之后,将以下路径添加到该文件中:
...
pathf = os.path.dirname(os.path.abspath(__file__))
...
这一行可以将应用程序文件所在的目录路径获取到我们应用程序的工作目录中。
- 在
u_tools.py文件中的UTools类中添加以下函数,这些函数将写入和读取 CSV 文件:
...
class UTools(object):
...
def csv_write(self, csvfile=None, fieldnames=None, mode='a',
newline='', rowdata=None, dialect=csv.excel,
delimiter=' ', quotechar='|', lineterminator='\r\n'):
csvpath = os.path.exists(r"%s/%s" % (pathf, csvfile))
csvf = open(csvfile, mode)
csvw = csv.DictWriter(csvf, fieldnames=fieldnames,
dialect=dialect,delimiter=delimiter,
lineterminator=lineterminator)
if csvpath is False:
csvw.writeheader()
csvdict = {k: v for (k, v) in zip(fieldnames, rowdata)}
csvw.writerow(csvdict)
...
前面的函数将数据写入 CSV 文件。如果指定的文件不存在,将添加标题到数据中。
- 现在,添加以下函数以读取 CSV 文件:
...
...
def csv_read(self, csvfile=None, mode='r',
dialect=csv.excel):
csvf = open(csvfile, mode)
csvr = csv.DictReader(csvf, dialect=dialect,
delimiter=' ')
return csvr
...
此函数将使用 Python 标准库的csv模块读取 CSV 文件,并将包含数据的DictReader对象返回。
在u_app.py文件中的UApp类中,我们现在需要添加打开和保存 CSV 文件的工具:
- 首先,将
csv模块功能添加到UApp类的data()函数中,如下所示:
...
...
def data(self, action):
...
if self.actx == "Shelve":
...
if self.actx == "CSV":
try:
for row in self.csv_read(
csvfile="data/tests.csv"):
self.text_edit.append("%s %s %s %s" % (
row["User_Name"],
row["User_email"],
row["User_password"],
row["User_data"]))
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
此函数将读取当调用UTools类的csv_read()函数时返回的DataReader对象的行。
- 接下来,将以下指令添加到
save_data()函数中:
...
...
def save_data(self):
...
...
elif self.actx == "Shelve":
...
elif self.actx == "CSV":
self.user_data3(uname, umail, upass, udata)
...
...
...
...
此函数将使用其参数指定的数据调用user_data3()函数。
- 现在将
user_data3()函数添加到UApp类的末尾,如下所示:
...
...
def user_data3(self, uname, umail, upass, udata):
fnames = ["User_Name", "User_email",
"User_password", "User_data"]
rdata = [uname, umail, upass, udata[:140]]
try:
for row in self.csv_read(
csvfile="data/tests.csv"):
if (row["User_Name"] == rdata[0]) and (
row["User_password"] == rdata[2]):
rdata = None
except Exception:
pass
if rdata is not None:
try:
self.csv_write(csvfile="data/tests.csv",
fieldnames=fnames,
rowdata=rdata, delimiter=' ',
lineterminator='\n')
except Exception as err:
self.error = err
...
函数将尝试将数据写入 CSV 文件。如果指定的数据已存在于文件中,则不会写入此数据。前面的示例展示了使用 Python 的csv模块进行读取和写入 CSV 文件所能实现的功能,尽管其中一些行是可选的,可以重写。
然而,有一些行我们需要注意。包含传递异常语句的行是不推荐的,因为当出现错误时,它们不会给我们提供任何关于错误的信息,也不会告诉我们发生了什么。这可以通过更改与 Python 2.x/3.x 相关的这些行来解决。(如前所述,PyQt5 使用 Python 3.x,而 PySide2 使用 Python 2.x。)
我们可以添加以下几行用于 PyQt5 异常处理:
except Exception as err:
print(err)
以下几行是用于 PySide2 异常处理的:
except Exception as err:
print err
注意,可以使用更具体的异常,例如FileNotFoundError或PermissionError(3.x)。Python 官方文档中提供了内置异常的完整列表,并且每个 Python 版本都有所不同。
pandas
在专业处理 CSV 文件时,你应该使用最流行的数据处理工具集:pandas。这个工具集允许我们处理大型数据集,操作数据,并在数据科学的几乎所有领域分析和表示数据。此包与 SciPy、NumPy 和 Matplotlib 一起构成了科学 Python 的基础。如其在官方源中所述,pandas 是一个为 Python 编程语言提供高性能、易于使用的数据结构和数据分析工具的库。有关 pandas 库的广泛功能信息,请访问pandas.pydata.org/。
我们现在将通过使用 CSV 文件来查看这个强大工具的实际应用。pandas 可以通过以下方式安装:
with pip
> pip install pandas
or with conda
> conda install pandas
注意,Anaconda 的最新版本将 pandas 作为默认安装的包,以及 NumPy、SciPy、Matplotlib、scikit-learn 和其他许多包。
在本节中,我们将通过一个简短的示例来介绍如何使用 pandas 编写和读取文件:
- 安装完成后,你需要导入 pandas 库。为此,将以下
import语句添加到u_tools.py文件中:
...
import pandas
...
- 接下来,将
pandas_write()函数添加到u_tools.py文件中的UTools类中,如下所示:
...
class UTools(object):
...
def pandas_write(self, filename=None, writer="csv",
data=None, columns=None, index=None, dtype=object):
df = pandas.DataFrame(data, columns=columns,
index=index, dtype=dtype)
df.index.name = "rows\columns"
if writer == "csv":
df.to_csv(filename)
if writer == "excel":
df.to_excel(filename)
if writer == "html":
df.to_html(filename)
if writer == "json":
df.to_json(filename)
return (df, writer)
...
前面的函数可以根据指定的文件名和扩展名(类型)以及writer参数中指定的类型,将数据写入各种文件,例如 CSV、Excel、HTML 和 JSON。
- 现在添加以下
pandas_read()函数,该函数将根据指定的参数读取文件:
...
...
def pandas_read(self, filename=None, reader="csv", sep=',',
delimiter=None, engine='python', maxrows=999):
if reader == "csv":
df = pandas.read_csv(filename, engine=engine)
if reader == "excel":
df = pandas.read_excel(filename)
if reader == "html":
df = pandas.read_html(filename)
if reader == "json":
df = pandas.read_json(filename)
pandas.options.display.max_rows = maxrows
return (df, reader)
...
此函数可以根据指定的文件名和扩展名(类型)以及reader参数中指定的类型,从各种文件中读取数据,例如 CSV、Excel、HTML 和 JSON。
- 在
u_app.py文件中的UApp类中,添加用于打开和保存文件的 pandas 工具。将 pandas 功能添加到UApp类的data()函数中,如下所示:
...
...
def data(self, action):
...
if self.actx == "CSV":
...
if self.actx == "Pandas":
try:
pread = self.pandas_read(
filename="data/ptests.csv",
reader="csv", sep=',')
self.text_edit.append(str(pread[0]))
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
此指令将调用使用 pandas 读取 CSV 文件的函数。它将要么将读取的数据追加到文本字段中,要么在应用程序的状态栏中显示错误消息。
- 接下来,将以下指令添加到
save_data()函数中:
...
...
def save_data(self):
...
...
elif self.actx == "CSV":
...
elif self.actx == "Pandas":
self.user_data4(uname, umail, upass, udata)
...
...
...
...
此指令将使用参数中指定的数据调用user_data4()函数。
- 将
user_data4()函数添加到UApp类的末尾,如下所示:
...
...
def user_data4(self, uname, umail, upass, udata):
try:
ucolumns = ["User_Name", "User_email",
"User_password", "User_data"]
uindex = [i for i in range(1000)]
udata = {"User_Name": range(0, 1000),
"User_email": range(0, 1000),
"User_password": range(0, 1000),
"User_data": range(0, 1000)}
self.pandas_write(filename="data/ptests.csv",
writer="csv", data=udata,
columns=ucolumns, index=uindex)
except Exception as err:
self.error = err
...
此功能不使用在参数中检索到的数据;相反,它使用由range()函数生成的数据,该函数用于表中的每一列。我们现在可以运行u_app.py文件并查看结果。当点击保存按钮时,将创建一个包含数据的文件。如果您愿意,可以将文件名扩展名更改为data/tests.xlsx并将写入器更改为 Excel 进行实验。如您所见,与我们的 CSV 示例相比,这段少量代码提供了很多功能。请注意,其他函数,如to_html(),是可选的,仅用于展示 pandas 库的功能。
Pandas 是应用程序中数据操作的首选工具,因为它拥有最广泛的工具集。另一方面,应用程序可能会变得很慢,这是意料之中的。导入 pandas 并写入值的总数会消耗内存资源;在第十六章,线程和进程中,我们将尝试解决这个问题。
SQL
在本节中,我们将探讨基于结构化查询语言(SQL)的数据库。SQL 是一种特定领域的语言,用于通过管理关系数据库管理系统(RDBMS)中的数据和处理关系 数据流管理系统(RDSMS)中的流式处理来操纵数据库。我们不会深入探讨 SQL 理论,因为您可以通过阅读相关文档来了解更多。在本节中,我们将仅涵盖 GUI 应用程序中最有价值的内容。
数据库,无论是基于 SQL 还是 NoSQL,都提供了比之前讨论的存储数据的其他方法。在早期的例子中,我们已经将数据保存到文件中,并通过创建数据结构来检索它。然而,以这种方式使用 CSV 文件并不总是最有效的方法。在某些应用程序中,我们可能需要一个既方便又提供管理功能的数据库。换句话说,我们需要创建一个 SQL(或 NoSQL)数据库来存储和管理数据。
为了充分利用这本书,读者必须对 SQL 及其主要语句(如CREATE、INSERT、SELECT、UPDATE和DELETE)有一些基本了解。在下一节中,我们将首先查看主要的第三方 SQL 数据库,然后再探讨 Qt 库能做什么。
SQLite
SQLite 是一个使用 C 语言实现的 SQL 数据库库,它实现了一个小型且快速的 SQL 数据库引擎。它是一个易于使用的数据库;其优势在于其简单性和可移植性。这个数据库可以轻松地与几乎任何设备的应用程序实现,并且是世界上使用最广泛的数据库。重要的是,这个数据库也包含在 Python 标准库模块中,因此可以使用 PyQt 和 PySide 绑定。
我们不需要下载它、安装它或通过复杂的过程来开始使用这个数据库;我们只需要在文件中导入它,无论何时需要,按照以下步骤:
- 首先,在
u_defaults.py文件的import部分中添加以下行:
...
import sqlite3
...
- 打开
u_defaults.py文件,并在import部分之后添加以下路径以创建数据库:
...
pathf = os.path.dirname(os.path.abspath(__file__))
...
- 然后,在写入文件颜色的函数之后,添加以下行:
...
dbcon = sqlite3.connect("%s/data/u_db.sqlite" % dbpath)
dbcursor = dbcon.cursor()
sql_query = """CREATE TABLE IF NOT EXISTS u_dbtable (
info_date DEFAULT CURRENT_TIMESTAMP,
user_name TEXT UNIQUE,
user_email TEXT UNIQUE,
user_passw TEXT,
user_data TEXT UNIQUE);"""
dbcursor.execute(sql_query)
dbcursor.close()
dbcon.close()
...
建立数据库及其游标的连接,编写并执行 SQL 查询,然后关闭游标与数据库的连接是使用 SQL 数据库的标准工作方式。
现在,如果我们运行 u_app.py 文件,应该存在一个带有表的 SQLite 数据库,并准备好使用。请注意,数据库文件将创建在应用程序目录的 data/ 文件夹中。
我们现在想为这个数据库提供一些操作,例如插入或选择值。
- 因此,在
u_tools.py文件的import部分中添加以下行:
...
import sqlite3
...
- 将以下将值插入数据库的函数添加到
u_tools.py文件的UTools类中:
...
class UTools(object):
...
def sqlite_insert(self, username=None, email=None,
passw=None, data=None):
dbcon = sqlite3.connect("%s/data/u_db.sqlite" % pathf)
dbcursor = dbcon.cursor()
sql_query = """INSERT INTO u_dbtable (user_name, user_email,
user_passw, user_data) VALUES (?, ?, ?, ?);"""
udata = (str(username), str(email), str(passw), str(data))
dbcursor.execute(sql_query, udata)
dbcon.commit()
dbcursor.close()
dbcon.close()
...
上述函数实现了向 SQLite 数据库插入指定值的连接。
- 接下来,添加以下函数以选择数据库的值:
...
...
def sqlite_select(self):
dbcon = sqlite3.connect("%s/data/u_db.sqlite" % pathf)
dbcursor = dbcon.cursor()
sql_query = """SELECT info_date, user_name,
user_email, user_passw,
user_data FROM u_dbtable;"""
dbcursor.execute(sql_query)
dbdata = dbcursor.fetchall()
dbcursor.close()
dbcon.close()
return dbdata
...
上述函数将根据特定的 SQL 查询从数据库中选择值。
- 在
u_app.py文件中的UApp类中,将插入或选择数据库值的 SQLite 功能添加到UApp类的data()函数中,如下所示:
...
...
def data(self, action):
...
if self.actx == "Pandas":
...
if self.actx == "SQLite":
try:
dbdata = self.sqlite_select()
for dtx in dbdata:
self.text_edit.append(
"%s\n%s\n%s\n%s\n%s" % (
dtx[0], dtx[1],dtx[2],
dtx[3], dtx[4]))
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
上述函数将使用 UTools 类的 sqlite_select() 函数从数据库中选择值。
- 接下来,将以下代码添加到
save_data()函数中:
...
...
def save_data(self):
...
...
elif self.actx == "Pandas":
...
elif self.actx == "SQLite":
self.user_data5(uname, umail, upass, udata)
...
...
...
...
上述指令将使用指定参数的数据调用 user_data5() 函数。
- 现在,将
user_data5()函数添加到UApp类的末尾,如下所示:
...
...
def user_data5(self, uname, umail, upass, udata):
try:
self.sqlite_insert(username=uname, email=umail,
passw=upass, data=udata)
except Exception as err:
self.error = err
...
上述函数将指定的数据写入 SQLite 数据库。
我们现在知道如何通过插入和选择值在我们的应用程序中使用 SQLite3 数据库。请注意,一些用户可能认为 SQLite 比其他数据库不太安全,但它也有许多优点。SQLite 的灵活性、简单性和可靠性等优势意味着它仍然推荐用于应用程序。
PostgreSQL
PostgreSQL 是一个高级管理的关联数据库系统,可以定义为对象-关系数据库管理系统(ORDBMS)。目前,它是大数据和工业任务相关案例中最常用的数据库。作为一个数据库,PostgreSQL 提供了广泛的功能。为了将此数据库应用于我们的应用程序,我们首先需要将其下载并安装到我们的远程或本地设备上。PostgreSQL 可以从官方源www.postgresql.org轻松下载,适用于任何平台。
要安装此数据库,我们需要遵循安装说明,并在连接之前提供密码。下载和安装完成后,我们可以在使用它之前配置 PostgreSQL。以下步骤演示了如何进行此操作:
- 首先,初始化数据库集群。为此,打开命令行或终端,并将当前目录更改为应用程序目录的
data/文件夹,如下所示:
> cd Path/to/the/App/App_Pyside2/data
or
> cd Path/to/the/App/App_PyQt5/data
- 接下来,初始化数据库集群,如下所示:
> Path/to/the/installed/PostgreSQL/bin/initdb postgresdb
数据库集群将被初始化为一个名为postgresdb的文件夹,或者是一个位置(磁盘上的存储区域),其中将创建数据库。初始化完成后,以下消息应出现在命令行或终端窗口中:
...Success. You can now start the database server using:
...Path/to/the/installed/PostgreSQL/bin/pg_ctl -D postgresdb -l logfile start
- 现在,使用命令行或终端中的上一行副本启动服务器:
> Path/to/the/installed/PostgreSQL/bin/pg_ctl -D postgresdb -l logfile start
结果应该如下所示:
...waiting for server to start.... done
...server started
我们现在已经在所需目录中启动了服务器和数据库集群。请注意,每次我们想要使用数据库时都必须启动服务器。在重新启动或重新安装操作系统后,此服务器可以停止,因此我们需要在环境启动时自动启动服务器。您可以通过阅读官方文档或适用于您操作系统的其他第三方资源来了解如何做到这一点。
- 现在用以下命令创建 PostgreSQL 数据库:
> Path/to/the/installed/PostgreSQL/bin/createdb psqldb
- 在数据库中创建一个表。为此,在命令行或终端中打开以下
psql外壳:
> Path/to/the/installed/PostgreSQL/bin/psql psqldb
- 输入以下 SQL 查询以创建表:
psqldb=# CREATE TABLE u_dbtable (
psqldb(# info_date TIMESTAMP DEFAULT NOW(),
psqldb(# user_name TEXT UNIQUE,
psqldb(# user_email TEXT UNIQUE,
psqldb(# user_passw TEXT,
psqldb(# user_data TEXT UNIQUE);
结果应该是这样的:
psqldb(# ...;
CREATE TABLE
因此,我们现在已经创建了一个用于我们应用程序的 PostgreSQL 数据库和表。PostgreSQL 具有各种功能,使用户能够配置和管理数据库,例如dropdb、dropuser和psql(命令行界面)。这些都可以在 PostgreSQL 安装的bin/文件夹中找到。
下一步是将此数据库用于我们的应用程序。Python 标准库不包括 PostgreSQL,因此需要通过第三方包适配器下载和安装,例如psycopg。为此,请使用以下命令:
> pip install psycopg2
我们现在可以使用 PostgreSQL 与任何基于 Python 的应用程序。要实现此功能,请将以下行添加到u_tools.py文件中:
- 在
u_tools.py文件中,将以下导入语句添加到import部分:
...
import psycopg2
...
- 然后,在
u_tools.py文件的UTools类中添加一个函数,将值插入到 PostgreSQL 数据库中,如下所示:
...
class UTools(object):
...
def psql_insert(self, username=None, email=None,
passw=None, data=None):
dbcon = psycopg2.connect(dbname="psqldb")
dbcursor = dbcon.cursor()
sql_query = """INSERT INTO u_dbtable (user_name,
user_email, user_passw,
user_data) VALUES (%s, %s, %s, %s);"""
udata = (str(username), str(email),
str(passw), str(data))
dbcursor.execute(sql_query, udata)
dbcon.commit()
dbcursor.close()
dbcon.close()
...
如前例所示,SQL 数据库非常相似,该功能很快就能在应用中识别出正在使用 PostgreSQL 数据库。此功能将值插入到数据库中。
- 添加以下函数,该函数从 PostgreSQL 数据库中选择值:
...
...
def psql_select(self):
dbcon = psycopg2.connect(dbname="psqldb")
dbcursor = dbcon.cursor()
sql_query = """SELECT info_date, user_name, user_email,
user_passw, user_data FROM u_dbtable;"""
dbcursor.execute(sql_query)
dbdata = dbcursor.fetchall()
dbcursor.close()
dbcon.close()
return dbdata
...
前述函数将根据指定的 SQL 查询从 PostgreSQL 数据库中选择值。
- 在
u_app.py文件的UApp类中,添加用于插入和选择数据库值的 PostgreSQL 工具。将 PostgreSQL 功能添加到UApp类的data()函数中,如下所示:
...
...
def data(self, action):
...
if self.actx == "SQLite":
...
if self.actx == "PostgreSQL":
try:
dbdata = self.psql_select()
for dtx in dbdata:
self.text_edit.append(
"%s\n%s\n%s\n%s\n%s" % (
dtx[0], dtx[1], dtx[2],
dtx[3], dtx[4]))
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
前述指令使用UTools类的psql_select()函数从数据库中选择数据并将其附加到文本编辑字段。
- 现在,将
user_data6()函数添加到save_data()函数中,如下所示:
...
...
def save_data(self):
...
...
elif self.actx == "SQLite":
...
elif self.actx == "PostgreSQL":
self.user_data6(uname, umail, upass, udata)
...
...
...
...
前述指令将调用带有指定参数的user_data6()函数。
- 接下来,将
user_data6()函数添加到UApp类的末尾,如下所示:
...
...
def user_data6(self, uname, umail, upass, udata):
try:
self.psql_insert(username=uname, email=umail,
passw=upass, data=udata)
except Exception as err:
self.error = err
...
前述指令调用psql_insert()函数将用户数据插入到数据库中。现在 PostgreSQL 数据库已集成并准备好使用!
MySQL
MySQL 数据库需要特别注意。MySQL 是一个开源的关系型数据库管理系统(RDBMS),它结合了 SQLite 的简单性和可靠性,但功能略低于 PostgreSQL。此外,MySQL 是Linux-Apache-MySQL-Python|PHP|Perl (LAMP)网络应用程序软件堆栈的组成部分,这对于开发非常重要。
在我们的应用程序中集成此数据库非常简单。我们可以下载并安装 MySQL 的二进制包或压缩存档。使用二进制包,我们可以通过遵循图形安装程序提供的说明轻松安装数据库。使用压缩存档,我们需要使用在www.mysql.com上可用的文档并初始化非安装的 MySQL 包。
一切下载并安装完成后,我们可以按照以下步骤创建一个包含表的数据库:
- 首先,打开一个客户端控制台,输入 root 用户的密码,并输入类似于以下 SQL 查询的查询:
mysql> CREATE DATABASE mysqldb;
- 现在,使用以下命令检查所有可用的数据库:
mysql> SHOW DATABASES;
前述命令的输出如下:

前述截图显示了我们可以使用的数据库。
现在,我们可以为mysqldb数据库创建一个表,但我们需要先选择数据库。请注意,在使用数据库之前,您必须选择使用它。
- 输入以下命令:
mysql> USE mysqldb;
- 使用以下代码创建向数据库添加表的查询:
mysql> CREATE TABLE u_dbtable (
-> info_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-> user_name VARCHAR(140) UNIQUE,
-> user_email VARCHAR(270) UNIQUE,
-> user_passw TEXT,
-> user_data TEXT);
- 现在,使用以下命令显示数据库中的表:
mysql> SHOW TABLES;
- 使用以下命令检查连接到数据库的用户:
mysql> SELECT CURRENT_USER();
与 PostgreSQL 类似,Python 标准库不包含 MySQL——需要通过第三方包适配器(如 PyMySQL)下载和安装。为此,请在命令行或终端中输入以下命令:
> pip install PyMySQL
现在,我们可以开始使用基于 Python 的应用程序来使用 MySQL 数据库。我们在 u_tools.py 文件中使用 MySQL 数据库:
- 在
u_tools.py文件中,将以下import语句添加到import部分:
...
import pymysql
...
- 如前所述,将用于将值插入到 MySQL 数据库表中的函数添加到
u_tools.py文件的UTools类中,如下所示:
...
class UTools(object):
...
def mysql_insert(self, username=None, email=None,
passw=None, data=None):
dbcon = pymysql.connect(host="localhost", user="root",
password="rootpassword", db="mysqldb")
dbcursor = dbcon.cursor()
sql_query = """INSERT INTO u_dbtable (user_name,
user_email, user_passw,
user_data) VALUES (%s, %s, %s, %s);"""
udata = (str(username), str(email),
str(passw), str(data))
dbcursor.execute(sql_query, udata)
dbcon.commit()
dbcursor.close()
dbcon.close()
...
上一函数将连接到 MySQL 数据库并插入用户数据。
- 添加以下函数,该函数将用于从 MySQL 数据库中选择值:
...
...
def mysql_select(self):
dbcon = pymysql.connect(host="localhost", user="root",
password="rootpassword", db="mysqldb")
dbcursor = dbcon.cursor()
sql_query = """SELECT info_date, user_name, user_email,
user_passw, user_data FROM u_dbtable;"""
dbcursor.execute(sql_query)
dbdata = dbcursor.fetchall()
dbcursor.close()
dbcon.close()
return dbdata
...
上一函数将连接到 MySQL 数据库并选择用户数据。
- 在
u_app.py文件的UApp类中,添加用于插入和选择数据库值的 MySQL 工具。将 MySQL 功能添加到UApp类的data()函数中,如下所示:
...
...
def data(self, action):
...
if self.actx == "PostgreSQL":
...
if self.actx == "MySQL":
try:
dbdata = self.mysql_select()
for dtx in dbdata:
self.text_edit.append(
"%s\n%s\n%s\n%s\n%s" % (
dtx[0], dtx[1], dtx[2],
dtx[3], dtx[4]))
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
上一条指令将使用 mysql_select() 函数从数据库中读取用户数据并将其附加到文本字段。
- 接下来,将以下代码添加到
save_data()函数中:
...
...
def save_data(self):
...
...
elif self.actx == "PostgreSQL":
...
elif self.actx == "MySQL":
self.user_data7(uname, umail, upass, udata)
...
...
...
...
上一条指令将调用带有指定用户数据的 user_data7() 函数。
- 将
user_data7()函数添加到UApp类的末尾,如下所示:
...
...
def user_data7(self, uname, umail, upass, udata):
try:
self.mysql_insert(username=uname, email=umail,
passw=upass, data=udata)
except Exception as err:
self.error = err
...
上一条指令将使用 UTools 类的 mysql_insert() 函数将值插入到 MySQL 数据库中。现在,MySQL 数据库操作可用!
Qt SQL
在 Qt 库中,Qt SQL 模块提供了与 GUI 应用程序的 SQL 数据库集成。此模块包括实现驱动程序、API 和用户界面层的类。目前可用的与驱动程序相关的类有 QSqlDriver、QSqlDriverCreatorBase 和 QSqlResult。对于 API,有 QSqlDatabase、QSqlQuery、QSqlField、QSqlIndex、QSqlRecord 和 QSqlError 等类。实现用户界面层的类包括 QSqlQueryModel、QSqlTableModel 和 QSqlRelationalTableModel。为了在我们的应用程序中使用此模块,我们需要将以下行添加到 u_tools.py 文件中:
- 将以下代码添加到 PyQt5
u_tools.py文件的import部分:
...
from PyQt5 import QtSql
...
- 将以下代码添加到 PySide2
u_tools.py文件的import部分:
...
from PySide2 import QtSql
...
现在我们来看看 QtSql 模块中包含的一些类,这些类用于在我们的应用程序中处理 SQL 数据库。
QSqlDatabase
此类实现了 SQL API 层并创建了应用程序中数据库的连接。此类的声明语法如下:
sql_db = QtSql.QSqlDatabase()
QSqlDatabase 类通过以下函数增强了功能。
add
sql_db.addDatabase(str, str) 函数将数据库及其驱动程序类型(第一个参数)和连接名称(第二个参数)添加到连接列表中。
可以为数据库连接指定的驱动程序类型如下:
-
"QSQLITE": SQLite3 或更高版本。 -
"QSQLITE2": SQLite2。 -
"QPSQL": PostgreSQL 驱动程序。 -
"QMYSQL": MySQL 驱动程序。 -
"QODBC": ODBC 驱动程序(包括 Microsoft SQL Server)。 -
"QOCI": Oracle 调用接口驱动程序。 -
"QDB2": IBM DB2。 -
"QIBASE": Borland InterBase 驱动程序。 -
"QTDS": Sybase 自适应服务器。
set
以下函数设置数据库连接的参数和属性:
sql_db.setConnectOptions(str): 这设置在参数中指定的数据库特定选项。
sql_db.setDatabaseName(str): 这将数据库连接中指定的参数设置的数据库名称。
sql_db.setHostName(str): 这将设置主机名,如参数中指定。
sql_db.setNumericalPrecisionPolicy(QtSql.QSql.NumericalPrecisionPolicy): 这将设置数值精度策略,如参数中指定。
sql_db.setPassword(str): 这设置参数中指定的密码。
sql_db.setPort(int): 这将设置参数中指定的端口号。
sql_db.setUserName(str): 这设置参数中指定的用户名。
is
以下函数返回与数据库连接状态相关的布尔值(bool):
sql_db.isDriverAvailable(str): 如果参数中指定的驱动程序可用,则返回True。
sql_db.isOpen(): 如果此数据库连接打开,则返回True;否则,返回False。
sql_db.isOpenError(): 如果在打开数据库连接时发生错误,则返回True。
sql_db.isValid(): 如果QtSql.QSqlDatabase对象具有有效的驱动程序,则返回True。
functional
以下函数与数据库连接的当前值、功能更改等相关:
sql_db.cloneDatabase(QtSql.QSqlDatabase, str): 这克隆数据库连接(第一个参数)并将其存储为连接名称(第二个参数)。
sql_db.close(): 这关闭此数据库连接。
sql_db.commit(): 这将事务提交到数据库,例如INSERT操作。
sql_db.connectionName(): 这返回数据库连接的连接名称。
sql_db.connectionNames(): 这返回数据库连接的连接名称列表。
sql_db.connectOptions(): 这返回与数据库连接一起使用的连接选项。
sql_db.contains(str): 如果连接列表包含参数中指定的连接名称,则返回True。
sql_db.database(str, bool): 这返回一个QtSql.QSqlDatabase类型的数据库连接,带有连接名称(第一个参数);如果open(第二个参数)为True,则未打开的数据库连接将打开。
sql_db.databaseName(): 这返回数据库连接的数据库名称。
sql_db.driver(): 这返回用于数据库连接的QtSql.QSqlDriver类型的数据库驱动程序。
sql_db.driverName(): 此函数返回用于数据库连接的驱动程序名称。
sql_db.drivers(): 此函数返回所有可用驱动程序的列表。
sql_db.exec_(str): 此函数执行 SQL 语句并返回 QtSql.QSqlQuery 类型的对象。
sql_db.hostName(): 此函数返回数据库连接的主机名。
sql_db.lastError(): 此函数返回数据库中发生的最后一个错误。
sql_db.numericalPrecisionPolicy(): 此函数返回数据库连接的 QtSql.QSql.NumericalPrecisionPolicy 类型的默认精度策略。
sql_db.open(): 此函数使用当前连接值打开数据库连接。
sql_db.open(str, str): 此函数使用指定的用户名(第一个参数)和密码(第二个参数)打开数据库连接。
sql_db.password(): 此函数返回数据库连接的密码。
sql_db.port(): 此函数返回数据库连接的端口号。
sql_db.primaryIndex(str): 此函数返回参数中指定的表的索引。
sql_db.record(str): 此函数返回 QtSql.QSqlRecord 类型的记录,其中填充了参数中指定的表中字段的名称。
sql_db.registerSqlDriver(str, QtSql.QSqlDriverCreatorBase):此函数使用名称(第一个参数)将 SQL 驱动程序(第二个参数)注册。
sql_db.removeDatabase(str): 此函数删除参数中指定的名称的数据库连接。
sql_db.rollback(): 这将回滚数据库事务。
sql_db.tables(QtSql.QSql.TableType): 此函数返回与数据库连接一起使用的数据库中表列表。
sql_db.transaction(): 这将在数据库中开始一个事务,例如插入值。
sql_db.userName(): 此函数返回数据库连接的用户名。
QSqlQuery
QSqlQuery 类执行与应用程序中数据库操作相关的 SQL 语句和数据库特定命令。此类的声明语法如下:
sql_query = QtSql.QSqlQuery()
QSqlQuery 类通过以下功能增强了功能。
add
此 add 函数添加 SQL 查询。
sql_query.addBindValue(object, PySide2.QtSql.QSql.ParamType) 函数将绑定值(第一个参数)添加到值列表中,使用类型(第二个参数)。
set
以下函数设置 SQL 查询的参数和属性:
sql_query.setForwardOnly(bool): 如果此参数为 True,则设置仅向前模式。
sql_query.setNumericalPrecisionPolicy(QtSql.QSql.NumericalPrecisionPolicy):此函数设置参数中指定的数值精度策略,该策略将用于查询。
is
以下函数返回与 SQL 查询状态相关的布尔值 (bool):
sql_query.isActive(): 如果查询是活动的,则此函数返回 True。
sql_query.isForwardOnly(): 如果结果集只能向前滚动,则此函数返回 True。
sql_query.isNull(int): 如果查询未激活或未定位到有效记录,如果没有指定参数中的字段,或如果此字段为 null,则返回 True。
sql_query.isNull(str): 如果此查询未激活,未定位到有效记录,如果参数中没有指定名称的字段,或如果此字段为 null,则返回 True。
sql_query.isSelect(): 如果当前查询使用 SQL SELECT 语句从数据库检索值,则返回 True。
sql_query.isValid(): 如果此查询定位到有效记录,则返回 True。
功能性
以下函数与 SQL 查询的当前值、功能变化等相关:
sql_query.at(): 这返回查询的当前内部位置。
sql_query.bindValue(str, object, QtSql.QSql.ParamType): 这设置占位符(第一个参数),该占位符将在语句中绑定到值(第二个参数),并使用类型(第三个参数)。
sql_query.bindValue(int, object, QtSql.QSql.ParamType): 这设置在位置(第一个参数)的占位符,该占位符将在语句中绑定到值(第二个参数),并使用类型(第三个参数)。
sql_query.boundValue(str): 这返回参数指定的占位符的绑定值。
sql_query.boundValue(int): 这返回参数指定位置的占位符的绑定值。
sql_query.boundValues(): 这返回一个包含绑定值的字典。
sql_query.clear(): 这清除查询的结果。
sql_query.driver(): 这返回与查询一起使用的 QtSql.QSqlDriver 类型的数据库驱动程序。
sql_query.exec_(): 这将执行预准备的查询语句,如果成功则返回 True。
sql_query.exec_(str): 这执行参数中指定的查询语句,如果成功则返回 True。
sql_query.execBatch(QtSql.QSqlQuery.BatchExecutionMode): 这将以批处理方式执行查询语句,参数指定了执行模式。可用的模式包括 QtSql.QSqlQuery.ValuesAsRows—0,用于更新多行,以及 QtSql.QSqlQuery.ValuesAsColumns—1,用于更新单行。
sql_query.executedQuery(): 这返回最后成功执行的查询。
sql_query.finish(): 此函数指示在查询重新执行之前,不再从查询中获取更多数据。
sql_query.first(): 这检索结果中的第一条记录,并将查询定位到检索到的记录。
sql_query.last(): 这检索结果中的最后一条记录,并将查询定位到检索到的记录。
sql_query.lastError(): 这返回与查询一起发生的最后 QtSql.QSqlError 类型的错误。
sql_query.lastInsertId(): 这返回最后插入行的对象 ID。
sql_query.lastQuery(): 这返回最后查询的文本。
sql_query.next(): 这检索结果中的下一个记录。
sql_query.nextResult(): 这将丢弃查询的结果集,如果可用,则导航到下一个结果。
sql_query.numericalPrecisionPolicy(): 这返回当前使用的QtSql.QSql.NumericalPrecisionPolicy类型的精度策略。
sql_query.numRowsAffected(): 这返回与 SQL 语句的结果相关的行数。
sql_query.prepare(str): 这将准备参数中指定的 SQL 查询语句以执行。
sql_query.previous(): 这检索结果中的上一个记录。
sql_query.record(): 这返回包含此查询字段信息的QtSql.QSqlRecord类型的记录。
sql_query.result(): 这返回与查询相关的QtSql.QSqlResult类型的结果。
sql_query.seek(int, bool): 这根据第二个参数,在特定索引(第一个参数)处检索记录。
sql_query.size(): 这返回结果中的行数。
sql_query.value(int): 这返回当前记录参数中指定的索引的字段值。
sql_query.value(str): 这返回当前记录参数中指定的名称的字段值。
Qt SQL 示例
让我们现在看看QtSql模块在我们应用程序中的实际应用示例。首先,我们需要打开u_tools.py文件,并向其中添加以下行:
- 将
QSqlDatabase添加到UTools类的__init__()函数中,以打开现有数据库或创建一个新数据库(如果不存在),如下所示:
...
class UTools(object):
def __init__(self):
...
self.qtsql_db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
self.qtsql_db.setDatabaseName("data/u_db.sqlite")
self.qtsql_db.open()
...
...
数据库驱动程序的名称在addDatabase()方法中定义。如果可用,还可以使用其他驱动程序。此方法设置名称并打开数据库。
- 接下来,添加将值插入打开的 SQLite 数据库的函数,如下所示:
...
...
def sql_qt_insert(self, username=None, email=None,
passw=None, data=None):
query = QtSql.QSqlQuery(self.qtsql_db)
query.prepare("""INSERT INTO u_dbtable (user_name,
user_email, user_passw, user_data)
VALUES (:user_name, :user_email,
:user_passw, :user_data);""")
query.bindValue(":user_name", username)
query.bindValue(":user_email", email)
query.bindValue(":user_passw", passw)
query.bindValue(":user_data", data)
query.exec_()
...
上述函数使用QSqlQuery类创建 SQL 查询并通过插入值绑定用户数据。
- 添加以下函数,该函数将从数据库中选择值:
...
...
def sql_qt_select(self):
query = QtSql.QSqlQuery(self.qtsql_db)
query.exec_("""SELECT * FROM u_dbtable;""")
return query
...
上述函数将根据查询选择用户数据并返回。
- 在
u_app.py文件的UApp类中,添加用于插入和选择数据库值的QtSQL工具。将QtSql模块功能添加到UApp类的data()函数中,如下所示:
...
...
def data(self, action):
...
if self.actx == "MySQL":
...
if self.actx == "QtSQL":
try:
dbdata = self.sql_qt_select()
while dbdata.next():
self.text_edit.append(
"%s\n%s\n%s\n%s\n%s" % (
dbdata.value(0),
dbdata.value(1),
dbdata.value(2),
dbdata.value(3),
dbdata.value(4)))
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
上一条指令使用了sql_qt_select()函数从数据库中选择用户数据,并将返回的结果附加到文本字段中。
- 接下来,向
save_data()函数中添加以下内容:
...
...
def save_data(self):
...
...
elif self.actx == "MySQL":
...
elif self.actx == "QtSQL":
self.user_data8(uname, umail, upass, udata)
...
...
...
...
上一条指令使用指定的用户数据参数调用了user_data8()函数。
- 现在将
user_data8()函数添加到UApp类的末尾,如下所示:
...
...
def user_data8(self, uname, umail, upass, udata):
try:
self.sql_qt_insert(username=uname,
email=umail,
passw=upass,
data=udata)
except Exception as err:
self.error = err
...
前面的函数将调用UTools类的sql_qt_insert()函数,将用户数据插入 SQLite 数据库。这个例子演示了在实际中QtSql模块的使用。正如你所见,它与标准的第三方工具不同,这种结构可能难以理解。在撰写本文时,默认情况下,此模块仅有一个"QSQLITE"驱动程序,因此其他驱动程序需要额外加载和配置。是否使用此模块代替第三方数据库工具取决于你。
NoSQL
NoSQL 数据库是存储数据的其他现代机制。NoSQL 被称为非 SQL 或非关系型,因为数据是以不同于关系型 SQL 数据库中的表格关系的方式建模的。NoSQL 数据库通常用于大数据和实时 Web 应用。NoSQL 的另一个流行定义是不仅限于 SQL。这意味着 NoSQL 数据库可以支持 SQL 或与 SQL 数据库并存。
在我们的应用程序中实现 NoSQL 数据库可能会简化文档存储并使数据处理更容易,因此让我们看看如何在 GUI 中使用最流行的 NoSQL 数据库的一些简短示例。
MongoDB
MongoDB 是一个开源的 NoSQL 文档存储数据库。该数据库以字段/值对的数据结构记录文档。这些文档类似于我们在pandas部分中创建的 JSON 对象。MongoDB 的值包括文档、数组和文档数组。要使用 MongoDB,你需要从官方源下载并安装它,mongodb.com,使用提供的文档。还建议你下载并安装可用的附加开发工具。
与前面的章节类似,在App/App_PySide2/data/和App/App_PyQt5/data/目录中创建MongoDB_1/文件夹,数据库将位于这些目录中:
- 首先,在你的命令行或 Terminal 中运行以下类似的命令,具体取决于你的操作系统:
> cd /Path/To/The/Installed/MongoDB/bin
- 找到可执行文件,例如
mongod(Linux)或mongod.exe(Windows),并运行以下命令:
> mongod --dbpath=/Path/To/The/App/App_PySide2/data/MongoDB_1
- 要连接到 MongoDB,使用新命令行或 Terminal 中的
mongo或mongo.exe等命令,如下所示:
> /Path/To/The/installed/MongoDB/bin/mongo
- 使用 Python 操作 MongoDB 需要一个适配器;在这种情况下,是
pymongo。使用以下方式使用pip安装适配器:
> python -m pip install pymongo
现在我们可以使用我们的应用程序的 MongoDB 功能了!
是时候向u_tools.py文件中添加一些行:
- 打开
u_tools.py文件,并在import部分添加以下行:
...
import pymongo
...
- 将以下函数添加到
u_tools.py文件中的UTools类。这将向 MongoDB 数据库插入值:
...
...
def mongo_insert(self, username=None, email=None,
passw=None, data=None):
client = pymongo.MongoClient('localhost', 27017)
db = client['umongodb']
post = {"User Name": username, "Email": email,
"Password": passw, "Data": data}
posts = db.posts
posts.insert_one(post)
...
前面的函数使用指定的主机和端口连接到 MongoDB 数据库。
- 添加用于从 MongoDB 选择值的函数,如下所示:
...
...
def mongo_select(self):
client = pymongo.MongoClient('localhost', 27017)
db = client['umongodb']
dbdata = db.posts.find()
return dbdata
...
在本例中,数据库的名称指定为'umongodb'。此函数从数据库中返回所有用户数据。
- 在
u_app.py文件中的UApp类中,添加 MongoDB 工具以插入和选择数据库值。将 MongoDB 功能添加到UApp类的data()函数中,如下所示:
...
...
def data(self, action):
...
if self.actx == "QtSQL":
...
if self.actx == "MongoDB":
try:
dbdata = self.mongo_select()
for dtx in dbdata:
self.text_edit.append(
"%s\n%s\n%s\n%s" % (
dtx["User Name"],
dtx["Email"],
dtx["Password"],
dtx["Data"]))
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
前面的指令使用mongo_select()函数从数据库中读取数据并将其追加到文本字段。
- 现在,将以下内容添加到
save_data()函数中:
...
...
def save_data(self):
...
...
elif self.actx == "QtSQL":
...
elif self.actx == "MongoDB":
self.user_data9(uname, umail, upass, udata)
...
...
...
...
elif指令将使用带有指定参数的user_data9()函数。
- 现在将
user_data9()函数添加到UApp类的末尾,如下所示:
...
...
def user_data9(self, uname, umail, upass, udata):
try:
self.mongo_insert(username=uname,
email=umail,
passw=upass,
data=udata)
except Exception as err:
self.error = err
...
前面的函数将用于将数据插入到数据库中。这是我们在应用程序中实现 MongoDB 的一个简单、简短和基本的示例。要详细了解 MongoDB 的所有功能和优势,建议阅读 Mongo 的官方文档。
CouchDB
另一种流行的 NoSQL 数据存储类型是 Apache CouchDB。这个数据库使用与上一节中描述的类似机制,但通过额外的功能进行了改进。CouchDB 是用于实现存储文档的现代化网络工具。如果你使用 HTTP 和 JSON 数据格式,这个数据库是首选选择。
要在你的应用程序中使用这个数据库,你需要按照couchdb.apache.org/上针对适当操作系统的说明进行下载和安装。当所有必需的软件都安装并配置好之后,就是启动 CouchDB 的时候了。为了配置和启动这个数据库,建议使用操作系统的额外文档,因为所需的步骤可能不同。
当 CouchDB 打开后,在网页浏览器的搜索栏中输入http://127.0.0.1:5984/_utils/。应该会出现一个解释 Couch 数据库管理的页面,以及额外的说明。现在,使用这个网页的功能创建一个名为u_couchdb的数据库。一旦数据库创建成功,你就可以创建一个文档。为此,点击网页上的创建文档按钮,并添加以下行:
{
"_id": "0e2484058a69f09841325dfa0d000b4e",
"User Name": "user",
"User email": "user@email.com",
"User password": "userpassword",
"User Data": "Hello CouchDB !!!"
}
注意,_id将会不同。当文档创建时,数据库的第一个记录应该出现在网页上。为了使用 Python 实现这些操作,需要额外的工具来连接到 Couch 数据库,例如CouchDB包。使用以下命令通过pip安装:
> pip install CouchDB
现在打开u_tools.py文件,并添加一些行以实现应用程序中的功能:
- 将以下代码添加到
u_tools.py文件的import部分:
...
import couchdb
...
- 接下来,将以下函数添加到
u_tools.py文件中的UTools类中:
...
class UTools(object):
...
def couch_insert(self, username=None, email=None,
passw=None, data=None):
couch = couchdb.Server("http://127.0.0.1:5984/")
db = couch["u_couchdb"]
dbdata = {"User Name": username,
"User email": email,
"User password": passw,
"User Data": data}
db.save(dbdata)
...
前面的函数将使用指定的 URL(主机和端口)连接到数据库,并将值插入到 CouchDB 中。
- 现在,添加用于从数据库中选择值的函数,如下所示:
...
...
def couch_select(self):
couch = couchdb.Server("http://127.0.0.1:5984/")
db = couch["u_couchdb"]
return db
...
前面的函数将连接到数据库,选择可用值,并返回数据。在 u_app.py 文件的 UApp 类中,添加用于插入和选择数据库值的 CouchDB 工具。
- 将 CouchDB 功能添加到
UApp类的data()函数中,如下所示:
...
...
def data(self, action):
...
if self.actx == "MongoDB":
...
if self.actx == "CouchDB":
try:
dbdata = self.couch_select()
for dtx in dbdata.view("_all_docs",
include_docs=True):
self.text_edit.append(
"%s\n%s\n%s\n%s" % (
dtx["doc"]["User Name"],
dtx["doc"]["User email"],
dtx["doc"]["User password"],
dtx["doc"]["User Data"]))
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
前面的指令使用了 UTools 类的 couch_select() 函数从 CouchDB 中选择用户数据。
- 现在,将以下代码添加到
save_data()函数中:
...
...
def save_data(self):
...
...
elif self.actx == "MongoDB":
...
elif self.actx == "CouchDB":
self.user_data10(uname, umail, upass, udata)
...
...
...
...
前面的指令使用了带有指定用户数据参数的 user_data10() 函数。
- 现在,将
user_data10()函数添加到UApp类的末尾,如下所示:
...
...
def user_data10(self, uname, umail, upass, udata):
try:
self.couch_insert(username=uname,
email=umail,
passw=upass,
data=udata)
except Exception as err:
self.error = err
...
前面的函数将调用 UTools 类的 couch_insert() 函数将指定的用户数据插入到数据库中。当 u_app.py 文件运行时,你可以与 CouchDB 通信以插入值并在文档中选择它们,这些值将在 CouchDB 功能提供的 Fauxton 工具的网页上表示。
摘要
本章介绍了构建应用程序最重要的部分——数据处理。在本章中,我们还解释了在应用程序中处理数据的初步步骤。正如我们在本章中概述的,实现的建设方式有些相似,并且它们的使用是可选的,因此我们现在将向前推进,专注于扩展 GUI 应用程序的功能。
下一章将解释应用程序与其用户之间的通信机制。在 Qt 库中,这是通过信号、槽和事件来实现的。
第三部分:向 GUI 应用程序添加功能
在本节中,我们将通过添加功能和额外特性来完成我们的 GUI 应用程序的实现。
本节包含以下章节:
-
第十五章,信号、槽和事件处理器
-
第十六章,线程和多进程
-
第十七章,完成应用、嵌入式设备和测试
第十五章:信号、槽和事件处理器
在本书的前几章中,我们介绍了 GUI 应用程序的图形组件,以及一些与使用数据相关的附加功能解释。然而,Qt 库有一个非常重要的通信组件,它通过点击按钮、悬停标签、拖动元素、选择框选项等多种方式实现了用户与应用程序之间的通信。在第十章“图形表示”中,我们介绍了 Qt 库的QObject类,它实现了功能,并且是便于对象之间通信的基类之一。这种行为是 GUI 应用程序的主要目标,需要学习。
在本章中,我们将涵盖以下主题:
-
信号/槽机制
-
事件和事件处理器
信号和槽
通常,用于开发图形应用程序的工具包和框架使用称为回调的通信机制。这种方法将某个函数的回调指针发送到另一个函数,以便在需要时调用回调过程。Qt 库提供了回调的替代方案,即信号和槽机制。这种技术用于对象之间的通信。信号可以由对象发出;例如,按钮被点击(信号)并调用响应特定信号的函数(槽)。
我们可以将 Qt 库的信号/槽机制描述如下:在继承方案中从QObject类继承的所有类都可以包含信号和槽。这种机制被称为类型安全。信号的定义必须与接收槽的签名相匹配,并且可以接受任何类型和数量的参数,同时仍然保持类型安全。
一些基本的信号/槽特性如下:
-
一个信号可以连接到多个槽。
-
一个槽可以连接到多个信号。
-
一个信号可以连接到另一个信号。
-
信号/槽连接可以是同步(直接)或异步(排队)的。
-
信号/槽连接可以通过线程实现。
现在,让我们更详细地分别描述信号和槽组件。
信号
信号可以被定义为对象发出的信号动作,以实现确保结果的过程。例如,当我们点击想要的按钮时,clicked()、pressed()或triggered()信号将在应用程序中产生结果,例如关闭窗口、颜色变化、发送电子邮件等。信号通过与 C++语言表示相关的公共访问函数执行。在这种情况下,当信号被发出时,连接到这些信号的槽通常会被立即作为正常函数调用执行。
信号和槽机制完全独立于 GUI 事件循环,并且 emit 语句之后的代码仅在所有槽都必须作为结果返回时才会执行。在这种情况下,当多个槽连接到同一信号时,这些槽将根据它们连接的方式依次执行。要使用这些信号,让我们描述基本知识并创建一个新的信号。正如我们之前在 第四章 “PyQt 和 PySide 入门”中提到的,信号声明在 PyQt5 和 PySide2 绑定之间存在一些差异:
- 首先,从
import语句开始,并将以下行添加到utools.py文件中:
- 在 PyQt5 的
import语句的情况下,将以下内容添加到utools.py文件中:
...
from PyQt5.QtCore import pyqtSignal as app_signal
...
- 在 PySide2 的
import语句的情况下,将以下内容添加到utools.py文件中:
...
from PySide2.QtCore import Signal as app_signal
...
在应用程序的上下文中,我们现在有导入的未绑定信号作为类属性。此未绑定信号可以检索以下参数:
app_signal(types, name, revision, arguments)
参数定义如下:
-
types: 定义此信号签名的类型,例如str、int、list或任何 Python 类型对象。 -
name: 作为关键字参数的此信号的名称。 -
revision: 作为关键字参数导出到 QML 的信号的修订版本。 -
arguments: 导出到 QML 的此信号参数名称的序列。
- 要绑定信号,我们需要将其引用为类实例的属性,Python 绑定将自动将实例绑定到信号以创建绑定信号。我们可以通过向
u_tools.py文件中的UTools类添加以下行来实现。在__init__()函数之前将绑定信号添加到类中:
...
class UTools(object):
sig1 = app_signal(int)
def __init__(self):
...
...
...
这种方式并非偶然,并且建议在应用程序类中构建信号时使用。现在,我们可以将整数作为类型参数的绑定信号。绑定信号有以下方法:
-
sig1.connect(object, type, no_receiver_check=bool): 这将创建一个连接。此信号连接的方法定义如下: -
object: 绑定的信号或槽,作为连接到它的 Python 可调用对象。 -
type: 连接的类型 (QtCore.Qt.ConnectionType)。 -
no_receiver_check: 这将抑制对底层接收器实例是否仍然存在的检查,并无论如何都传递信号。 -
sig1.disconnect([object]): 这将从信号断开一个或多个槽。信号断开的方法定义为object;这是作为 Python 可调用对象连接到的绑定信号或槽。 -
sig1.emit(*args): 这会发出一个信号,其中*args是可选的参数序列,这些参数将被传递到槽中。
槽
槽可以定义为当信号发出时将处理的函数,并且它们需要实现某些功能;例如,使用 close() 函数关闭窗口,使用 setColor(QtGui.QColor("FFFFFF")) 属性更改颜色,或使用 smtplib Python 标准库模块的 sendmail() 函数发送消息。
槽与普通函数之间的区别在于,槽在某种意义上具有特殊功能,信号可以连接到它们。换句话说,信号定义了某些函数将是槽。实际上,槽可以是任何 Python 可调用对象,但在某些情况下,我们可以显式定义槽并装饰函数。连接到装饰的 Python 方法在内存使用方面有一些优势。我们还可以创建新的槽和新的信号。为此,我们需要将以下行添加到 u_tools.py 文件的 import 语句中:
- 在 PyQt5 的
import语句中,将以下内容添加到utools.py文件中:
...
from PyQt5.QtCore import pyqtSlot as app_slot
...
- 在 PySide2 的
import语句中,将以下内容添加到utools.py文件中:
...
from PySide2.QtCore import Slot as app_slot
...
import 语句也有所不同。app_slot(types, name, result, revision) 参数可以传递给槽。其函数可以定义如下:
-
types: 定义此槽签名类型的类型,例如str、int、list或任何 Python 类型对象。 -
name: 作为关键字参数的此槽的名称。 -
result: 定义此槽签名的结果类型,例如str、int、list或任何 Python 类型对象。 -
revision: 作为关键字参数导出到 QML 的槽的版本。
这些槽通常以以下方式装饰:
...
...
@app_slot(int, name='slot_func')
def slot_func(self, num):
# Some processing...
...
...
信号-槽连接
如我们所知,许多 GUI 应用程序都是使用 Qt 库的 PyQt/PySide Python 绑定构建的。如果我们审查这些应用程序的代码,我们将看到信号/槽连接构造的风格有所不同。我们需要考虑应用程序中可用的构造。已绑定的信号具有 connect()、emit() 和 disconnect() 方法,它们提供了与信号和槽的操作。返回信号宏签名的 signal() 属性也是可用的。
连接
我们可以使用 triggered() 信号将选择选项连接到提供这些选项功能的槽。这里使用了非静态连接。然而,出于演示目的,也将使用静态构造。现在,我们需要查看 u_app.py 文件中 UApp 类的行:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.combox1.activated.connect(self.txt_table)
self.mb1.triggered.connect(self.files)
self.mb3.triggered.connect(self.data)
self.mb4.triggered.connect(self.options)
...
self.push_but1.clicked.connect()
self.push_but2.clicked.connect(lambda:
self.text_edit.setText("HELLO"),
QtCore.Qt.QueuedConnection)
...
让我们考虑与信号相关的行。应用程序的组合框用于在Text和Table之间选择一个选项,并使用activated()信号以非静态方式构建,该信号在鼠标悬停和点击时激活选项,并调用槽。顶部面板菜单使用triggered()信号连接到相关槽,也是非静态的。Ok按钮将使用clicked()信号(非静态构建)来调用 lambda 函数。换句话说,非静态方法可以使用以下语法描述:
object.signal.connect(SLOT, type=QtCore.Qt.ConnectionType)
在这里,object是一个小部件或另一个信号,signal是一个可用的信号或构造的信号,connect()方法连接到槽,而SLOT是一个函数/方法或 Python 可调用对象。type参数描述了将要使用的连接类型。以下类型的连接可用:
-
QtCore.Qt.AutoConnection—0: 这是默认类型。如果信号的接收者在发出信号的线程中,将使用QtCore.Qt.DirectConnection。如果接收者和发出信号的线程不同,将使用QtCore.Qt.QueuedConnection。 -
QtCore.Qt.DirectConnection—1: 立即调用此槽,并以与发出信号相同的方式在相同线程中执行。 -
QtCore.Qt.QueuedConnection—2: 当控制返回接收者线程的事件循环时,将调用此槽,并在接收者线程中执行。 -
QtCore.Qt.BlockingQueuedConnection—3: 当控制返回接收者线程的事件循环时,将调用此槽,并在接收者线程中执行,同时阻塞信号线程。如果发出信号和接收者的线程相同,则不能使用此方法。 -
QtCore.Qt.UniqueConnection—3: 将使用唯一连接,如果相同的信号已经连接到相同的小部件对上的相同槽,则另一个连接将失败。
使用QObject类构建连接的方法也有以下静态方法:
QtCore.QObject.connect(object, SIGNAL, SLOT, type=QtCore.Qt.ConnectionType)
在这里,object是一个小部件、信号等;SIGNAL,作为QtCore.SIGNAL ("signal_name()"),是一个可用的信号或构造的信号;而SLOT是一个函数/方法或 Python 可调用对象,也可以是QtCore.SLOT ("slot_name()")。type参数描述了将要使用的连接类型。connect方法用作QtCore模块中QObject类的静态函数。
在静态函数的情况下,我们有以下:
QtCore.QObject.connect(object1, SIGNAL, object2, SLOT, type=QtCore.Qt.ConnectionType)
在这里,object1(小部件、信号等)是QtCore.QObject类型的发送者,SIGNAL(QtCore.SIGNAL ("signal_name()"))是QtCore.QMetaMethod类型的信号,object2(小部件、信号等)是QtCore.QObject类型的接收者,SLOT(QtCore.SLOT("slot_name()"))是QtCore.QMetaMethod类型的功能/方法,而type是连接将要使用的参数。
实际上,使用QObject类的静态构造在 PySide 和 PySide2,或 PyQt4 中是可用的。PyQt5 绑定不支持这些构造,并使用之前描述的新式的信号和槽。为了避免混淆并保持材料的复杂性,我们不会这样做。在我们的应用程序中,我们将使用非静态方法在信号和槽之间建立连接。
emit
在某些情况下,当应用程序正在处理时,需要从应用程序中发出信号。emit()方法可以在连接的信号/槽对象之间执行信号的发射,同时(可选地)向接收者发送一些相关数据。这对于使用线程来标准化过程执行的应用程序非常有用,这将在第十六章线程和多进程中详细讨论。
让我们考虑一个与emit()方法相关的例子,其中使用这些各种数据处理工具的应用程序开始变慢。我们将更改用于打开 1,000 行的 pandas 工具函数,使用线程来分割这个功能,并操作将要写入文件的 1,000,000 行/5 列的表格。为此,我们需要打开u_tools.py文件并添加/更改以下行:
- 首先,我们需要将这些行添加到这些文件的
import部分:
- 在 PyQt5 的
u_tools.py文件的情况下,将以下内容添加到import部分:
...
from PyQt5.QtCore import QThread
import time
...
- 在 PySide2 的
u_tools.py文件的情况下,将以下内容添加到import部分:
...
from PySide2.QtCore import QThread
import time
...
- 在
UTools类之前,我们需要添加将使用 pandas 读取/写入 CSV 文件的线程类。
添加带有线程的WPandas类以写入 CSV 文件:
...
class WPandas(QThread):
sig1 = app_signal(object, str)
def __init__(self, parent=None):
super(WPandas, self).__init__(parent)
def on_source(self, datas):
self.datas = datas
def run(self):
try:
import pandas
uindex = [i for i in range(self.datas[2])]
udata = {"User_Name": range(0, self.datas[2]),
"User_email": range(0, self.datas[2]),
"User_password": range(0, self.datas[2]),
"User_data": range(0, self.datas[2])}
df = pandas.DataFrame(udata, columns=self.datas[3],
index=uindex, dtype=self.datas[5])
df.index.name = "rows\columns"
if self.datas[1] == "csv":
df.to_csv(self.datas[0])
if self.datas[1] == "excel":
df.to_excel(self.datas[0])
if self.datas[1] == "html":
df.to_html(self.datas[0])
if self.datas[1] == "json":
df.to_json(self.datas[0])
if self.isFinished():
self.quit()
except Exception as err:
self.sig1.emit('', str(err))
if self.isFinished():
self.quit()
...
这个类包括sig1信号,如果发生错误,将发出带有错误信息的字符串。
- 现在,添加带有线程的
RPandas类以读取 CSV 文件:
...
class RPandas(QThread):
sig1 = app_signal(object, str)
def __init__(self, parent=None):
super(RPandas, self).__init__(parent)
def on_source(self, datas):
self.datas = datas
def run(self):
try:
import pandas
if self.datas[1] == "csv":
df = pandas.read_csv(self.datas[0],
chunksize=self.datas[6],
engine=self.datas[4])
if self.datas[1] == "excel":
df = pandas.read_excel(self.datas[0])
if self.datas[1] == "html":
df = pandas.read_html(self.datas[0])
if self.datas[1]== "json":
df = pandas.read_json(self.datas[0])
pandas.options.display.max_rows = self.datas[5]
for ch in df:
self.sig1.emit(ch, '')
time.sleep(0.1)
if self.isFinished():
self.quit()
except Exception as err:
self.sig1.emit('', str(err))
if self.isFinished():
self.quit()
...
此类包括sig1信号,该信号将发出带有object类型的DataFrame,如果存在,则带有string类型的错误。CSV 文件将分块读取,并在循环中发出,而不是一次性读取。这样做是因为大文件难以读取,当文本添加到文本字段时可能会出现问题。因为我们需要记住文本编辑字段是另一个线程的一部分——即应用程序的主 GUI 线程——每个块包含 10,000 行,但只显示块中的 9 行。这展示了处理大型数据集的可能性,因为将所有这些数据显示在应用程序的文本字段中可能会使应用程序冻结。
实际上,这并不需要,因为用户不想读取文件的所有行;他们只想操作这些数据并可视化它;这是关键。所有前面的线程都在on_source()函数外部检索数据。
- 现在,我们需要继续添加/修改
u_tools.py文件中的UTools类。
在UTools类的__init__()函数之前添加以下信号:
...
class UTools(object):
...
pandas_sig1 = app_signal(list)
pandas_sig2 = app_signal(list)
def __init__(self):
...
...
这创建了类函数和线程之间的绑定信号,用于通信。这些信号将发送带有参数的列表到线程。
- 现在,我们需要更改
pandas_write()函数,如下所示:
...
...
def pandas_write(self, filename=None, writer="csv",
data=None, columns=None,
index=None, dtype=object):
data = 1000000
index = 1000000
datas = [filename, writer, data, columns, index, dtype]
self.pandas_thread1 = WPandas()
self.pandas_sig1.connect(self.pandas_thread1.on_source)
self.pandas_sig1.emit(datas)
self.pandas_thread1.start()
...
...
在这里,我们正在替换函数中的数据和索引变量。这是可选的,并表明数据将在 0-1,000,000 的data范围内,行数等于 1,000,000 的index。当创建线程实例时,pandas_sig1信号连接到线程的on_source()函数,然后向线程发出带有数据和参数的列表以进行处理。
- 按如下方式更改
pandas_read()函数:
...
...
def pandas_read(self, filename=None, reader="csv", sep=',',
delimiter=None, engine='python',
maxrows=9, chunk=10000):
datas = [filename, reader, sep, delimiter,
engine, maxrows, chunk]
self.pandas_thread2 = RPandas()
self.pandas_sig2.connect(self.pandas_thread2.on_source)
self.pandas_sig2.emit(datas)
self.pandas_thread2.start()
return self.pandas_thread2
...
...
此函数创建线程实例,定义读取参数,例如文件名、读取器和块大小,连接到on_source()函数,并将参数作为列表发出。启动线程后返回此线程,以便可以自由使用。
现在,我们需要更改u_app.py文件中的UApp类。让我们开始吧:
- 在使用 pandas 打开 CSV 文件的
data()函数中进行更改:
...
...
def data(self, action):
...
if self.actx == "Pandas":
try:
pread = self.pandas_read(
filename="data/bigtests.csv",
reader="csv", sep=',')
def to_field(df, er):
if er == '':
self.text_edit.append(
"\n" + str(df))
else:
self.stat_bar.showMessage(
self.actx + ' ' + er)
pread.sig1.connect(
to_field, QtCore.Qt.QueuedConnection)
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
在这里,我们添加了线程的sig1信号,该信号连接到槽,以及一个嵌套的to_field()函数,用于将读取文件的块追加到应用程序的文本编辑字段,或将错误添加到状态栏。
user_data4()函数现在如下所示:
...
...
def user_data4(self, uname, umail, upass, udata):
try:
ucolumns = ["User_Name", "User_email",
"User_password", "User_data"]
self.pandas_write(filename="data/bigtests.csv",
writer="csv", columns=ucolumns)
except Exception as err:
self.error = err
...
...
这些示例展示了我们如何将信号连接到槽(应用程序函数)以及从/到线程和从/到函数发出各种数据。
断开连接
信号断开连接的方法很简单。在某些情况下,我们需要从槽断开信号的连接,这如下所示:
object.signal.disconnect(SLOT)
在这里,object是一个控件或另一个信号,signal是一个使用的信号,具有disconnect方法,以及一个SLOT,这是一个连接到此信号的功能/方法或 Python 可调用对象。
这个构造函数断开了连接的槽的信号。需要注意的是,构造函数需要与信号连接时使用的相同。
Qt 模块
Qt 库提供了几个类来实现信号和槽的附加功能。这些类是QSignalBlocker、QSignalMapper和QSignalTransition。所有这些都在QtCore模块中可用。
QSignalBlocker
这个类实现了对blockSignals()方法的异常安全包装,该方法阻止了项的信号。通常,这个类可以用作blockSignals()方法的替代。这个类的声明语法如下:
signal_blocker = QtCore.QSignalBlocker()
QSignalBlocker类通过以下函数提高了功能。
functional
这些是与功能变化相关的函数。
signal_blocker.reblock(): 这重新阻止了之前取消阻止的信号。
signal_blocker.unblock(): 这将signalsBlocked()状态恢复到阻塞前的状态。
QSignalMapper
这个类实现了从可识别的发送者发出的信号包,并提供了一组信号。它使用与发送者对应的integer、string或widget参数重新发出它们。这个类的声明语法如下:
signal_mapper = QtCore.QSignalMapper()
QSignalMapper类通过以下函数提高了功能。
set
这些是与信号映射器相关的设置参数/属性的函数。
signal_mapper.setMapping(QtCore.QObject, int): 这设置了当map()函数从发送者(第一个参数)发出信号时的映射;映射的信号 ID(第二个参数)将被发出。
signal_mapper.setMapping(QtCore.QObject, str): 这设置了当map()函数从发送者(第一个参数)发出信号时的映射;映射的信号文本(第二个参数)将被发出。
signal_mapper.setMapping(QtCore.QObject, object): 这设置了当map()函数从发送者(第一个参数)发出信号时的映射;映射的信号对象(第二个参数)将被发出。
signal_mapper.setMapping(QtCore.QObject, QtWidgets.QWidget): 这设置了当map()函数从发送者(第一个参数)发出信号时的映射;映射的信号控件(第二个参数)将被发出。
functional
这些是与信号映射器当前值的返回、功能变化等相关的函数。
signal_mapper.map(): 这根据向它发送信号的发送者对象发出信号。
signal_mapper.map(QtCore.QObject): 这根据参数中指定的发送者发出信号。
signal_mapper.mapping(int): 这返回与参数中指定的 ID 关联的 QtCore.QObject 类型的发送者。
signal_mapper.mapping(str): 这返回与参数中指定的文本关联的 QtCore.QObject 类型的发送者。
signal_mapper.mapping(object): 这返回与参数中指定的对象关联的 QtCore.QObject 类型的发送者。
signal_mapper.mapping(QtWidgets.QWidget): 这返回与参数中指定的小部件关联的 QtCore.QObject 类型的发送者。
signal_mapper.removeMappings(QtCore.QObject): 这移除参数中指定的发送者的映射。
信号
QSignalMapper 类的可用信号如下:
signal_mapper.mapped(int): 当从具有 ID 映射设置的对象发出 map() 函数信号时,会发出此信号;ID 通过参数传递。
signal_mapper.mapped(str): 当从具有字符串映射设置的对象发出 map() 函数信号时,会发出此信号;文本通过参数传递。
signal_mapper.mapped(object): 当从具有对象映射设置的对象发出 map() 函数信号时,会发出此信号;对象通过参数传递。
signal_mapper.mapped(QtWidgets.QWidget): 当从具有小部件映射设置的对象发出 map() 函数信号时,会发出此信号;小部件通过参数传递。
QSignalTransition
此类实现信号转换。该类使用参数中定义的源状态构建新的信号转换。此类的声明语法如下:
signal_transit = QtCore.QSignalTransition(QtCore.QState)
QSignalTransition 类通过以下函数改进了功能。
设置
这些是与信号转换相关联的参数/属性设置相关的函数:
signal_transit.setSenderObject(QtCore.QObject): 这设置参数中指定的将与该信号转换关联的发送者。
signal_transit.setSignal(QtCore.QByteArray): 这设置参数中指定的将与该信号转换关联的信号。
功能
这些是与信号转换当前值返回、功能变化等相关联的函数:
signal_transit.senderObject(): 这返回与该信号转换关联的 QtCore.QObject 类型的发送者。
signal_transit.signal(): 这返回与该信号转换关联的 QtCore.QByteArray 类型的信号。
事件和事件处理器
GUI 应用程序的一个重要方面是实现事件和事件处理器。事件通知应用程序有关由于与应用程序进程相关联的内部或外部活动而发生的事情。在 Qt 库中,这种行为通过 Qt 事件系统来表征和实现。通过此系统,事件是派生于QtCore模块的抽象QEvent类的对象。事件可以通过QObject子类的任何实例来处理。通常,事件是通过调用一个虚拟函数——事件处理器——来传递的,这提供了一个方便的方式来处理与应用程序相关的事件。事件处理器通常如下所示:
QEnterEvent
这里,它使用enterEvent()方法作为事件处理器。Qt 框架实现了绘画、调整大小、发送、显示、拖放、鼠标、键盘等事件处理器。下一节描述了在 GUI 应用程序中可以实现的常用事件和事件处理器。
QEvent
这是所有事件类的基类,并提供了具有特殊事件类型功能的事件系统实现。此类的声明语法如下:
event = QtCore.QEvent(QtCore.QEvent.Type)
可以在参数中指定的可用类型完整列表可以在 Qt 文档中找到(doc.qt.io)。QEvent类通过以下函数提高了功能。
设置
此函数与设置与事件相关的参数/属性相关:
event.setAccepted(bool): 如果参数为True,则将此事件设置为接受状态。
是
此函数返回一个与事件状态相关的布尔值(bool):
event.isAccepted(): 如果此事件被接受,则返回True。
功能
这些是与当前事件值的返回、功能变化等相关联的函数:
event.accept(): 此函数设置事件对象的接受标志;此事件将被接受。
event.ignore(): 这个函数设置事件对象的忽略标志;此事件将被忽略。
event.registerEventType(int): 此函数注册并返回一个自定义事件类型,参数中指定了提示。
event.spontaneous(): 如果这是一个系统事件(在应用程序外部),则返回True。
event.type(): 这个函数返回事件类型,作为QtCore.QEvent.Type对象。
事件处理器
此事件的处理程序如下:
def event(self, event):
return True
QEventLoop
此类提供了进入和离开事件循环的功能。主事件循环在应用程序启动时实现,并进入无限循环。此类的声明语法如下:
event_loop = QtCore.QEventLoop()
QEventLoop类通过以下函数提高了功能。
是
此函数返回一个与事件循环状态相关的布尔值(bool):
event.isRunning(): 如果此事件循环正在运行,则返回True;否则,返回false。
功能性
这些是与事件循环当前值的返回、功能变化等相关的函数:
event_loop.exec_(QtCore.QEventLoop.ProcessEventsFlags): 这将进入事件循环,并开始根据参数中指定的标志进行处理。可用的标志如下:
-
QtCore.QEventLoop.AllEvents: 将处理所有事件。 -
QtCore.QEventLoop.ExcludeUserInputEvents: 排除在处理过程中的用户输入事件。 -
QtCore.QEventLoop.ExcludeSocketNotifiers: 排除在处理过程中的套接字通知事件。 -
QtCore.QEventLoop.WaitForMoreEvents: 如果没有挂起事件,则处理将等待事件。
event_loop.exit(int): 这将使用参数中指定的返回代码退出事件循环。返回代码为 0 表示成功;其他非零值表示错误。
event_loop.processEvents(QtCore.QEventLoop.ProcessEventsFlags): 这将处理与参数中指定的标志匹配的挂起事件。
event_loop.processEvents(QtCore.QEventLoop.ProcessEventsFlags, int): 这将在指定的最大时间(以毫秒为单位)内处理与标志(第一个参数)匹配的挂起事件。
event_loop.quit(): 这将正常退出事件循环,类似于 event_loop.exit(0) 方法。
event_loop.wakeUp(): 这将唤醒事件循环。
Q 子事件
此类实现了与子对象相关的事件。当子对象被添加或删除时,事件被发送到对象。此类的声明语法如下:
child_event = QtCore.QChildEvent(QtCore.QEvent.Type, object)
此事件可用的类型如下:
-
QtCore.QEvent.ChildAdded: 对象中添加了子对象。 -
QtCore.QEvent.ChildRemoved: 从对象中移除了子对象。 -
QtCore.QEvent.ChildPolished: 子对象被抛光。
QChildEvent 类通过以下函数提高功能:
功能性
这些是与当前事件值的返回、功能变化等相关的函数:
child_event.added(): 如果此事件的类型是 ChildAdded,则返回 True。
child_event.child(): 这返回被添加或删除的 QtCore.QObject 类型的子对象。
child_event.polished(): 如果此事件的类型是 ChildPolished,则返回 True。
child_event.removed(): 如果此事件的类型是 ChildRemoved,则返回 True。
事件处理器
此事件的处理器如下:
def childEvent(self, event):
"""Some code lines for processing..."""
QTimerEvent
此类可以实现定期向对象发送事件的计时器事件。此类的声明语法如下:
timer_event = QtCore.QTimerEvent(int)
计时器的唯一 ID 在事件的参数中指定。QTimerEvent 类通过以下函数提高功能:
功能性
此函数与当前事件的值的返回、功能变化等相关:
timer_event.timerId(): 这返回计时器的唯一 ID。
事件处理器
此事件的处理器如下:
def timerEvent(self, event):
"""Some code lines for processing..."""
QActionEvent
此类提供了当使用 QAction 类实现动作添加、移除或更改时出现的事件。它适用于支持操作的项目,如 QMenu。此类的声明语法如下:
action_event = QtGui.QActionEvent(QtCore.QEvent.Type,
QtWidgets.QAction, QtWidgets.QAction)
第一个参数是事件类型,第二个是动作,第三个是指定的先前动作。此事件的可选类型如下:
-
QtCore.QEvent.ActionChanged: 动作已更改。 -
QtCore.QEvent.ActionAdded: 向对象添加动作。 -
QtCore.QEvent.ActionRemoved: 从对象中移除动作。
QActionEvent 类通过以下函数改进了功能。
功能性
这些是与当前事件值的返回、功能变化等相关联的函数:
action_event.action(): 这返回已添加、更改或移除的动作。
action_event.before(): 如果动作类型是 ActionAdded,则返回之前出现的动作。
事件处理器
此事件的处理器如下:
def actionEvent(self, event):
"""Some code lines for processing..."""
QDropEvent
此类提供了当拖放操作完成时出现的事件。它适用于支持拖动操作的项目,如 QWidget 和 QTextEdit。此类的声明语法如下:
drop_event = QtGui.QDropEvent(QtCore.QPointF, QtCore.Qt.DropActions,
QtCore.QMimeData, QtCore.Qt.MouseButtons,
QtCore.Qt.KeyboardModifiers, QtCore.QEvent.Drop)
构建丢弃事件时使用以下参数:
-
位置(第一个参数)。
-
丢弃操作(第二个参数)。
-
MIME 数据(第三个参数)。
-
按钮状态(第四个参数)。
-
键盘修饰符(第五个参数)。
-
类型(第六个参数)。
QDropEvent 类通过以下函数改进了功能。
set
此函数与设置与丢弃事件相关的参数/属性有关:
drop_event.setDropAction(QtCore.Qt.DropAction): 这将设置参数中指定的动作,该动作将用于此事件。
功能性
这些是与丢弃事件当前值的返回、功能变化等相关联的函数:
drop_event.acceptProposedAction(): 这将设置丢弃操作为此事件的建议操作。
drop_event.dropAction(): 这返回与此事件一起使用的 QtCore.Qt.DropAction 类型的动作。
drop_event.keyboardModifiers(): 这返回与此事件一起使用的 QtCore.Qt.KeyboardModifiers 类型的键盘修饰符。
drop_event.mimeData(): 这返回与此事件一起使用的 QtCore.QMimeData 类型的 MIME 数据。
drop_event.mouseButtons(): 这返回与此事件一起使用的 QtCore.Qt.MouseButtons 类型的鼠标按钮。
drop_event.pos(): 这返回丢弃操作的 QtCore.QPoint 类型的位置。
drop_event.posF(): 这返回丢弃操作的 QtCore.QPointF 类型的位置。
drop_event.possibleActions(): 这返回 QtCore.Qt.DropActions 类型的可能丢弃操作。
drop_event.proposedAction(): 这返回 QtCore.Qt.DropAction 类型的建议动作。
drop_event.source(): 此函数返回用于拖放事件操作的QtCore.QObject类型源,例如小部件。
事件处理程序
此事件的处理程序如下:
def dropEvent(self, event):
"""Some code lines for processing..."""
QDragEnterEvent、QDragMoveEvent和QDragLeaveEvent类型的事件处理程序,这些处理程序提高了QDropEvent的功能,如下所示:
def dragEnterEvent(self, event):
"""Some code lines for processing..."""
def dragMoveEvent(self, event):
"""Some code lines for processing..."""
def dragLeaveEvent(self, event):
"""Some code lines for processing..."""
QEnterEvent
此类处理鼠标光标进入小部件、窗口或其他 GUI 元素/项时的事件。它几乎适用于所有支持鼠标光标进入操作的项。此类声明的语法如下:
enter_event = QtGui.QEnterEvent(QtCore.QPointF,
QtCore.QPointF,QtCore.QPointF)
关于进入事件的构建,使用以下参数:
-
本地位置(第一个参数)。
-
窗口位置(第二个参数)。
-
鼠标光标相对于接收项的屏幕位置(第三个参数)。
QEnterEvent类通过以下函数提高功能。
功能性
这些是与当前进入事件值返回、功能变化等相关的函数:
enter_event.globalPos(): 当进入事件发生时,此函数返回项的QtCore.QPoint类型全局位置。
enter_event.globalX(): 当进入事件发生时,此函数返回鼠标光标在项上的全局 x 轴位置。
enter_event.globalY(): 当进入事件发生时,此函数返回鼠标光标在项上的全局 y 轴位置。
enter_event.localPos(): 当进入事件发生时,此函数返回鼠标光标在项上的QtCore.QPointF类型本地位置。
enter_event.pos(): 当进入事件发生时,此函数返回鼠标光标在全局屏幕坐标下的QtCore.QPoint类型位置。
enter_event.screenPos(): 当进入事件发生时,此函数返回鼠标光标在屏幕上的QtCore.QPointF类型位置。
enter_event.windowPos(): 当进入事件发生时,此函数返回鼠标光标在窗口上的QtCore.QPointF类型位置。
enter_event.x(): 当进入事件发生时,此函数返回鼠标光标在项上的x位置。
enter_event.y(): 当进入事件发生时,此函数返回鼠标光标在项上的y位置,
事件处理程序
此事件的处理程序如下:
def enterEvent(self, event):
"""Some code lines for processing..."""
鼠标光标从项中离开的事件可以如下实现:
def leaveEvent(self, event):
"""Some code lines for processing..."""
QFocusEvent
此类处理项的焦点事件。这些事件出现在键盘输入焦点变化时。它适用于支持键盘焦点操作的QWidget等小部件。此类声明的语法如下:
focus_event = QtGui.QFocusEvent(QtCore.QEvent.Type,
QtCore.Qt.FocusReason)
关于焦点事件的构建,使用事件类型(第一个参数)和焦点原因(第二个参数)。此事件可用的类型如下:
-
QtCore.QEvent.FocusIn: 此项获得键盘焦点。 -
QtCore.QEvent.FocusOut: 此项失去键盘焦点。 -
QtCore.QEvent.FocusAboutToChange: 此项的焦点即将改变。
QFocusEvent类通过以下函数增强了功能。
功能
这些是与当前焦点事件当前值相关的函数:
focus_event.gotFocus(): 如果此事件具有FocusIn类型,则返回True。
focus_event.lostFocus(): 如果此事件具有FocusOut类型,则返回True。
focus_event.reason(): 返回此焦点事件的QtCore.Qt.FocusReason类型的理由。
事件处理器
此事件的处理程序如下:
def focusInEvent(self, event):
"""Some code lines for processing..."""
def focusOutEvent(self, event):
"""Some code lines for processing..."""
QKeyEvent
此类处理与键盘活动相关的事件。当您使用QWidget等小部件按下键盘键时,它变得可用。此类的声明语法如下:
key_event = QtGui.QKeyEvent(QtCore.QEvent.Type, int,
QtCore.Qt.KeyboardModifiers)
关于按键事件的构建,使用类型(第一个参数)、键(第二个参数)和键盘修饰符(第三个参数)。此事件可用的类型如下:
-
QtCore.QEvent.KeyPress: 按下键。 -
QtCore.QEvent.KeyRelease: 释放键。 -
QtCore.QEvent.ShortcutOverride: 子窗口中的按键。
QKeyEvent类通过以下函数增强了功能。
是
此函数返回与按键事件状态相关的布尔值(bool):
key_event.isAutoRepeat(): 如果按键事件来自自动重复键,则返回True。
功能
这些是与当前按键事件当前值相关的函数:
key_event.count(): 返回此事件可用的键的数量。
key_event.key(): 返回键的代码,对应于QtCore.Qt.Key。
key_event.matches(QtGui.QKeySequence.StandardKey): 如果按键事件与参数中指定的标准键匹配,则返回True。
key_event.modifiers(): 返回此按键事件的QtCore.Qt.KeyboardModifiers类型的键盘修饰符。
key_event.nativeModifiers(): 返回此按键事件的本地修饰符。
key_event.nativeScanCode(): 返回此按键事件的扫描码。
key_event.nativeVirtualKey(): 返回此按键事件的虚拟键。
key_event.text(): 返回由此键生成的文本。
事件处理器
此事件的处理程序如下:
def keyPressEvent(self, event):
"""Some code lines for processing..."""
def keyReleaseEvent((self, event):
"""Some code lines for processing..."""
QMouseEvent
此类处理与鼠标活动同时出现的事件。它几乎与所有可以与鼠标交互的图形项都可用。此类的声明语法如下:
mouse_event = QtGui.QMouseEvent(QtCore.QEvent.Type,
QtCore.QPointF, QtCore.QPointF,
QtCore.QPointF, QtCore.Qt.MouseButton,
QtCore.Qt.MouseButtons,
QtCore.Qt.KeyboardModifiers)
关于鼠标事件构建,使用以下参数:
-
类型(第一个参数)。
-
光标局部位置(第二个参数)。
-
光标窗口位置(第三个参数)。
-
光标屏幕位置(第四个参数)。
-
导致事件的按钮(第五个参数)。
-
描述鼠标/键盘状态的按钮(第六个参数)。
此事件可用的类型如下:
-
QtCore.QEvent.MouseButtonPress: 点击鼠标按钮。 -
QtCore.QEvent.MouseButtonRelease: 释放鼠标按钮。 -
QtCore.QEvent.MouseMove: 将鼠标移动到项目上。 -
QtCore.QEvent.MouseButtonDblClick: 双击鼠标按钮。
通过以下函数,QMouseEvent 类通过以下方式提高功能。
设置
此函数与设置与鼠标事件相关的参数/属性相关:
mouse_event.setLocalPos(QtCore.QPointF): 此函数设置此鼠标事件的局部位置,位置由参数指定。
功能性
这些是与当前鼠标事件当前值返回相关的函数:
mouse_event.button(): 此函数返回导致此鼠标事件的 QtCore.Qt.MouseButton 类型按钮。
mouse_event.buttons(): 此函数返回与此鼠标事件一起生成的 QtCore.Qt.MouseButtons 类型按钮状态。
mouse_event.flags(): 此函数返回此鼠标事件的 QtCore.Qt.MouseEventFlags 类型标志。
mouse_event.globalPos(): 当事件发生时,此函数返回鼠标光标的 QtCore.QPoint 类型全局位置。
mouse_event.globalX(): 当鼠标事件发生时,此函数返回鼠标光标的全局 x 轴位置。
mouse_event.globalY(): 当鼠标事件发生时,此函数返回鼠标光标的全局 y 轴位置。
mouse_event.localPos(): 当鼠标事件发生时,此函数返回鼠标光标在项目上的 QtCore.QPointF 类型局部位置。
mouse_event.pos(): 当鼠标事件发生时,此函数返回鼠标光标在全局屏幕坐标下的 QtCore.QPoint 类型位置。
mouse_event.screenPos(): 当鼠标事件发生时,此函数返回鼠标光标在屏幕上的 QtCore.QPointF 类型位置。
mouse_event.windowPos(): 当鼠标事件发生时,此函数返回鼠标光标在窗口上的 QtCore.QPointF 类型位置。
mouse_event.source(): 此函数返回与鼠标事件源相关的 QtCore.Qt.MouseEventSource 类型信息。
mouse_event.x(): 当鼠标事件发生时,此函数返回鼠标光标在项目上的 x 位置。
mouse_event.y(): 当鼠标事件发生时,此函数返回鼠标光标在项目上的 y 位置。
事件处理器
此事件的处理器如下:
def mousePressEvent(self, event):
"""Some code lines for processing..."""
def mouseReleaseEvent(self, event):
"""Some code lines for processing..."""
def mouseMoveEvent(self, event):
"""Some code lines for processing..."""
def mouseDoubleClickEvent(self, event):
"""Some code lines for processing..."""
QWheelEvent
此类处理当鼠标滚轮被操作时出现的事件。这些事件是为鼠标滚轮和触摸板滚动手势生成的。此类声明的语法如下:
wheel_event = QtGui.QWheelEvent(QtCore.QPointF, QtCore.QPointF,
QtCore.QPoint, QtCore.QPoint,
int, QtCore.Qt.Orientation,
QtCore.Qt.MouseButtons,
QtCore.Qt.KeyboardModifiers,
QtCore.Qt.ScrollPhase,
QtCore.Qt.MouseEventSource, bool)
关于滚轮事件的构建,以下参数被使用:
-
鼠标光标位置的位置(第一个参数)。
-
全局位置(第二个参数)。
-
像素增量(第三个参数)或屏幕上的滚动距离。
-
角度增量(第四个参数)或滚轮旋转距离。
-
qt4 delta(第五个参数)单向旋转。
-
qt4 方向(第六个参数)单向方向。
-
鼠标状态(第七个参数)。
-
键盘状态(第八个参数)。
-
滚动阶段(第九个参数)。
-
鼠标滚轮或手势的来源(第十个参数)。
-
反转(第十一个参数)选项。
QWheelEvent 类通过以下函数提高功能。
功能性
这些是与当前滚轮事件值返回相关的函数:
wheel_event.angleDelta(): 这返回滚轮旋转的 QtCore.QPoint 类型的距离。
wheel_event.buttons(): 这返回由此滚轮事件生成的 QtCore.Qt.MouseButtons 类型的按钮状态。
wheel_event.globalPos(): 这返回与该滚轮事件相关的指针的 QtCore.QPoint 类型的全球位置。
wheel_event.globalPosF(): 这返回与该滚轮事件相关的指针的 QtCore.QPointF 类型的全球位置。
wheel_event.globalX(): 这返回与该滚轮事件相关的指针的全球 x 轴位置。
wheel_event.globalY(): 这返回与该滚轮事件相关的指针的全球 y 轴位置。
wheel_event.inverted(): 如果此事件的增量值被反转,则返回 True。
wheel_event.orientation(): 这返回此滚轮的 QtCore.Qt.Orientation 类型的方向。
wheel_event.phase(): 这返回此事件的滚动阶段。
wheel_event.pixelDelta(): 这返回 QtCore.QPoint 类型的像素增量,作为屏幕上的滚动距离。
wheel_event.pos(): 这返回与项目相关的指针的 QtCore.QPoint 类型的位置。
wheel_event.posF(): 这返回与项目相关的指针的 QtCore.QPointF 类型的位置。
wheel_event.source(): 这返回与滚轮事件源相关的 QtCore.Qt.MouseEventSource 类型的信息。
wheel_event.x(): 这返回事件发生时与项目相关的指针的 x 位置。
wheel_event.y(): 这返回事件发生时与项目相关的指针的 y 位置。
事件处理器
此事件的处理器如下:
def wheelEvent(self, event):
"""Some code lines for processing..."""
QMoveEvent
此类处理与项目移动活动相关的事件。它几乎适用于所有可以实现移动的图形项目。此类的声明语法如下:
move_event = QtGui.QMoveEvent(QtCore.QPoint, QtCore.QPoint)
关于移动事件的构建,使用新位置(第一个参数)和旧位置(第二个参数)。QMoveEvent 类通过以下函数提高功能。
功能性
这些是与当前移动事件值返回相关的函数:
move_event.oldPos(): 这返回移动项目的 QtCore.QPoint 类型的旧位置。
move_event.pos(): 这返回移动项目的 QtCore.QPoint 类型的新位置。
事件处理器
此事件的处理器如下:
def moveEvent(self, event):
"""Some code lines for processing..."""
QPaintEvent
此类处理与绘制相关的、与项目相关的事件。它几乎适用于所有可以进行绘制的图形项目。正如我们在前面的章节中描述的,Qt 库的所有图形元素都可以进行绘制,因此可以使用 paintEvent() 事件处理器来更新项目图形表示。此类的声明语法如下:
paint_event = QtGui.QPaintEvent(QtCore.QRect)
# or
paint_event = QtGui.QPaintEvent(QtGui.QRegion)
关于画布事件的构建,使用参数中指定的矩形或区域进行绘制。QPaintEvent 类通过以下函数提高功能。
functional
这些是与画布事件当前值相关的函数:
paint_event.rect(): 这返回用于更新的 QtCore.QRect 类型的矩形。
paint_event.region(): 这返回用于更新的 QtGui.QRegion 类型的矩形。
事件处理器
此事件的处理器如下:
def paintEvent(self, event):
"""Some code lines for processing..."""
QResizeEvent
此类处理调整项目大小时出现的事件。它几乎适用于所有可以调整项目大小的图形项目。此类的声明语法如下:
resize_event = QtGui.QResizeEvent(QtCore.QSize, QtCore.QSize)
关于调整大小事件的构建,使用新大小(第一个参数)和旧大小(第二个参数)。QResizeEvent 类通过以下函数提高功能。
functional
这些是与调整大小事件当前值相关的函数:
resize_event.oldSize(): 这返回正在调整大小的项目的 QtCore.QSize 类型的旧大小。
resize_event.size(): 这返回正在调整大小的项目的 QtCore.QSize 类型的新大小。
事件处理器
此事件的处理器如下:
def resizeEvent(self, event):
"""Some code lines for processing..."""
QTabletEvent
此类处理与平板设备功能相关的事件。此类的声明语法如下:
tablet_event = QtGui.QTabletEvent(QtCore.QEvent.Type,
QtCore.QPointF,
QtCore.QPointF, int,
int, float, int, int,
float, float, int,
QtCore.Qt.KeyboardModifiers,
int, QtCore.Qt.MouseButton,
QtCore.Qt.MouseButtons)
关于平板事件的构建,使用以下参数:
-
类型(第一个参数)。
-
事件发生的位置(第二个参数)。
-
绝对坐标系中的全局位置(第三个参数)。
-
设备(第四个参数)。
-
指针类型(第五个参数)。
-
对设备施加的压力(第六个参数)。
-
此设备的x倾斜度(第七个参数)。
-
此设备的y倾斜度(第八个参数)。
-
空气刷的切向压力(第九个参数)。
-
此设备的旋转(第十个参数)。
-
设备的z(第十一个参数)坐标。
-
键盘状态(第十二个参数)。
-
唯一标识符(第十三个参数)。
-
引起事件的按钮(第十四个参数)。
-
事件发生时的按钮状态(第十五个参数)。
QTabletEvent 类通过以下函数增强了功能:
函数式
这些是与当前平板事件返回值相关的函数:
tablet_event.button(): 此函数返回导致此平板事件的 QtCore.Qt.MouseButton 类型的按钮。
tablet_event.buttons(): 此函数返回与该平板事件一起生成的 QtCore.Qt.MouseButtons 类型的按钮状态。
tablet_event.device(): 此函数返回生成此平板事件的设备的类型,作为 QtGui.QTabletEvent.TabletDevice。
tablet_event.globalPos(): 此函数返回当事件发生时设备的 QtCore.QPoint 类型的全局位置。
tablet_event.globalPosF(): 此函数返回当事件发生时设备的 QtCore.QPointF 类型的全局位置。
tablet_event.globalX(): 此函数返回当平板事件发生时设备的全局 x 轴位置。
tablet_event.globalY(): 此函数返回当平板事件发生时设备的全局 y 轴位置。
tablet_event.hiResGlobalX(): 此函数返回该设备的高精度 x 位置。
tablet_event.hiResGlobalY(): 此函数返回该设备的高精度 y 位置。
tablet_event.pointerType(): 此函数返回生成此事件的指针类型,作为 QtGui.QTabletEvent.PointerType。
tablet_event.pos(): 此函数返回与项目相关的设备的 QtCore.QPoint 类型的位置。
tablet_event.posF(): 此函数返回与项目相关的设备的 QtCore.QPointF 类型的位置。
tablet_event.pressure(): 此函数返回设备的压力,范围从 0.0(笔不在平板上)到 1.0(笔在平板上且施加最大压力)。
tablet_event.rotation(): 此函数返回设备的旋转角度,其中 0 表示笔尖指向平板顶部,正值表示向右旋转,负值表示向左旋转。
tablet_event.tangentialPressure(): 此函数返回由气刷工具上的手指滚轮提供的该设备的切向压力,范围在 -1.0 到 1.0 之间。
tablet_event.uniqueId(): 此函数返回此平板设备的唯一 ID。
tablet_event.xTilt(): 此函数返回设备与垂直线之间的 x 轴角度。
tablet_event.yTilt(): 此函数返回设备与垂直线之间的 y 轴角度。
tablet_event.x(): 此函数返回当事件发生时与项目相关的设备的 x 位置。
tablet_event.y(): 此函数返回当事件发生时与项目相关的设备的 y 位置。
tablet_event.z(): 此函数返回设备沿 z 轴的 z 位置;例如,4D 鼠标的滚轮所表示。
事件处理器
此事件的处理器如下:
def tabletEvent(self, event):
"""Some code lines for processing..."""
QTouchEvent
此类处理我们在支持触摸操作设备的触摸点上移动一个或多个触摸点时出现的事件。这些设备必须具有触摸屏或轨迹板。为了使此功能可用,控件或图形项需要将acceptTouchEvents属性设置为True。此类的声明语法如下:
touch_event = QtGui.QTouchEvent(QtCore.QEvent.Type,
QtGui.QTouchDevice,
QtCore.Qt.KeyboardModifiers,
QtCore.Qt.TouchPointStates,
[QtGui.QTouchEvent.TouchPoint])
关于触摸事件的构建,使用了以下参数:
-
类型(第一个参数)。
-
设备(第二个参数)。
-
键盘修饰符(第三个参数)。
-
触点状态(第四个参数)。
-
触点(第五个参数)。
QTouchEvent类通过以下函数提高了功能。
设置
这些是与设置与触摸事件相关的参数/属性相关的函数:
touch_event.setDevice(QtGui.QTouchDevice): 这设置参数中指定的设备,该设备将被使用。
touch_event.setTarget(QtCore.QObject): 这为此事件设置参数中指定的目标(如控件)。
touch_event.setTouchPoints([QtGui.QTouchEvent.TouchPoint]): 这为此事件设置参数中指定的触摸点。
touch_event.setTouchPointStates(QtCore.Qt.TouchPointStates): 这为此事件设置参数中指定的触摸点状态。
touch_event.setWindow(QtGui.QWindow): 这为此触摸事件设置参数中指定的窗口。
功能性
这些是与当前触摸事件当前值返回相关的函数:
touch_event.device(): 这返回从发生触摸事件的QtGui.QTouchDevice类型的设备。
touch_event.target(): 这返回事件发生的QtCore.QObject类型的目标对象。
touch_event.touchPoints(): 这返回此触摸事件的触摸点列表。
touch_event.touchPointStates(): 这返回此touch事件的QtCore.Qt.TouchPointStates类型的触摸点状态。
touch_event.window(): 这返回发生触摸事件的QtGui.QWindow类型的窗口。
事件处理程序
此事件的处理程序如下:
def touchEvent(self, event):
"""Some code lines for processing..."""
其他符号
Qt 库有未在此描述但我们将简要提及的事件。其中一些实现特殊或普通事件的类如下:
QtCore.QDynamicPropertyChangeEvent:用于动态属性更改事件。
QtGui.QCloseEvent:用于处理通过closeEvent()事件处理程序关闭的事件。
QtGui.QHideEvent:用于与隐藏控件相关的事件。
QtGui.QShowEvent:用于控件的显示事件。
QtGui.QContextMenuEvent:用于上下文菜单事件。
QtGui.QExposeEvent:用于处理通过exposeEvent()事件处理程序暴露的事件。
QtGui.QFileOpenEvent:用于与打开文件操作相关的事件。
QtGui.QHelpEvent:用于与控件中点的有用信息相关的事件。
QtGui.QHoverEvent:用于与QGraphicsItem相关联的鼠标事件。
QtGui.QIconDragEvent:用于主图标的拖动事件。
QtGui.QInputEvent:用于用户的输入事件。
QtGui.QInputMethodEvent:用于输入方法事件。
QtGui.QNativeGestureEvent:用于手势事件。
QtGui.QScrollEvent:用于滚动事件。
QtGui.QScrollPrepareEvent:用于滚动准备事件。
QtGui.QShortcutEvent:用于键组合事件。
QtGui.QStatusTipEvent:用于状态栏事件。
QtGui.QWhatsThisClickedEvent:用于处理“这是什么?”文本中的超链接。
QtGui.QWindowStateChangeEvent:用于窗口状态更改事件。
QtWidgets模块的类,如QGestureEvent和QGraphicsSceneEvent,也可以使用。
发送事件
在应用程序开发中,有时可能需要发送事件。这可以帮助我们创建更灵活的功能。为此,可以使用QtCore模块的QCoreApplication类的静态方法。静态方法可以按以下方式实现:
QtCore.QCoreApplication.sendEvent(object, event):这是sendEvent()方法立即将事件发送到对象的地方。object是一个QtCore.QObject,例如小部件、按钮或其他项目,而event是一个QtCore.QEvent,例如进入事件或鼠标事件。
QtCore.QCoreApplication.postEvent(object, event):这是postEvent()方法将事件添加到队列的地方。object是一个QtCore.QObject,例如小部件、按钮或其他项目,而event是一个QtCore.QEvent,例如进入事件或鼠标事件。此方法可以与应用程序中的线程一起使用。
事件示例
为了演示事件和事件处理器,让我们使我们的应用程序现代化。通常,在应用程序中,使用可用于项目的可用事件处理器。它们处理一些事件并提供额外的功能。在这里,我们将介绍向应用程序的小部件添加事件处理器的最佳方式。为此,我们需要添加/更改u_style.py文件中UWid类的某些行。让我们开始吧:
- 首先,通过添加额外的参数来改进功能,更改
UWid类的__init__()函数:
...
class UWid(QtWidgets.QWidget):
def __init__(self, parent=None, bg=color[1],
bgh=color[3], minw=0, minh=0,
maxw=None, maxh=None, fixw=None,
fixh=None, mrg=0, pad=0, bds="solid",
bdr=3, bdw=0, bdc=color[3]):
...
...
这将用于根据小部件在应用程序中的表示更改小部件的参数,类似于UBut1类。
- 现在,我们需要将行添加到
UWid类的__init__()函数中,如下所示:
...
def __init__(...):
...
self.setMinimumWidth(minw)
self.setMinimumHeight(minh)
if maxw is not None:
self.setMaximumWidth(maxw)
if maxh is not None:
self.setMaximumHeight(maxh)
if fixw is not None:
self.setFixedWidth(fixw)
if fixh is not None:
self.setFixedHeight(fixh)
self.bg, self.bgh, self.mrg, self.pad = bg, bgh, mrg, pad
self.bds, self.bdr, self.bdw, self.bdc = bds, bdr, bdw, bdc
self.setStyleSheet(self.wid_style(self.mrg, self.pad,
self.bg, self.bds,
self.bdr, self.bdw,
self.bgh))
...
这里可以选择设置固定宽度/高度、最小/最大宽度/高度、背景颜色等。
- 现在,我们需要将
wid_style()样式函数添加到UWid类中,该函数将根据发生的事件重新样式化此小部件:
...
def __init__(...):
...
def wid_style(self, mrg=None, pad=None, bg=None, bds=None,
bdr=None, bdw=None, bdc=None):
style = """margin: %spx; padding: %spx;
background-color: %s; border-style: %s;
border-radius: %spx; border-width: %spx;
border-color: %s;""" % (mrg, pad, bg, bds, bdr,
bdw, bdc)
return style
...
这是一个可选功能,用于减少各种事件行数。现在,我们需要添加将用于处理此小部件事件的事件处理器。
- 将
enterEvent()事件处理器添加到UWid类中,以处理与鼠标光标进入此小部件相关的事件:
...
...
def enterEvent(self, event):
self.setStyleSheet(self.wid_style(self.mrg, self.pad,
self.bgh, self.bds, self.bdr,
self.bdw, self.bdc))
...
- 然后,将
leaveEvent()事件处理器添加到UWid类中,以处理与鼠标光标离开此小部件相关的事件:
...
...
def leaveEvent(self, event):
self.setStyleSheet(self.wid_style(self.mrg, self.pad,
self.bg, self.bds, self.bdr,
self.bdw, self.bdc))
...
现在,如果我们运行u_app.py文件,我们将看到结果。我们也可以通过实验添加其他事件处理器。
摘要
本章考虑了信号功能的主要原则和在 GUI 应用程序中可以处理的一些常用事件。理解这些基础知识非常重要,因为这代表了任何现代应用程序的核心功能。许多 GUI 没有这些机制就变得不太有用。本章提供的最后一个示例演示了根据发生的事件对小部件进行样式化。通过这种方式,所有实现过的样式化元素都可以扩展。本章是 Qt 库的信号和事件的一个介绍。官方文档可以巩固你在这一领域的知识。
在下一章中,我们将介绍任何应用程序的另一个重要方面——线程和进程的实现。
第十六章:线程和进程池
正如我们在整本书中看到的那样,如果我们继续向我们的 GUI 应用程序添加新功能,我们将会遇到一些问题,例如应用程序冻结、操作速度下降、同时执行的问题以及许多其他不舒适的情况。这些问题在任何多功能应用程序中都会出现。根据我们自己的经验,当我们使用微软办公软件、设计工具或其他占用大量内存资源的软件时,我们会遇到各种等待、冻结等情况。如果我们向正在创建的应用程序的功能中添加内容,在某个阶段,应用程序将变得缓慢(在最好的情况下),并且可能不会像我们希望的那样功能齐全。为什么会这样呢?在大多数情况下,几乎每个操作系统都详细说明了执行进程和线程。我们可以打开我们操作系统的任务管理器,看到各种程序作为进程(任务)运行。它们有进程 ID(PID)、名称等等。这些应用程序(进程)使用一些内部任务,并且通常有执行额外操作的线程。它们也可以使用外部任务,即独立进程。这些进程可以包含多个线程,它们可以并发执行任务。当我们的应用程序在一个进程中以一个线程运行,并且有很多任务时,可用的内存资源可能不足以运行它们。解决这个问题的方法是将任务分割成不同的线程,如果需要的话,还可以分割成不同的进程。本章将介绍 GUI 创建的这些方面。我们将探索 Qt 库工具,例如QProcess和QThread。我们还将演示可以轻松实现于 GUI 中的 Python 标准库工具。我们还将检查这些工具的优点和缺点。
在本章中,我们将涵盖以下主题:
-
进程
-
线程
-
锁
-
Python 标准库工具
进程
在计算中,进程是任何环境的主要部分。从广义上讲,进程是程序的实例,它执行应用程序。它可以有多个进程来执行操作任务,通常包括多个线程。如果只使用单个 CPU,则任何时刻只能执行一个进程。然而,如果 CPU 有多个核心,任务的执行可以在这些核心之间分配。但这并不意味着多核架构会并发执行所有操作进程/任务。实际上,系统是多任务的,这意味着当新任务开始时,它们可以中断已经启动的任务,可以被新任务中断,并且可以再次启动。这样,进程的执行被分割成并发操作的段。一个常见的情况是主程序有一个父进程,子进程并行执行。进程之间的通信通常是通过使用输入通道(数据流)STDIN(标准输入)和两个预定义的输出通道(分离的数据流)——STDOUT(标准输出)和STDERR(标准错误)来进行的。进程的通道也被称为读(STDOUT和STDERR)和写(STDIN)通道。Qt 库运行新进程并在应用程序中实现进程间通信(IPC)的一种方式是通过使用QProcess类。这个类允许我们管理应用程序的外部进程。QProcess是一个跨平台类,它在 Qt 库的QtCore模块中可用。在应用程序中,它可以用来启动外部程序作为子进程,并根据操作任务与它们通信。这种机制是一个 API,用于控制和监控子进程的状态。QProcess类还通过继承QtCore.QIODevice类提供了对子进程的 I/O(输入/输出)通道的访问。这些操作的简单示例是运行实现附加功能(如打开网页或运行服务器)的第三方应用程序。它也可以用于长期任务,包括循环和估计。然而,QProcess类不支持某些平台,例如 iOS。因此,应用程序可以使用 Python 标准库工具,如subprocess模块和multiprocessing包。
应用程序流程
要理解在创建和运行 GUI 或非 GUI 应用程序时发生的应用程序进程,我们需要了解 Qt 模块以及参与应用程序进程的类的继承方案。QtCore 模块中的 QCoreApplication 类继承自 QObject 类,并为非 GUI 应用程序创建事件循环。QtGui 模块中的 QGuiApplication 类继承自 QCoreApplication,并使用 GUI 应用程序的主要设置管理控制流。QtWidgets 模块中的 QApplication 类继承自 QGuiApplication,并基于附加功能,使用 GUI 应用程序相对于 QWidget 类的主要设置管理控制流。要访问应用程序对象,您可以使用全局指针:
-
QtCore.QCoreApplication.instance():用于QCoreApplication、QGuiApplication和QApplication。 -
QtGui.QGuiApplication.qGuiApp:用于QGuiApplication。 -
QtWidgets.QApplication.qApp:用于QApplication。
在应用程序中,可以使用 QCoreApplication 类的 processEvents() 静态方法与长期任务(循环)一起使用。长期操作通常如下所示:
...
def long_task():
while True:
QtWidgets.qApp.processEvents(QtCore.QEventLoop.AllEvents)
print("HELLO")
...
...
此 while 指令是无限循环的,并将打印字符串,直到通过按 Ctrl + Z 停止。
QProcess
此类提供了在应用程序中处理进程时可以使用的 Qt 库工具。使用此类在单独的进程中启动外部任务(程序),并组织与它们的通信。此类的声明语法如下:
process = QtCore.QProcess()
QProcess 继承自 QIODevice,它是 Qt 库中所有 I/O 设备的基接口类,并通过以下功能增强了功能。
set
这些函数设置进程的参数/属性:
process.setArguments([str]):此操作为在进程启动时调用的程序设置指定的参数。
process.setEnvironment(["environment"]):此操作为该进程设置指定的环境,该环境将与该进程一起使用。
process.setInputChannelMode(QtCore.QProcess.InputChannelMode):此操作为该进程的 STDIN 设置指定的参数中的通道模式。可用的输入通道模式如下:
-
QtCore.QProcess.ManagedInputChannel—0:此进程管理运行进程的输入。 -
QtCore.QProcess.ForwardedInputChannel—1:此进程将主进程的输入转发到运行进程。
process.setProcessChannelMode(QtCore.QProcess.ProcessChannelMode):此操作为该进程的 STDOUT(标准输出)设置指定的参数中的通道模式。可用的进程通道模式如下:
-
QtCore.QProcess.SeparateChannels—0:STDOUT和STDERR数据在单独的内部缓冲区中。 -
QtCore.QProcess.MergedChannels—1:此操作将进程的输出合并到STDOUT(标准输出)通道。 -
QtCore.QProcess.ForwardedChannels—2: 这将进程的输出转发到主进程。 -
QtCore.QProcess.ForwardedErrorChannel—4: 这将STDERR(标准错误)转发到主进程。
process.setProcessEnvironment(QtCore.QProcessEnvironment): 这将设置由参数指定的环境,该环境将用于此进程。
process.setProcessState(QtCore.QProcess.ProcessState): 这将此进程的状态设置为参数中指定的状态。可用状态如下:
-
QtCore.QProcess.NotRunning—0: 此进程未运行。 -
QtCore.QProcess.Starting—1: 此进程正在启动,但该进程所操作的程序尚未被调用。 -
QtCore.QProcess.Running—2: 此进程正在运行且准备就绪。 -
process.setProgram("program"): 这将设置由参数指定的程序,该程序将在此进程中启动。 -
process.setReadChannel(QtCore.QProcess.ProcessChannel): 这将为此进程设置参数中指定的通道。可用的进程通道如下:-
QtCore.QProcess.StandardOutput—0: 进程的STDOUT(标准输出)。 -
QtCore.QProcess.StandardError—1: 进程的STDERR(标准错误)。
-
process.setStandardErrorFile("path/to/the/filename", QtCore.QIODevice.OpenMode): 这将 STDERR(标准错误)重定向到文件(第一个参数),相对于文件模式(第二个参数)。
process.setStandardInputFile("path/to/the/filename"): 这将 STDIN(标准输入)重定向到参数指定的文件。
process.setStandardOutputFile("path/to/the/filename", QtCore.QIODevice.OpenMode): 这将 STDOUT(标准输出)重定向到文件(第一个参数),相对于文件模式(第二个参数)。
process.setStandardOutputProcess(QtCore.QProcess): 这将此进程的 STDOUT(标准输出)流管道连接到参数指定的进程的 STDIN(标准输入)。
process.setWorkingDirectory("path/to/dir"): 这将设置由参数指定的工作目录,在此进程中启动此进程。
is
此函数返回与进程状态相关的布尔值 (bool):
process.isSequential(): 如果此进程是顺序的,则返回 True。
functional
这些函数与进程的当前值、功能变化等相关:
process.arguments(): 这返回最近启动的进程的命令行参数列表。
process.atEnd(): 如果此进程未运行且没有更多数据可读,则返回 True。
process.bytesAvailable(): 这返回可用于读取的此进程的字节数。
process.bytesToWrite(): 这返回可用于写入的此进程的字节数。
process.canReadLine(): 如果可以通过此进程读取完整的数据行,则返回 True。
process.close(): 这将终止此进程并关闭所有通信。
process.closeReadChannel(QtCore.QProcess.ProcessChannel): 这关闭指定的读取通道。
process.closeWriteChannel(): 这在所有数据都已写入后关闭通道。
process.environment(): 这返回此进程的环境。
process.error(): 这返回最后一个发生的错误,类型为 QtCore.QProcess.ProcessError。可用的进程错误如下:
-
QtCore.QProcess.FailedToStart—0: 此进程启动失败。 -
QtCore.QProcess.Crashed—1: 此进程崩溃。 -
QtCore.QProcess.Timedout—2: 此进程超时。 -
QtCore.QProcess.ReadError—3: 从此进程读取时出现错误。 -
QtCore.QProcess.WriteError—4: 向此进程写入时出现错误。 -
QtCore.QProcess.UnknownError—5: 此进程中出现未知错误。
process.execute("command"): 这将在新进程中启动由参数指定的命令。
process.execute("program", "arguments"): 这将在新进程中以参数(第二个参数)启动程序(第一个参数)。
process.exitCode(): 这返回最后一个进程退出代码。
process.exitStatus(): 这返回最后一个进程退出状态,类型为 QtCore.QProcess.ExitStatus。可用的退出状态如下:
-
QtCore.QProcess.NormalExit—0: 此进程正常退出。 -
QtCore.QProcess.CrashExit—1: 此进程崩溃。
process.inputChannelMode(): 这返回此进程 STDIN (标准输入) 通道的 QtCore.QProcess.InputChannelMode 类型的通道模式。
process.kill(): 这将立即终止此进程并退出。
process.nullDevice(): 这是操作系统中的空设备,用于丢弃进程的输出流或空文件用于输入流。
process.open(QtCore.QIODevice.OpenMode): 这以参数指定的模式打开进程。
process.processChannelMode(): 这返回此进程标准输出和标准错误通道的 QtCore.QProcess.ProcessChannelMode 类型的通道模式。
process.processEnvironment(): 这返回此进程的 QtCore.QProcessEnvironment 类型的环境。
process.processId(): 这返回运行进程的本地 ID。
process.program(): 这返回与此进程一起启动的最后一个程序。
process.readAllStandardError(): 这将从此进程的 STDERR 返回 QtCore.QByteArray 类型的所有错误数据。
process.readAllStandardOutput(): 这将从此进程的 STDOUT 返回 QtCore.QByteArray 类型的所有数据。
process.readChannel(): 这返回此进程的 QtCore.QProcess.ProcessChannel 类型的读取通道。
process.readData(int): 这将读取限制在参数指定的最大大小的字节到数据中。
process.start(QtCore.QIODevice.OpenMode): 这将在新进程中以参数中指定的模式启动程序。
process.start("command", QtCore.QIODevice.OpenMode): 这将在新进程中以模式(第二个参数)启动命令(第一个参数)。
process.start("program", ["arguments"], QtCore.QIODevice.OpenMode): 这将在新进程中以相对于模式(第三个参数)的参数(第二个参数)启动程序(第一个参数)。
process.startDetached(): 这将在新进程中启动程序,然后从该进程中分离出来。
process.startDetached(int): 这将在新进程中以参数中指定的进程 ID 启动程序,然后从该进程中分离出来。
process.startDetached("command"): 这将在新进程中启动参数中指定的命令,然后从该进程中分离出来。
process.startDetached("program", ["arguments"]): 这将在新进程中以参数(第二个参数)启动程序(第一个参数),然后从该进程中分离出来。
process.startDetached("program", ["arguments"], "path/to/dir"): 这将在新进程中以参数(第二个参数)和工作目录(第三个参数)启动程序(第一个参数),然后从该进程中分离出来。
process.state(): 这返回此进程的 QtCore.QProcess.ProcessState 类型的当前状态。
process.systemEnvironment(): 这返回此进程的系统环境。
process.terminate(): 这将终止进程。
process.waitForBytesWritten(int): 这将等待参数中指定的毫秒数,直到已将缓冲写入的字节数据写入。
process.waitForFinished(int): 这将等待参数中指定的毫秒数,直到此进程完成,阻塞进程。
process.waitForReadyRead(int): 这将等待参数中指定的毫秒数,直到有新数据可供读取,阻塞进程。
process.waitForStarted(int): 这将等待参数中指定的毫秒数,直到此进程开始,阻塞进程。
process.workingDirectory(): 这返回用于此进程的工作目录。
信号
以下是与 QProcess 类一起可用的信号:
process.errorOccurred(QtCore.QProcess.ProcessError): 当此进程发生错误时,会发出此信号,并将错误作为参数传递。
process.finished(int, QtCore.QProcess.ExitStatus): 当此进程完成时,会发出此信号,并将退出代码和退出状态作为参数传递。
process.readyReadStandardError(): 当此进程在 STDERR 通道上提供新数据时,会发出此信号。
process.readyReadStandardOutput(): 当此进程在 STDOUT 通道上提供新数据时,会发出此信号。
process.started(): 当此进程开始时,会发出此信号。
process.stateChanged(QtCore.QProcess.ProcessState): 当此进程的状态改变时,会发出此信号,并将新的进程状态作为参数传递。
QProcessEnvironment
此类创建在启动使用进程的应用程序中的程序时可以使用的环境变量。进程的环境变量表示为键/值对的集合,例如 ["PATH=/Path/To/dir", "USER=user"]。此类的声明语法如下:
process_env = QtCore.QProcessEnvironment()
QProcessEnvironment 类通过以下函数增强了功能。
是
此函数返回一个与进程环境状态相关的布尔值 (bool):
process_env.isEmpty(): 这将返回 True,如果这个进程环境为空且没有任何环境变量。
功能性
这些函数与进程环境的当前值、功能变化等相关:
process_env.clear(): 这将清除此进程环境中的所有键/值对。
process_env.contains(str): 如果在参数指定的名称在此进程环境中找到变量,则返回 True。
process_env.insert(QtCore.QProcessEnvironment): 这将参数指定的进程环境的内容插入到此进程环境中。
process_env.insert(str, str): 这将在此进程环境中插入环境变量的键(第一个参数)和值(第二个参数)。
process_env.keys(): 这将返回一个包含此进程环境所有环境变量键的列表。
process_env.remove(str): 这将删除包含参数指定的名称(键)的环境变量。
process_env.swap(QtCore.QProcessEnvironment): 这将与此参数指定的进程环境交换此进程环境。
process_env.systemEnvironment(): 这将返回进程的 **QtCore.QProcessEnvironment** 类型的系统环境。
process_env.toStringList(): 这将此进程环境转换为键/值对的字符串列表。
process_env.value(str, str): 这将返回第一个参数指定的名称(键)的值,或者如果此进程环境中不存在具有该名称的变量,则返回默认值(第二个参数)。
进程示例
让我们通过向我们的应用程序添加一些内容来查看使用 QProcess 类的示例。我们将使用本书中之前使用的 QML 脚本来可视化标签控件的应用程序部分中的按钮,并通过单击其中的一些按钮来运行这些应用程序。请注意,使用 QProcess 类创建的进程可能无法与某些操作系统一起工作,因此 subprocess 模块构造仍然是注释的。因此,为了做到这一点,我们需要将我们用于 QML 实现的目录(如 qmls/ 和 jscripts/)复制到我们的工作目录中。我们还需要复制 u_qml.qml 文件。现在,我们需要在 App/App_PySide2/ 和 App/App_PyQt5/ 目录中创建新的 apps.qml 文件,其中将包含应用程序中按钮的 QML 脚本。apps.qml 文件如下所示,可以复制并从我们之前创建的 qmls/UGrid.qml 文件中进行修改:
- 将 QML 导入部分、一个基本的
Rectangle以及其属性和按钮的网格布局添加到apps.qml文件中:
import QtQuick 2.7
import QtQuick.Layouts 1.3
import "qmls" as Uqmls
Rectangle {
visible: true
color: Qt.rgba(0, 0.07, 0.14, 1);
GridLayout {
id: grid1; anchors.fill: parent; visible: true
function wsize() {
if (width < 590) {return 1;} else {return 2;};
}
columns: wsize();
...
...
...
这是 QML 中所有矩形的父矩形。请注意,在编写本书时,Qt 的版本发生了变化,QtQuick 的版本也发生了变化。因此,在使用 QML 脚本之前,建议您检查可用的版本。
- 添加第一个发光按钮,该按钮将用于运行视频摄像头,并将其添加到网格布局中:
...
...
...
Uqmls.URectGlow {
id: g5; Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 20
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(0.007, 1, 1, 1);
txglow: Qt.rgba(0.007, 0.7, 0.7, 1);
txtext: "Camera"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
signal clicked();
MouseArea {
anchors.fill: parent
onClicked: {
g5.glowcolor == Qt.rgba(0.007, 1, 1, 1) ?
g5.glowcolor = Qt.rgba(0, 0.07, 0.14, 1) :
g5.glowcolor = Qt.rgba(0.007, 1, 1, 1);
g5.txglow == Qt.rgba(0, 0.07, 0.14, 1) ?
g5.txglow = Qt.rgba(0.007, 1, 1, 1) :
g5.txglow = Qt.rgba(0, 0.07, 0.14, 1);
g5.clicked();
}
}
}
...
...
...
这是带有发光效果的第一个矩形,它将在单独的窗口中调用视频摄像头应用程序。
- 将第二个发光按钮添加到网格布局中,该按钮将用于运行 QML 应用程序示例:
...
...
...
Uqmls.URectGlow {
id: g6; Layout.fillWidth: true;
Layout.fillHeight: true
Layout.margins: 20
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(0.95, 0, 0, 1);
txglow: Qt.rgba(0.77, 0, 0, 1);
txtext: "QMLS"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
signal clicked();
MouseArea {
anchors.fill: parent
onClicked: {
g6.glowcolor == Qt.rgba(0.95, 0, 0, 1) ?
g6.glowcolor = Qt.rgba(0, 0.07, 0.14, 1) :
g6.glowcolor = Qt.rgba(0.95, 0, 0, 1);
g6.txglow == Qt.rgba(0, 0.07, 0.14, 1) ?
g6.txglow = Qt.rgba(0.77, 0, 0, 1) :
g6.txglow = Qt.rgba(0, 0.07, 0.14, 1);
g6.clicked();
}
}
}
...
...
...
这是带有发光效果的第二个矩形,它将通过创建的 clicked() 信号调用 QML 应用程序。
- 添加第三个发光按钮,该按钮将用于运行 Jupyter Notebook,并将其添加到网格布局中:
...
...
...
Uqmls.URectGlow {
id: g7; Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 20
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(0,0.95,0.37,1);
txglow: Qt.rgba(0,0.47,0.37,1);
txtext: "JUPYTER"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
signal clicked();
MouseArea {
anchors.fill: parent
onClicked: {
g7.glowcolor == Qt.rgba(0, 0.95, 0.37, 1) ?
g7.glowcolor = Qt.rgba(0, 0.07, 0.14, 1) :
g7.glowcolor = Qt.rgba(0, 0.95, 0.37, 1);
g7.txglow == Qt.rgba(0, 0.07, 0.14, 1) ?
g7.txglow = Qt.rgba(0, 0.47, 0.37, 1) :
g7.txglow = Qt.rgba(0, 0.07, 0.14, 1);
g7.clicked();
}
}
}
...
...
...
带有发光效果的第三个矩形将在使用 QProcess 类创建的分离进程中启动 Jupyter Notebook。
- 最后,添加第四个发光按钮,该按钮将用于运行默认的网页浏览器,并将其添加到网格布局中,从而完成 QML 文件:
...
...
...
Uqmls.URectGlow {
id: g8; Layout.fillWidth: true; Layout.fillHeight: true
Layout.margins: 20
color: Qt.rgba(0, 0.07, 0.14, 1);
glowcolor: Qt.rgba(1, 1, 1, 1);
txglow: "grey";
txtext: "WEB"
txcolor: Qt.rgba(0.2, 0.2, 0.2, 1)
signal clicked();
MouseArea {
anchors.fill: parent
onClicked: {
g8.glowcolor == Qt.rgba(1, 1, 1, 1) ?
g8.glowcolor = Qt.rgba(0, 0.07, 0.14, 1) :
g8.glowcolor = Qt.rgba(1, 1, 1, 1);
g8.txglow == Qt.rgba(0, 0.07, 0.14, 1) ?
g8.txglow = "grey" :
g8.txglow = Qt.rgba(0, 0.07, 0.14, 1);
g8.clicked();
}
}
}
}
}
带有发光效果的第四个矩形将在单独的进程中打开系统的默认网页浏览器。
现在,我们需要在 u_app.py 文件中进行一些更改,以实现 QML 脚本并在运行新进程的应用程序中运行,例如 QML 应用程序和其他第三方程序:
- 首先,将以下行添加到每个文件的导入部分:
- 将以下内容添加到 PySide2 的
u_app.py文件中:
...
from PySide2 import QtQuickWidgets
...
- 将以下内容添加到 PyQt5 的
u_app.py文件中:
...
from PyQt5 import QtQuickWidgets
...
- 然后,根据以下内容修改或添加
UApp类的__init__()函数中的某些行:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.apps = QtQuickWidgets.QQuickWidget(self.twid1)
self.apps.setSource(QtCore.QUrl("apps.qml"))
self.properties = self.apps.rootObject()
...
self.qmlbut1 = self.properties.childItems()[0].childItems()[0]
self.qmlbut1.clicked.connect(self.video_camera)
self.qmlbut2 = self.properties.childItems()[0].childItems()[1]
self.qmlbut2.clicked.connect(self.qml_apps)
self.qmlbut3 = self.properties.childItems()[0].childItems()[2]
self.qmlbut3.clicked.connect(self.jupyter)
self.qmlbut4 = self.properties.childItems()[0].childItems()[3]
self.qmlbut4.clicked.connect(self.web_browse)
...
self.qapp1 = 0
self.qapp2 = 0
self.qapp3 = 0
self.qapp4 = 0
...
...
在 QML 文件中创建的信号将被用于调用与将要运行的新任务相关联的函数。现在,我们需要向 UApp 类添加一些函数,以实现 QML 并使用指定的应用程序运行进程。
- 添加调整大小事件处理程序以调整视图中的 QML 元素大小:
...
...
def resizeEvent(self, event):
self.properties.setWidth(
float(self.tabwid.currentWidget().width()))
self.properties.setHeight(
float(self.tabwid.currentWidget().height()))
...
...
此事件处理程序将在使用鼠标或其他方式调整应用程序窗口大小时,调整包含 QML 元素的窗口的标签大小。
- 添加第一个进程以运行视频摄像头设备:
...
...
def video_camera(self):
self.qapp1 += 1
if self.qapp1 == 1:
# subprocess.Popen(["python", r"u_media.py"])
self.approc1 = QtCore.QProcess()
self.approc1.start("python", ["u_media.py"])
if self.qapp1 == 2:
self.approc1.kill()
self.qapp1 = 0
...
...
这将在新进程中启动摄像头小部件。Qt 库提供的摄像头设备功能可能因版本而异。如果您使用的是需要 root 权限的操作系统,您需要根据这些要求启动此功能。
- 添加第二个进程,该进程将运行我们之前创建的 QML 应用程序:
...
...
def qml_apps(self):
self.qapp2 += 1
if self.qapp2 == 1:
# subprocess.Popen(["python", r"u_qml.py"])
self.approc2 = QtCore.QProcess()
self.approc2.start("python", ["u_qml.py"])
if self.qapp2 == 2:
self.approc2.kill()
self.qapp2 = 0
...
...
这将在新进程中运行 QML 应用程序。我们还需要在 App/App_PySide2/ 和 App/App_PyQt5/ 目录中创建一个 u_qml.py 文件,并添加以下行。
在每个 import 部分添加以下行:
- 将以下行添加到 PySide2 的
u_qml.py文件中:
...
from PySide2 import QtWidgets, QtCore
from PySide2.QtQml import QQmlApplicationEngine
import sys
...
- 将以下行添加到 PyQt5 的
u_qml.py文件中:
...
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtQml import QQmlApplicationEngine
import sys
...
- 最后,将以下用于在应用程序中启动 QML 的行添加到两个文件中:
...
app = QtWidgets.QApplication(sys.argv)
qwid = QQmlApplicationEngine()
qwid.load(QtCore.QUrl('u_qml.qml'))
sys.exit(app.exec_())
...
我们以类似的方式更改此文件,即不使用类。然而,我们在 第二章,QML 概述中创建的 u_qml.py 文件也可以通过额外的修改来使用。
- 为了在指定的浏览器中运行 Jupyter Notebook(可以更改为您喜欢的浏览器;如果没有指定,将使用默认浏览器):
...
...
def jupyter(self):
self.qapp3 += 1
if self.qapp3 == 1:
# subprocess.Popen(["jupyter", ["notebook", "--
# browser=firefox"])
self.approc3 = QtCore.QProcess()
self.approc3.start("jupyter", ["notebook", "--
browser=firefox"])
if self.qapp3 == 2:
self.approc3.kill()
self.qapp3 = 0
...
...
此函数将在新进程中启动 Jupyter Notebook,它将在 Firefox 浏览器中显示。如果我们想在我们的默认浏览器中打开笔记本,可以通过在 start() 函数的浏览器参数中不指定任何浏览器来实现。或者,我们可以通过指定浏览器参数来使用我们喜欢的浏览器。
- 最后,添加第四个进程,该进程将使用 Python 标准库的
webbrowser模块运行默认的网页浏览器,并指定 URL:
...
...
def web_browse(self):
self.qapp4 += 1
if self.qapp4 == 1:
# subprocess.Popen("python", ["-m", "webbrowser", "-n",
# "https://www.python.org"])
self.approc4 = QtCore.QProcess()
self.approc4.start("python", ["-m", "webbrowser", "-n",
"https://www.python.org"])
if self.qapp4 == 2:
self.approc4.kill()
self.qapp4 = 0
...
...
在这里,我们指定了 QProcess 类的 start() 函数中的命令,类似于 Python 标准库中 subprocess 模块的构建。所有这些用于启动进程的函数都模拟了按钮的切换。当按钮被点击时,进程将启动。当不再被点击时,将调用 kill() 函数。这些函数是可选的,可以用来启动另一个程序。
线程
与应用程序和程序的环境相关的执行操作的下一个元素是线程。在本质上,线程与进程非常相似,但也有一些区别。线程以并行的方式做事。从广义上讲,执行线程是操作系统操作调度器可以独立管理的指令序列。在目前大多数可用的应用程序中,线程是进程的一个组成部分。在我们周围的世界里,我们通常遇到的多任务操作系统提供了多线程模型,允许在单个进程的上下文中存在多个线程。那么,我们如何描述线程呢?当你使用你喜欢的操作系统,或者运行你喜欢的编辑器,例如,Anaconda 工具集包含的 Spyder 编辑器时,你想要找到最新的新闻并打开一个网页浏览器。假设你打开你的媒体播放器来听音乐或看视频——这些应用程序通常在你做类似的事情时使用。这是一个几个进程在使用执行的多任务模型并行工作的例子。此外,正如我们所看到的,这些进程中的每一个都有其他在单个进程中并行执行的内部进程。当你使用编辑器的文本字段时,你可以同时运行这个编辑器的另一个选项。这种行为描述了应用程序中线程的意义——单个进程内的并发。
我们如何描述并发执行呢?正如我们在本章的进程部分所描述的,在单核 CPU 上的并行执行只是一个假象。对于进程来说,这就像当另一个进程开始时对进程的打断,然后当另一个进程开始时,另一个进程又被打断。这种情况可以推广到单个进程的程序段执行。当一个进程开始时,它总是执行一个代码段。这被称为进程有一个线程。我们可以将进程的执行分割成两个代码段,这样看起来就像有两个不同的代码序列同时在运行。当我们有一个单核 CPU 时,并发是通过与进程的并行执行类似的方式实现的。如果我们有一个多核 CPU,这些线程可以被分配到多个核心上。这实际上就是并发。
关于使用 Qt(尽管这不仅仅与 Qt 相关)进行 GUI 应用程序开发,我们需要了解两种类型的线程。第一种类型是作为应用程序主线程使用的 GUI 线程。当我们运行应用程序时,通过调用 QtCore.QApplication.exec() 函数启动此线程。所有 GUI 组件,如小部件,以及一些类,如 QPixmap,都必须在此线程中运行。第二种类型是辅助线程,也称为工作线程,用于卸载主线程并运行长期任务。本书中展示的所有提供额外功能(如 pandas)的线程都是工作线程。每个线程都有自己的堆栈(调用历史和局部变量),其大小通常由操作系统定义。线程共享相同的地址空间。如果我们想在应用程序中使用线程,我们需要了解以下内容:
-
实际并发执行可用的线程数等于可用的 CPU 核心数
-
多个线程不能同时访问同一对象
-
所有线程对象只有在其他线程与它们无关且对象没有与其他线程的隐式耦合时才能安全使用
-
我们不能从工作线程中更改 GUI 线程中的某个内容
Qt 库提供了几个用于在应用程序中处理线程的类,例如 QThread 和 QThreadPool。QThread 类的优点是我们可以使用信号机制更改 GUI 组件。Qt 库提供了诸如 可重入 和 线程安全 这样的文档术语,用于标记类和函数,以指示它们如何在多线程应用程序中使用。术语 线程安全 意味着即使调用使用共享数据,此方法也可以从多个线程中调用,因为所有对共享数据的引用都是序列化的。
术语 可重入 意味着此方法可以从多个线程中调用,但前提是每个调用都使用自己的数据。在本节中,我们将介绍 QThread 和 QThreadPool 类。我们还建议学习 QtConcurrent 模块和 WorkerScript QML 类型。
QThread
此类管理应用程序中可用的线程。它是平台无关的,并提供了一种将任务执行分离到不同事件循环的方法。此类声明的语法如下:
thread = QtCore.QThread()
QThread 从 QObject 类继承,并通过以下函数增强了功能。
设置
这些函数将参数/属性设置到线程中:
thread.setEventDispatcher(QtCore.QAbstractEventDispatcher): 这将设置用于此线程的事件分发器,该分发器由参数指定。
thread.setPriority(QtCore.QThread.Priority): 这将设置用于此线程运行的优先级,该优先级由参数指定。可用的优先级如下:
-
QtCore.QThread.IdlePriority—0: 此线程仅在没有任何其他线程运行时运行。 -
QtCore.QThread.LowestPriority—1: 此线程具有最低的运行优先级。 -
QtCore.QThread.LowPriority—2: 此线程具有低运行优先级。 -
QtCore.QThread.NormalPriority—3: 此线程具有正常(操作系统的默认值)的运行优先级。 -
QtCore.QThread.HighPriority—4: 此线程具有高运行优先级。 -
QtCore.QThread.HighestPriority—5: 此线程具有最高的运行优先级。 -
QtCore.QThread.TimeCriticalPriority—6: 此线程尽可能频繁地与其他线程运行。 -
QtCore.QThread.InheritPriority—7: 此线程以与创建线程相同的优先级运行。
thread.setStackSize(int): 这将此线程的最大堆栈大小设置为参数中指定的字节数。
thread.setTerminationEnabled(bool): 如果此参数为 True,则启用线程的终止。
is
这些函数返回与线程状态相关的布尔值,bool:
thread.isFinished(): 如果此线程已完成,则返回 True。
thread.isInterruptionRequested(): 如果请求中断此线程,则返回 True。
thread.isRunning(): 如果此线程正在运行,则返回 True。
functional
这些函数与线程的当前值、功能变化等相关:
thread.currentThread(): 这返回当前操作线程的 QtCore.QThread 类型的对象。
thread.currentThreadId(): 这返回当前线程的处理程序。
thread.eventDispatcher(): 这返回当前操作线程的 QtCore.QAbstractEventDispatcher 类型的事件分发器对象。
thread.exec_(): 这通过进入事件循环来执行此线程。
thread.exit(int): 这以参数中指定的返回代码退出线程的事件循环(0 表示成功;任何非零值表示错误)。
thread.idealThreadCount(): 这返回系统上可以使用的理想线程数。
thread.loopLevel(): 这返回此线程的事件循环级别。
thread.msleep(int): 在参数中指定的毫秒数过去后,此线程会进入休眠状态。
thread.priority(): 这返回用于此线程的 QtCore.QThread.Priority 类型的优先级。
thread.quit(): 这以返回代码 0 退出此线程的事件循环。
thread.requestInterruption(): 这请求中断此线程
thread.run(): 这调用创建的线程的 run() 函数。
thread.sleep(int): 在参数中指定的秒数过去后,此线程会进入休眠状态。
thread.stackSize(): 这返回此线程的最大堆栈大小,以字节数表示。
thread.start(QtCore.QThread.Priority): 这启动此线程并开始执行参数中指定的 run() 函数指令,指定优先级。
thread.terminate(): 这将终止此线程的执行。
thread.usleep(int): 该线程将在参数指定的微秒数内休眠。
thread.wait(int): 这将阻塞此线程,直到它完成执行或等待参数指定的毫秒数。
thread.yieldCurrentThread(): 这将使当前线程的执行权交由另一个线程,操作系统将切换到该线程。
信号
这些是 QThread 类的可用信号:
thread.finished(): 在此线程执行完毕之前发出此信号。
thread.started(): 在此线程开始执行之前发出此信号。
QThreadPool
此类管理可用于应用程序的线程集合。Qt 应用程序有一个全局的 QThreadPool 对象,用于管理应用程序中使用的主(GUI)和附加(工作)线程。可以通过调用 globalInstance() 静态函数来访问现有的线程池。此类的声明语法如下:
thread_pool = QtCore.QThreadPool()
QThreadPool 从 QObject 类继承,并通过以下函数增强了其功能。
设置
这些函数设置线程池的参数/属性:
thread_pool.setExpiryTimeout(int): 这将为线程池设置过期超时时间(以毫秒为单位),指定在参数中,之后所有未使用的线程都被视为过期并退出。
thread_pool.setMaxThreadCount(int): 这将设置池中将使用的最大线程数,该数由参数指定。
thread_pool.setStackSize(int): 这将为池中的工作线程设置最大堆栈大小,以字节数的形式指定在参数中。
函数式
这些函数与线程池的当前值、功能变化等相关:
thread_pool.activeThreadCount(): 这返回池中活动线程的数量。
thread_pool.cancel(QtCore.QRunnable): 这将从队列中移除尚未启动或指定在参数中的可运行对象。
thread_pool.clear(): 这将从队列中移除尚未启动的可运行对象。
thread_pool.expiryTimeout(): 这返回线程池的过期超时时间,或所有未使用的线程被视为过期并退出后的时间(以毫秒为单位)。
thread_pool.globalInstance(): 这返回线程池的 QtCore.QThreadPool 类的全局实例。
thread_pool.maxThreadCount(): 这将返回池中使用的最大线程数。
thread_pool.releaseThread(): 通过 reserveThread() 函数之前保留的线程被释放。
thread_pool.reserveThread(): 这将保留线程。
thread_pool.stackSize(): 这返回池中工作线程的最大堆栈大小(以字节数表示)。
thread_pool.start(QtCore.QRunnable, int):这会保留这个线程,并使用它来运行一个可运行的(第一个参数)对象,具有优先级(第二个参数),以确定队列的执行顺序。
thread_pool.tryStart(QtCore.QRunnable):这尝试保留线程以运行在参数中指定的可运行对象。
thread_pool.tryTake(QtCore.QRunnable):这尝试从队列中移除在参数中指定的可运行对象。
thread_pool.waitForDone(int):这将等待在参数中指定的毫秒数超时,等待所有线程退出,并从池中移除所有线程(默认超时为-1或忽略)。
线程示例
为了查看线程的示例,我们将修改与 CouchDB 和 MongoDB 功能相关的先前代码。在u_tools.py文件中,让我们添加具有线程和函数的类,这些函数将使线程依赖于应用程序中的任务:
- 添加用于 MongoDB 服务器的线程类:
...
class MongoThread(QThread):
sig1 = app_signal(object, str)
def __init__(self, parent=None):
super(MongoThread, self).__init__(parent)
def on_source(self, datas):
self.datas = datas
...
...
这是课程的第一个部分,它有一个会发射数据的信号。它还包含on_source()函数,该函数将接收数据。
- 现在,我们需要将实现我们的线程功能的
run()函数添加到MongoThread类中:
...
...
def run(self):
try:
import pymongo
try:
self.client = pymongo.MongoClient('localhost',
27017)
self.db = self.client['umongodb']
except pymongo.errors as err:
self.sig1.emit('', str(err))
if self.datas[1] == "insert":
posts = self.db.posts
posts.insert_one(self.datas[0])
if self.datas[1] == "select":
dbdata = self.db.posts.find()
self.sig1.emit(dbdata, '')
if self.isFinished():
self.quit()
except Exception as err:
self.sig1.emit('', str(err))
if self.isFinished():
self.quit()
...
线程的run()函数将启动线程功能。它将尝试连接到 MongoDB 服务器。当连接成功后,它将尝试向/从数据库插入/选择值。
- 添加用于 CouchDB 服务器的
CouchThread类:
...
class CouchThread(QThread):
sig1 = app_signal(object, str)
def __init__(self, parent=None):
super(CouchThread, self).__init__(parent)
def on_source(self, datas):
self.datas = datas
...
...
这是课程的第一个部分,它有一个会发射数据的信号,以及on_source()函数,该函数将接收数据。
- 现在,将实现线程功能的
run()函数添加到CouchThread类中:
...
...
def run(self):
try:
import couchdb
try:
self.couch = couchdb.Server(
"http://127.0.0.1:5984/")
self.db = self.couch["u_couchdb"]
except Exception as err:
self.sig1.emit('', str(err))
if self.datas[1] == "insert":
self.db.save(self.datas[0])
if self.datas[1] == "select":
self.sig1.emit(self.db, '')
if self.isFinished():
self.quit()
except Exception as err:
self.sig1.emit('', str(err))
if self.isFinished():
self.quit()
...
这个线程的run()函数将启动线程功能。它将尝试连接到 CouchDB 服务器。当连接成功后,它将尝试向/从数据库插入/选择值。现在,我们需要添加将在应用程序中提供线程功能的功能。首先,我们需要添加在UTools类中将使用的信号。
- 用于通信的信号看起来像这样:
...
class UTools(object):
pandas_sig1 = app_signal(list)
pandas_sig2 = app_signal(list)
mongo_sig1 = app_signal(list)
mongo_sig2 = app_signal(list)
couch_sig1 = app_signal(list)
couch_sig2 = app_signal(list)
def __init__(self):
...
...
...
这些新信号将在UTools类的功能与为 Mongo 和 Couch 数据库实现创建的线程之间进行通信。然后,我们需要将u_tools.py文件中的UTools类的先前创建的函数修改为写入和读取 Couch 和 Mongo 数据库。
- 修改
UTools类的mongo_insert()函数:
...
...
def mongo_insert(self, username=None, email=None,
passw=None, data=None):
datas = [{"User Name": username, "Email": email,
"Password": passw, "Data": data}, "insert"]
self.mongo_thread1 = MongoThread()
self.mongo_sig1.connect(self.mongo_thread1.on_source)
self.mongo_sig1.emit(datas)
self.mongo_thread1.start()
...
...
这个函数将使用线程写入datas列表中指定的数据。这个线程的实例将被使用,以及用于向线程发射这些数据的信号的连接。这将启动线程(默认优先级为InheritPriority)。
- 修改
UTools类的mongo_select()函数:
...
...
def mongo_select(self):
datas = [{}, "select"]
self.mongo_thread2 = MongoThread()
self.mongo_sig2.connect(self.mongo_thread2.on_source)
self.mongo_sig2.emit(datas)
self.mongo_thread2.start()
return self.mongo_thread2
...
...
此函数将使用线程读取 MongoDB 实例的数据。线程实例将与用于向线程发射此数据的信号连接创建。发射的数据将是一个包含空字典(可选)和指示读取操作的字符串的列表。然后,线程开始运行。
- 现在,修改
UTools类的couch_insert()函数:
...
...
def couch_insert(self, username=None, email=None,
passw=None, data=None):
datas = [{"User Name": username,
"User email": email,
"User password": passw,
"User Data": data}, "insert"]
self.couch_thread1 = CouchThread()
self.couch_sig1.connect(self.couch_thread1.on_source)
self.couch_sig1.emit(datas)
self.couch_thread1.start()
...
...
此函数将使用线程将datas列表中指定的数据写入 Couch 数据库。线程实例将被使用,同时连接用于向线程发射此数据的信号。现在,线程将开始运行。
- 修改
UTools类的couch_select()函数:
...
...
def couch_select(self):
datas = [{}, "select"]
self.couch_thread2 = CouchThread()
self.couch_sig2.connect(self.couch_thread2.on_source)
self.couch_sig2.emit(datas)
self.couch_thread2.start()
return self.couch_thread2
...
...
此函数将使用线程读取数据。线程实例将被创建,同时连接用于向线程发射此数据的信号。发射的数据将是一个包含空字典(可选)和指示读取操作的字符串的列表。
现在,我们需要修改与从 Couch 和 Mongo 数据库读取相关的u_app.py文件中的UApp类的data()函数。让我们开始吧:
- 修改
UApp类的data()函数:
...
...
...
if self.actx == "MongoDB":
try:
mongo_data = self.mongo_select()
def to_field(dbdata, er):
if er == '':
for dtx in dbdata:
self.text_edit.append(
"%s\n%s\n%s\n%s" % (
dtx["User Name"],
dtx["Email"],
dtx["Password"],
dtx["Data"]))
else:
self.stat_bar.showMessage(
self.actx + ' ' + er)
mongo_data.sig1.connect(
to_field, QtCore.Qt.QueuedConnection)
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
当在顶部面板中选择数据|MongoDB选项时,这些行提供 MongoDB 功能。它接收到线程对象时调用mongo_select()函数,通过线程的信号连接到嵌套函数,并将数据库数据放入文本字段。如果发生错误,它将在应用程序的状态栏中显示此错误。
- 修改
UApp类的data()函数:
...
...
...
if self.actx == "CouchDB":
try:
couch_data = self.couch_select()
def to_field(dbdata, er):
if er == '':
for dtx in dbdata.view(
"_all_docs",
include_docs=True):
self.text_edit.append(
"%s\n%s\n%s\n%s" % (
dtx["doc"]["User Name"],
dtx["doc"]["User email"],
dtx["doc"]["User password"],
dtx["doc"]["User Data"]))
else:
self.stat_bar.showMessage(
self.actx + ' ' + er)
couch_data.sig1.connect(
to_field, QtCore.Qt.QueuedConnection)
self.stat_bar.showMessage(
self.actx + " opened")
except Exception as err:
self.stat_bar.showMessage(
self.actx + ' ' + str(err))
...
...
...
当选择CouchDB选项时,这些行提供 CouchDB 功能。它接收到线程对象时调用couch_select()函数,通过线程的信号连接到嵌套函数,并将数据库数据放入文本字段。如果发生错误,它将在应用程序的状态栏中显示此错误。
这些示例在使用方面有一些限制。请注意,当我们使用此功能时,我们需要确保 CouchDB 和 MongoDB 服务器已配置并正在运行,并且数据库已在该目录中创建。
锁定
在应用程序中使用线程时,可能会出现与多个线程访问类似源相关的问题,或者当您需要锁定代码的一部分执行时。Qt 库提供了一些类来解决此问题,例如QMutex、QMutexLocker、QReadWriteLock、QSemaphore和QWaitCondition。在这里,我们将描述其中的一些。然而,请注意,锁定某些源可能会创建与阻塞 GUI 线程或另一个线程相关的其他问题。因此,在应用程序中使用锁不是一件简单的事情,在实现之前,我们需要仔细考虑。
QMutex
这个类允许线程之间的访问序列化。为了强制互斥(mutex),线程锁定互斥锁以获取对资源的访问。这个类的声明语法如下:
mutex = QtCore.QMutex(QtCore.QMutex.RecursionMode)
可以通过参数指定递归模式来构造互斥锁。可用的递归模式如下:
-
QtCore.QMutex.Recursive—0: 这个线程能够多次锁定相同的互斥锁。这个互斥锁将不会解锁,直到相应的unlock()函数调用次数达到相应的数量。 -
QtCore.QMutex.NonRecursive—1: 这个线程只能锁定一次相同的互斥锁。
QMutex从QBasicMutex类继承,并通过以下函数增强了其功能。
是
这个函数返回一个与互斥锁状态相关的布尔值(bool):
mutex.isRecursive(): 如果这个互斥锁具有递归模式,则返回True。
功能性
这些函数与互斥锁的当前值、功能变化等相关:
mutex.lock(): 这将锁定互斥锁。
mutex.tryLock(int): 这将尝试锁定互斥锁。如果另一个线程已经锁定了互斥锁,它将在锁定之前等待指定参数中的毫秒数(默认超时为0)。
mutex.unlock(): 这将解锁互斥锁。
QMutex 示例
当使用线程时,通常可以在应用程序中实现互斥锁。让我们用以下代码行来演示这一点:
...
class WPandas(QThread):
...
def __init__(self, parent=None):
...
self.mutex = QMutex()
...
def run(self):
self.mutex.lock()
try:
...
except Exception as err:
...
self.mutex.unlock()
...
__init__()函数创建了从QtCore模块导入的QMutex类的实例。在线程的run()函数内部,我们添加了包含互斥锁的lock()和unlock()方法的行,它们将分别锁定和解锁它们之间的代码。
QMutexLocker
这个类提供了锁定和解锁互斥锁的附加方便功能。这个类的声明语法如下:
mutex_locker = QtCore.QMutexLocker(QtCore.QBasicMutex)
QMutexLocker类通过以下函数提高了功能。
功能性
这些函数与互斥锁锁定的当前值、功能变化等相关:
mutex_locker.mutex(): 这将返回由这个互斥锁锁定器操作的QtCore.QMutex类型的互斥锁。
mutex_locker.relock(): 这将重新锁定已解锁的互斥锁锁定器。
mutex_locker.unlock(): 这将解锁互斥锁锁定器。
QMutexLocker 示例
之前关于互斥锁的例子有一些缺陷。如果在unlock()方法执行代码之前发生异常,互斥锁可能会永久锁定。为了解决这个问题,我们可以使用QMutexLocker类。让我们用之前创建的互斥锁来演示这一点:
...
class WPandas(QThread):
...
def __init__(self, parent=None):
...
self.mutex = QMutex()
...
def run(self):
mutex_locker = QMutexLocker(self.mutex)
try:
...
except Exception as err:
...
...
在 run() 函数中,我们创建了一个从 QtCore 模块导入的 QMutexLocker 类的实例,并将指定的互斥锁作为参数。在作用域结束时,类的析构函数将被调用,并且这个锁将自动释放。这也可以用于构建上下文管理器,例如指令;例如,with/as。将前面的代码行更改为以下内容:
...
class WPandas(QThread):
...
def __init__(self, parent=None):
...
self.mutex = QMutex()
...
def run(self):
with QMutexLocker(self.mutex):
try:
...
except Exception as err:
...
...
QSystemSemaphore
此类为在应用程序中与线程和多个进程一起工作提供了一般计数系统信号量。此类的声明语法如下:
system_semaphore = QtCore.QSystemSemaphore(str, int,
QtCore.QSystemSemaphore.AccessMode)
此系统信号量可以使用键(第一个参数)和系统依赖的初始化资源数量(第二个参数)以及访问模式(第三个参数)进行构造。可用的访问模式如下:
-
QtCore.QSystemSemaphore.Open—0: 如果系统信号量存在,则其初始资源计数不会被重置;否则,它将被创建。 -
QtCore.QSystemSemaphore.Create—0: 系统信号量将被创建。
QSystemSemaphore 类通过以下函数增强了功能。
set
此函数设置系统信号量的参数/属性:
system_semaphore.setKey(str, int, QtCore.QSystemSemaphore.AccessMode): 这使用键(第一个参数)和系统依赖的初始化资源数量(第二个参数)以及访问模式(第三个参数)重建系统信号量对象。
functional
这些函数与系统信号量的当前值、功能变化等相关:
system_semaphore.acquire(): 这将获取由该系统信号量守护的资源之一。
system_semaphore.error(QtCore.QSystemSemaphore.SystemSemaphoreError): 如果此系统信号量发生错误,则返回错误类型的值。可能发生的错误如下:
-
QtCore.QSystemSemaphore.NoError—0: 无错误。 -
QtCore.QSystemSemaphore.PermissionDenied—1: 调用者权限不足。 -
QtCore.QSystemSemaphore.KeyError—2: 已指定无效的键。 -
QtCore.QSystemSemaphore.AlreadyExists—3: 指定的键的系统信号量已存在。 -
QtCore.QSystemSemaphore.NotFound—4: 指定的系统信号量无法找到。 -
QtCore.QSystemSemaphore.OutOfResources—5: 内存不足。 -
QtCore.QSystemSemaphore.UnknownError—6: 错误未知。
system_semaphore.errorString(): 这返回错误文本描述。
system_semaphore.key(): 这返回此系统信号量的键或从其他进程访问此系统信号量的名称。
system_semaphore.release(int): 这将释放由该系统信号量守护的指定参数数量的资源。
QSemaphore
这个类为应用程序中与线程一起工作创建了一般计数信号量。这个类的声明语法如下:
semaphore = QtCore.QSemaphore(int)
信号量可以通过指定参数中指定的资源数量进行初始化。QSemaphore类通过以下函数增强了功能。
functional
这些函数与信号量的当前值、功能变化等相关:
semaphore.acquire(int): 这获取由该信号量保护的指定数量(参数中指定)的资源。
semaphore.available(): 这返回此信号量可用的资源数量。
semaphore.release(int): 这释放由该信号量保护的指定数量的资源。
semaphore.tryAcquire(int): 这尝试获取由该信号量保护的指定数量的资源。
semaphore.tryAcquire(int, int): 这尝试获取由该信号量保护的资源数量(第一个参数)在指定的时间内(第二个参数)。
信号量构造通常用于控制多个线程对资源的访问。在 PyQt5/PySide 绑定和/examples/threads/文件夹中的线程示例中,可以找到一个很好的信号量示例,该文件夹位于site-packages/,这与使用的绑定相关。
QWaitCondition
这个类通过提供条件变量来同步线程。这个类的声明语法如下:
wait_condition = QtCore.QWaitCondition()
QWaitCondition类通过以下函数增强了功能。
functional
这些函数与信号量的当前值返回、功能变化等相关:
wait_condition.wait(QtCore.QMutex, int): 这释放被锁定的互斥锁(第一个参数)并等待等待条件,例如其他线程的信号,包括wakeOne()或wakeAll(),或者毫秒数(第二个参数)超时。
wait_condition.wait(QtCore.QReadWriteLock, int): 这释放被锁定的读写锁(第一个参数)并等待等待条件,例如其他线程的信号,包括wakeOne()或wakeAll(),或者毫秒数(第二个参数)超时。
wait_condition.wakeAll(): 这唤醒所有正在等待等待条件的线程。
wait_condition.wakeOne(): 这唤醒一个正在等待等待条件的线程。
Python 标准库工具
Python 标准库的工具可以通过 Qt 库的 PySide2/PyQt5 Python 绑定轻松实现,在我们的 GUI 应用程序中。我们可以用类似我们在本章前面描述的方式描述我们将要使用的工具。
threading
此 Python 标准库模块使用 PyQt 和 PySide 绑定实现了任何基于 Python 的应用程序的线程功能。此模块可以在比类似 QThread 类更广泛的意义上使用,用于应用程序中的专用任务。但我们需要知道,在 PyQt/PySide GUI 中,QThread 类允许通过信号进行通信和功能。要在应用程序中使用线程,我们需要导入此模块:
...
import threading
...
我们将只描述此模块的常用部分。有关此模块的完整信息可在官方文档中找到:docs.python.org/3/。此模块使用以下有用的函数:
threading.active_count(): 这返回当前正在运行的线程数。
threading.current_thread(): 这返回当前正在使用的线程。
threading.get_ident(): 这返回当前线程的标识符。
threading.enumerate(): 这返回当前所有正在运行的线程的列表。
threading.main_thread(): 这返回主线程。在 Python 语境中,这是启动操作 Python 环境的 Python 解释器的线程。
threading.stack_size(int): 这返回创建新线程时将使用的堆栈大小。如果指定了可选参数,则将其用作堆栈大小。请注意,该参数是字节数,并且可以使用 0 或至少 32 KiB (32768);例如,512 KiB 以数字形式表示为 524288。
threading 模块通过几个类实现此功能(提供的参数与 Python 3.x 相关)。
Thread
threading 模块的 thread 类如下:
thread1 = threading.Thread(group=None, target=None, name=None,
args=(), kwargs={}, *, daemon=None)
group 保留用于将来扩展,当实现 ThreadGroup 类时;target 是一个可调用对象;name 是线程的名称;args 是用于的参数元组;kwargs 是关键字参数的字典;daemon 将线程设置为守护线程。Thread 类具有以下功能:
-
thread1.start(): 这将启动线程。 -
thread1.run(): 这代表线程活动。 -
thread1.join(float): 这等待直到线程终止。超时参数可选地等待在阻塞操作之前或终止后立即阻塞。 -
thread1.is_alive(): 如果此线程正在运行,则返回True,否则返回False。
构建此类通常如下所示:
def func(n):
...
thread1 = threading.Thread(target=func, args=(14,))
thread1.start()
thread1.join()
Lock
这些是原始锁对象:
thread1_lock = threading.Lock
Lock 类具有以下功能:
thread1_lock.acquire(blocking=True, timeout=-1): 这将获取阻塞或非阻塞。
thread1_lock.release(): 这将释放锁。
RLock
这些是可重入锁对象:
thread1_rlock = threading.RLock
RLock 类具有以下功能:
thread1_rlock.acquire(blocking=True, timeout=-1): 这将获取阻塞或非阻塞。
thread1_rlock.release(): 这将释放锁。
条件
这些是条件变量对象:
thread1_cond = threading.Condition(lock=None)
Condition类有以下功能:
thread1_cond.acquire(*args): 这获取底层的锁。
thread1_cond.release(): 这释放了底层的锁。
thread1_cond.wait(timeout=None): 这将等待直到被通知或发生超时。
thread1_cond.wait_for(predicate, timeout=None): 这将等待直到条件评估为True。条件参数是一个可调用对象,它返回一个布尔值(True或False)。
thread1_cond.notify(n=1): 这将唤醒n个线程。
thread1_cond.notify_all(): 这唤醒所有线程。
信号量
这些是信号量对象,它们管理一个计数器,该计数器计算释放次数减去获取次数,再加上初始值:
thread1_sema = threading.Semaphore(value=1)
Semaphore类有以下功能:
thread1_sema.acquire(*args): 这获取信号量。
thread1_sema.release(): 这释放信号量。
有界信号量
这些是有界信号量对象,用于检查当前值是否不超过其初始值:
thread1_bsema = threading.BoundedSemaphore(value=1)
事件
这些是用于线程间通信的事件对象。这是通过管理内部标志来完成的:
thread1_event = threading.Event
Event类有以下功能:
thread1_event.is_set(): 如果内部标志为True,则返回True。
thread1_event.set(): 这将内部标志设置为True。
thread1_event.clear(): 这将内部标志设置为False。
thread1_event.wait(timeout=None): 这将阻塞直到标志为True。
定时器
这些是运行动作计时的定时器对象。这将在指定的时间段之后运行。提供的参数是动作将运行的interval;要运行的function;作为将使用的参数的args;以及作为关键字参数的kwargs:
thread1_timer = threading.Timer(interval, function,
args=None, kwargs=None)
Timer类有以下功能:
thread1_timer.cancel(): 这通过取消其执行来停止定时器。
屏障
这些是使用固定数量的线程实现的屏障对象,这些线程需要相互等待。线程通过调用wait()方法来尝试通过屏障。提供的参数是parties,即线程的数量;action,即将被一个线程调用的可调用对象;以及timeout,它是用于wait()方法的值:
thread1_barrier = threading.Barrier(parties, action=None,
timeout=None)
Barrier类有以下功能:
thread1_barrier.wait(timeout=None): 这通过屏障。
thread1_barrier.reset(): 这重置屏障并设置空状态。
thread1_barrier.abort(): 这中止屏障并设置损坏状态。
thread1_barrier.parties: 这返回通过屏障所需的线程数量。
thread1_barrier.n_waiting: 这返回在屏障中等待的线程数量。
thread1_barrier.broken: 如果屏障处于损坏状态,则返回True。
队列
在多个线程等待运行一个任务的情况下,使用队列来运行这个任务非常重要。标准库queue模块可以在我们的应用程序中使用多生产者和多消费者队列功能。Python 对 Qt 的绑定有相对复杂的队列实现工具,并且这个模块在 GUI 的线程结构中得到了广泛的应用。此模块实现了三种类型的队列:先进先出(FIFO)、后进先出(LIFO)和带优先级的队列。要在我们的应用程序中使用它们,我们需要导入以下模块:
...
import queue
..
让我们描述一下可以使用的最重要的类和方法。
Queue
这些是具有maxsize上限的 FIFO 队列,可以放置在队列中的项目数量:
queue1 = queue.Queue(maxsize=0)
LifoQueue
这些是具有maxsize上限的 LIFO 队列,可以放置在队列中的项目数量:
queue1 = queue.LifoQueue(maxsize=0)
PriorityQueue
这些是具有maxsize上限的优先队列,可以放置在队列中的项目数量:
queue1 = queue.PriorityQueue(maxsize=0)
SimpleQueue
这些是无界 FIFO 队列:
queue1 = queue.SimpleQueue
functions
可以使用的Queue, LifoQueue, PriorityQueue, 和 SimpleQueue类的方法定义如下:
queue1.qsize(): 返回队列的大约大小,因为队列通常会变化(Queue, LifoQueue, PriorityQueue, SimpleQueue)。
queue1.empty(): 如果队列大约为空,则返回True(Queue, LifoQueue, PriorityQueue, SimpleQueue)。
queue1.full(): 如果队列大约已满(至少有一个项目),则返回True(Queue, LifoQueue, PriorityQueue)。
queue1.put(item, block=True, timeout=None): 将指定的项目放入队列。提供了可选的 block 和 timeout 参数(Queue, LifoQueue, SimpleQueue)。
queue1.put((priority, item), block=True, timeout=None): 将指定的项目以整数优先级值放入队列。提供了可选的 block 和 timeout 参数(PriorityQueue)。
queue1.put_nowait(item): 将指定的项目放入队列。提供了可选的 block 和 timeout 参数(Queue, LifoQueue, SimpleQueue)。
queue1.put_nowait((priority, item)): 将指定的项目以整数优先级值放入队列。提供了可选的 block 和 timeout 参数(PriorityQueue)。
queue1.get(block=True, timeout=None): 从队列中返回一个项目。提供了可选的 block 和 timeout 参数(Queue, LifoQueue, PriorityQueue, SimpleQueue)。
queue1.get_nowait(): 这从队列中返回一个项目(Queue, LifoQueue, PriorityQueue, SimpleQueue)。
queue1.task_done(): 这表示队列的任务已完成(Queue, LifoQueue, PriorityQueue)。
queue1.join(): 这将阻塞,直到所有项目都已被处理并完成(Queue, LifoQueue, PriorityQueue)。
subprocess
这个 Python 标准库模块以类似于 Qt 库中的QProcess类的方式实现了运行进程的功能。此模块以新进程的形式运行任务,连接到进程的输入/输出/错误管道,并获取它们的返回码。之前,我们实现了运行相机设备功能等子进程。让我们更详细地描述这个模块。要在我们的应用程序中使用它,我们需要导入以下模块:
...
import subprocess
...
在以下部分中描述了在应用程序中可以使用的最重要的类和方法。
run()
从 Python 3.5 版本开始可用的run()方法,在新的进程中运行任务。其语法如下:
subprocess1 = subprocess.run(["command", "-flags", "args"],
*, stdin=None, input=None, stdout=None,
stderr=None, capture_output=False,
shell=False, cwd=None, timeout=None,
check=False, encoding=None, errors=None,
text=None, env=None, universal_newlines=None)
第一个参数是一个包含命令、参数以及如果有的话标志的列表。stdin、stdout和stderr参数指定了执行程序的STDIN(标准输入)、STDOUT(标准输出)和STDERR(标准错误)。可以使用PIPE、DEVNULL和STDOUT等值。input用于communicate()方法。如果capture_output为True,则stdout和stderr将被捕获。如果shell为True,则指定通过 shell 执行的命令。如果cwd不是None,则在执行前会更改cwd(当前工作目录)。timeout用于communicate()方法。当超时到期时,子进程将被杀死并等待。如果check为True,并且进程以非零退出码退出,则将引发CalledProcessError异常。encoding指定将使用哪种编码,例如"utf-8"或"cp1252"。errors指定如何使用字符串值(如"strict"、"ignore"、"replace"、"backslashreplace"、"xmlcharrefreplace"和"namereplace")处理编码和解码错误。如果text为True,则stdin、stdout和stderr的文件对象将以文本模式打开。env定义了新进程的环境变量。universal_newlines与text等效,并提供向后兼容性。
Popen
Popen类在subprocess模块中处理底层进程创建和管理。这个类提供了可以使用的附加可选参数。这个类的语法看起来像这样:
subprocess1 = subprocess.Popen(["command", "-flags", "args"],
bufsize=-1, executable=None, stdin=None,
stdout=None, stderr=None, preexec_fn=None,
close_fds=True, shell=False, cwd=None,
env=None, universal_newlines=None,
startupinfo=None, creationflags=0,
restore_signals=True,
start_new_session=False, pass_fds=(), *,
encoding=None, errors=None, text=None)
第一个参数是一个包含命令、参数以及(如果提供)标志的列表。bufsize将在创建stdin/stdout/stderr管道文件对象时与open()函数一起使用。executable指定要执行的替换程序。stdin、stdout和stderr参数指定要执行的程序的STDIN(标准输入)、STDOUT(标准输出)和STDERR(标准错误)。有效值包括PIPE、DEVNULL和STDOUT。如果设置了preexec_fn,则对象将在子进程执行之前在子进程中调用(仅限 POSIX)。如果close_fds为True,则在执行之前将关闭所有文件描述符,除了0、1和2。如果shell为True,则将通过 shell 执行命令。如果cwd不是None,则在执行之前将更改cwd(当前工作目录)。env定义了新进程的环境变量。universal_newlines等同于文本,并提供向后兼容性。startupinfo将是一个STARTUPINFO对象,它将带有创建标志传递给CreateProcess函数。如果restore_signals为True,则在执行之前将所有设置为SIG_IGN的信号恢复为SIG_DFL(仅限 POSIX)。如果start_new_session为True,则在子进程执行子进程之前将执行setsid()系统调用(仅限 POSIX)。pass_fds是父进程和子进程之间保持打开的文件描述符序列(仅限 POSIX)。encoding指定将使用哪种编码,例如"utf-8"或"cp1252"。errors指定如何处理编码和解码错误,字符串值包括"strict"、"ignore"、"replace"、"backslashreplace"、"xmlcharrefreplace"和"namereplace"。如果text为True,则将stdin、stdout和stderr的文件对象以文本模式打开。
函数
可以与该模块一起使用的以下方法:
subprocess1.poll(): 这检查子进程是否已终止。
subprocess1.wait(timeout=None): 如果指定了超时,则等待子进程终止。
subprocess1.communicate(input=None, timeout=None): 通过向子进程发送数据并从STDOUT/STDERR读取数据,同时等待终止来与进程交互。输入可以是发送到子进程的数据。
subprocess1.send_signal(signal): 这向子进程发送信号。它有以下功能:
-
subprocess1.terminate(): 使用操作系统参数终止子进程。 -
subprocess1.kill(): 使用操作系统参数终止子进程。 -
subprocess1.args: 这返回传递给Popen的参数。 -
subprocess1.stdin: 这返回传递给Popen标准输入的参数。 -
subprocess1.stdout: 这返回传递给Popen标准输出的参数。 -
subprocess1.stderr: 这返回传递给Popen标准错误的参数。 -
subprocess1.pid: 这将返回子进程的进程 ID。 -
subprocess1.returncode: 这将返回子进程的返回代码。
multiprocessing
这个 Python 标准库包管理了在应用程序中可以使用的进程创建。当使用本地和远程并发时,这个工具通过使用子进程而不是线程来绕过 全局解释器锁 (GIL) 的限制,如果设备有多个处理器,则可以有效地利用多个处理器。multiprocessing 包的 API 与 threading 模块类似,方法大多复制了 threading 模块的 Thread 类,类似于前面展示的 queue 模块的 Queue。为了在我们的应用程序中使用它,我们需要导入以下包:
...
import multiprocessing
..
Process
这个类表示了能够实现多进程和单独进程活动的进程对象。语法如下:
process1 = multiprocessing.Process(group=None, target=None,
name=None, args=(),
kwargs={}, *, daemon=None)
参数的含义与 threading 模块的 Thread 类中的参数类似。在这个类中使用的如下方法:
process1.run(): 这代表进程的活动。
process1.start(): 这将启动进程。
process1.join(float): 这将等待直到进程终止。超时参数(可选)在阻塞操作之前等待,或者在终止后立即阻塞。
process1.is_alive(): 如果此进程正在运行,则返回 True,否则返回 False。
process1.close(): 这将关闭进程并释放所有相关资源。
process1.kill(): 这将杀死进程。
process1.terminate(): 这将终止进程。
process1.name: 这将返回进程的名称。
process1.daemon: 这将返回进程的守护进程标志,即 True 或 False。
process1.pid: 这将返回进程的 ID。
process1.exitcode: 这将返回子进程的退出代码。
process1.authkey: 这将返回进程的认证密钥。
process1.sentinel: 这将返回系统对象数字句柄,当进程结束时将准备好。
Connection
这个类创建了连接对象,允许我们发送和接收可序列化的对象或字符串。语法如下:
conn = multiprocessing.connection.Connection
可以使用的方法如下:
conn.send(obj): 这将可序列化的对象发送到连接的另一端。
conn.recv(): 这将返回从连接另一端接收到的对象。
conn.fileno(): 这将返回连接的文件描述符或句柄。
conn.close(): 这将关闭连接。
conn.poll(timeout): 如果有可读数据,则返回 True。
conn.send_bytes(buffer, offset, size): 这将从字节对象发送数据。如果指定了 offset,则将从 buffer 中的位置读取数据,如果指定了 size,则以字节数为单位。
conn.recv_bytes(maxlength): 这返回从连接的另一端接收到的字节数据的消息。如果指定了maxlength,则限制消息。
conn.recv_bytes_into(buffer, offset): 这读取从连接的另一端接收到的字节数据的消息,并返回消息中的字节数。如果指定了offset,则消息将从该位置写入buffer。
连接通常使用Pipe类创建。构建此类连接的语法如下:
conn1, conn2 = multiprocessing.Pipe(duplex)
如果duplex参数为True,则管道是双向的;如果为False,则管道是单向的。这意味着conn1用于接收消息,而conn2用于发送消息。以下是一个连接的示例:
def func1(msg, conn):
conn.send(str(msg))
conn.close()
def func2(msg, conn):
conn.send(msg)
conn.close()
if __name__ == "__main__":
conn1, conn2 = multiprocessing.Pipe()
process1 = multiprocessing.Process(
target=func1, args=(
"Hello Process # 1", conn2))
process2 = multiprocessing.Process(
target=func2, args=(
"Hello Process # 2", conn1))
process1.start()
process2.start()
print(conn1.recv())
print(conn2.recv())
process1.join()
process2.join()
在这里,我们创建了具有Connection类的发送方法的函数;使用了Pipe类进行连接,并且也使用了之前描述的方法。这种构建不是随机的。在多进程方面,我们需要在if __name__ == "__main__"指令内操作进程,或者调用具有多进程功能的功能。使用multiprocessing包,类如Pool(创建进程池)、Queue(创建队列)、Manager(控制管理共享对象的服务器进程)以及连接模块的Listener和Client类也是可用的。建议您了解这些类和模块。此外,多进程包还具有以下方法,可能很有用:
-
multiprocessing.active_children(): 这返回当前进程的所有活动子进程。 -
multiprocessing.cpu_count(): 这返回设备中使用的 CPU 数量。 -
multiprocessing.current_process(): 这返回当前进程。
摘要
本章完成了本书材料的基本部分。线程的使用提高了应用程序的生产力。仪器的重性和大小是一个如此庞大的主题,以至于我们需要一本书来涵盖所有内容。这就是为什么我们只看了起点。关于这些有趣且有用的工具的更多信息可以在 PySide2 的官方文档(doc.qt.io/qtforpython/index.html)、PyQt5([www.riverbankcomputing.com/static/Docs/PyQt5/](https://www.riverbankcomputing.com/static/Docs/PyQt5/))和当然还有 Python(https://docs.python.org/3/)的官方文档中找到。多线程和多进程的构建以及在我们应用程序中的实现具有核心地位,因为它们使得 GUI 应用程序舒适且用户友好。本章涵盖了 GUI 开发中所需的所有必要内容。
下一章将完成这本书。我们将最终确定我们的图形用户界面应用程序,提供将应用程序嵌入不同平台的方法,并在解释基础知识的同时尝试一些代码。
第十七章:完成应用程序、嵌入式设备和测试
本章将完成本书。描述了在开发初期可以使用的主要 GUI 元素。当然,Qt 库有超过 1,500 个类,工具可能根据 GUI 应用任务的不同而有所变化。然而,实现原理是相似的,读者可以轻松实现它们。在本书中,我们创建并演示了一个提供最有用功能的应用程序,本章将打包这个 GUI 应用程序以供展示。我们还将讨论在不同设备和平台上实现 GUI 的机制,并在可能的情况下,无需额外修改。Qt 目前支持最流行和最现代的平台,并为使用嵌入式设备部署应用程序提供了额外的机制。此外,我们将涵盖使用 Qt 库工具实现基于 Qt 的应用程序和库的单元测试的类。本章将涵盖以下主题:
-
完成应用程序
-
嵌入式设备
-
测试
完成应用程序
为了完成应用程序,我们需要运行u_app.py文件并查看哪些部分/功能尚未完成。正如我们所看到的,顶部面板栏中的一些选项尚未完成,所以让我们来完成这些。

在前面的屏幕截图中,我们看到了Edit、Options、Help和Visualization选项,这些选项将在本章的后续内容中构建。
编辑选项
顶部面板中的Edit选项通常用于使用简单的操作(如撤销/重做之前的操作、从文本字段中剪切选定文本、复制和粘贴到/从缓冲区)编辑文本编辑字段中的某些文本。
一些编辑选项是标准的,并复制了默认弹出窗口的选项,但我们添加了带有子菜单的Alignment选项以及文本编辑字段文本的字体/颜色更改选项。首先,打开u_window.py文件并添加/更改以下行:
- 向
Edit菜单添加新选项并添加一个子菜单,如下所示:
...
class UWindow(UWin):
def __init__(self, parent=None):
...
self.mb2 = UMenu(self.menubar)
self.mb2.addAction("Undo")
self.mb2.addAction("Redo")
self.mb2.addAction("Cut")
self.mb2.addAction("Copy")
self.mb2.addAction("Paste")
self.mb2_1 = self.mb2.addMenu("&Alignment")
self.mb2_1.addAction("center")
self.mb2_1.addAction("left")
self.mb2_1.addAction("right")
self.mb2_1.addAction("justify")
self.mb2.addAction("Text Color")
self.mb2.addAction("Text Font")
self.mb2.setTitle("&Edit")
...
...
将"&Alignment"选项添加为Edit选项的子菜单。还添加了关于文本字段中选定文本的颜色和字体的选项。
- 现在我们需要对
u_app.py文件中的UApp类进行一些添加/更改。
对UApp类的Edit选项的信号进行一些修改:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.mb1.triggered.connect(self.files)
self.mb2.triggered.connect(self.edit)
self.mb2_1.triggered.connect(self.edit_align)
self.mb3.triggered.connect(self.data)
...
...
...
Edit选项(self.mb2)将triggered()信号连接到edit()函数,而Alignment子菜单选项将连接到edit_align()函数。
- 现在将
edit()函数添加到UApp类中,如下所示:
...
...
def edit(self, action):
if action.text() == "Undo":
self.text_edit.undo()
if action.text() == "Redo":
self.text_edit.redo()
if action.text() == "Cut":
self.text_edit.cut()
if action.text() == "Copy":
self.text_edit.copy()
if action.text() == "Paste":
self.text_edit.paste()
if action.text() == "Text Color":
fd = QtWidgets.QColorDialog(self)
if fd.exec_() == QtWidgets.QDialog.Accepted:
fc = fd.selectedColor()
self.text_edit.setTextColor(fc)
if action.text() == "Text Font":
fd = QtWidgets.QFontDialog()
if fd.exec_() == QtWidgets.QDialog.Accepted:
f = fd.selectedFont()
self.text_edit.setFont(f)
...
...
此函数将使用简单的编辑选项操作,并包含更改文本编辑字段中选定文本的字体/颜色的功能。
- 现在将
edit_align()函数添加到UApp类中,如下所示:
...
...
def edit_align(self, action):
if action.text() == "center":
self.text_edit.setAlignment(
QtCore.Qt.AlignCenter)
if action.text() == "left":
self.text_edit.setAlignment(
QtCore.Qt.AlignLeft)
if action.text() == "right":
self.text_edit.setAlignment(
QtCore.Qt.AlignRight)
if action.text() == "justify":
self.text_edit.setAlignment(
QtCore.Qt.AlignJustify)
...
...
与此选项相关联,文本编辑字段的文本对齐将使用QtCore模块的Qt命名空间的Alignment标志进行更改。
选项“选项”
下一个选项是“运行”子选项。这可以在脚本执行部分的文本编辑字段中直接实现 Python 标准库的一些功能。这将非常清楚地展示 Python 解释器的本质。我们将把文本字段的内容保存到文件中,并使用subprocess模块运行它。我们还将实现之前描述的线程的另一种构建。让我们实施以下步骤:
- 首先,我们需要在
u_tools.py文件中添加一些行。通过添加QObject类来更改import部分的行,如下所示:
- 在 PyQt5 的
u_tools.py文件的情况下,添加以下行:
...
from PyQt5.QtCore import QThread, QObject, QMutex
...
- 并且,在 PySide2 的
u_tools.py文件的情况下,添加以下行:
...
from PySide2.QtCore import QThread, QObject, QMutex
...
- 添加将实现功能的
RunThread类:
...
class RunThread(QObject):
sig1 = app_signal(object, object, str)
def __init__(self, parent=None, datas=None):
super(RunThread, self).__init__(parent)
self.datas = datas
def on_run_code(self):
try:
import subprocess
wf = open("temp.py", "w")
wf.write(self.datas)
wf.close()
sp = subprocess.Popen(
["python", "temp.py"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out = sp.communicate()
self.sig1.emit(out[0].decode("utf-8"),
out[1].decode("utf-8"), '')
except Exception as err:
self.sig1.emit('', '', str(err))
...
这是一个简单的类,继承自QtCore模块的QObject类。当on_run_code()函数被调用时,它将写入文件并使用子进程运行文件。
- 将
run_code()函数添加到u_tools.py文件的UTools类中,如下所示:
...
...
def run_code(self, datas=None):
self.run_thread = QThread()
self.run_obj = RunThread(datas=datas)
self.run_obj.moveToThread(self.run_thread)
self.run_thread.started.connect(self.run_obj.on_run_code)
self.run_thread.start()
return (self.run_thread, self.run_obj)
...
...
此函数与之前创建的线程相关联,使用QObject类的moveToThread()方法。重要的是要注意,我们可以看到需要使用线程的started()信号来启动RunThread类的on_run_code()函数。
现在,我们可以在u_app.py文件的UApp类中实现此选项。我们需要在u_app.py文件的import部分添加标准库的 time 模块,用于处理时间和数据,如下所示:
- 将
time模块添加到u_app.py文件中:
...
import time
...
- 现在,我们可以将新选项添加到
UApp类的options()函数中:
...
...
def options(self, action):
...
if action.text() == "Run":
action.setEnabled(False)
datas = self.text_edit.toPlainText()
try:
self.text_edit.append(
"\n\n\n\n\nRESULT -----------> %s\n" %
time.strftime("%Y.%m.%d %H:%M:%S"))
runs = self.run_code(datas=datas)
def to_field(sto, ste, er):
if er == '':
self.text_edit.append(
str(sto) + "\n" + str(ste))
else:
self.stat_bar.showMessage(er)
runs[1].sig1.connect(
to_field, QtCore.Qt.QueuedConnection)
runs[0].quit()
def on_stop():
action.setEnabled(True)
runs[0].finished.connect(on_stop)
except Exception as err:
self.stat_bar.showMessage(str(err))
...
...
在此选项中,我们禁用了顶部面板菜单中的“运行”项。然后,我们从文本字段中检索文本,从u_tools.py文件中调用UTools类的函数,并接收一个包含线程和所用类的元组。我们创建了两个嵌套函数来接收信号。第一个接收来自RunThread类的信号,第二个接收具有finished()信号的线程的信号。
配置选项
“配置”项是可选的,读者可以添加他们自己的喜欢的功能。使用此选项,我们将提供有关 Python 及其已安装包的一些信息。为此,在App/App_PyQt5/和App/App_PySide2/目录中创建u_widget.py文件,并在其中包含用于应用程序中附加信息任务的控件:
- 我们需要向此文件的
import部分添加以下行:
- 在 PyQt5 的
u_widget.py文件的情况下,添加以下内容:
...
from PyQt5 import QtWidgets
from u_style import UWid, UTextEd, UComBox, UListV
...
- 并且,在 PySide2 的
u_widget.py文件的情况下,添加以下内容:
...
from PySide2 import QtWidgets
from u_style import UWid, UTextEd, UComBox, UListV
...
唯一的区别是导入QtWidgets模块。
- 现在将
UWidget类添加到这些u_widget.py文件中,如下所示:
...
class UWidget(UWid):
def __init__(self, parent=None):
super(UWidget, self).__init__(parent)
self.setWindowOpacity(0.95)
self.infotxt = UTextEd(self)
self.infocomb = UComBox(self)
self.infocomb.setView(UListV())
self.infolay = QtWidgets.QGridLayout()
self.infolay.addWidget(self.infotxt, 0, 0, 1, 1)
self.infolay.addWidget(self.infocomb, 1, 0, 1, 1)
self.infolay.setSpacing(0)
self.infolay.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.infolay)
...
用于小部件的简单类取决于任务。
现在将行添加到应用程序的 u_app.py 文件中:
- 在
import部分,添加将导入小部件的行,如下所示:
...
from u_widget import UWidget
...
- 然后,向
UApp类的options()函数添加选项,以显示有关使用的 Python 版本的信息:
...
...
def options(self, action):
...
if action.text() == "Configuration":
def get_info():
if self.uwid1.infocomb.currentIndex() == 0:
try:
condinf = subprocess.Popen(
["conda", "list"],
stdout=subprocess.PIPE)
conp = condinf.communicate()
self.uwid1.infotxt.setText(
conp[0].decode("utf-8"))
except Exception as err:
self.uwid1.infotxt.setText(str(err))
if self.uwid1.infocomb.currentIndex() == 1:
try:
condinf = subprocess.Popen(
["pip", "list"],
stdout=subprocess.PIPE)
conp = condinf.communicate()
self.uwid1.infotxt.setText(
"""Platform: %s\nPython %s version
\nPython path list: %s
\n\nRecursion limit: %s
\nFilesystem encoding: %s
\nDefault encoding: %s
\nAvailable installed packages:
\n\n%s""" %
(sys.platform, sys.version,
sys.path,
sys.getrecursionlimit(),
sys.getfilesystemencoding(),
sys.getdefaultencoding(),
conp[0].decode("utf-8")))
except Exception as err:
self.uwid1.infotxt.setText(str(err))
self.uwid1 = UWidget()
self.uwid1.setWindowTitle("Configuration")
self.uwid1.infocomb.addItems(["conda", "pip"])
self.uwid1.infotxt.setReadOnly(True)
self.uwid1.show()
self.uwid1.infocomb.activated.connect(get_info)
...
...
选择此选项将显示带有窗口标题的导入小部件。将选项添加到组合框中,以便使用您选择的子进程运行命令。如果已安装并使用 Anaconda 与此应用程序,将显示 conda 软件包,或者可以使用 pip 选项检查 Python 软件包。
帮助选项
你需要完成的下一步是在顶部面板中添加一个 Help 选项。我们将使用 Qt 库的一些网页功能来演示附加功能。首先,Online Help 子选项将设置 HTML 标签,然后加载 URL。让我们实现以下步骤:
- 首先,我们需要向
u_widget.py文件中添加一些行。在import部分,按照以下方式添加以下行:
- 在 PyQt5 的
u_widget.py文件的情况下,添加以下内容:
...
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWebEngineWidgets import QWebEngineSettings
...
- 并且,在 PySide2 的
u_widget.py文件的情况下,添加以下内容:
...
from PySide2.QtWebEngineWidgets import QWebEngineView
from PySide2.QtWebEngineWidgets import QWebEngineSettings
...
QtWebEngineWidgets 模块通过提供表示小部件内容和附加设置的类,在 Qt 库中实现了网页功能。
- 现在,我们需要向
UWidget类添加以下行:
...
class UWidget(UWid):
def __init__(self, parent=None):
...
self.wview = QWebEngineView(self)
self.wview.settings().setAttribute(
QWebEngineSettings.PluginsEnabled, True)
self.wview.settings().setAttribute(
QWebEngineSettings.AutoLoadImages, True)
self.wview.settings().setAttribute(
QWebEngineSettings.JavascriptEnabled, True)
self.wview.setVisible(False)
...
self.infolay = QtWidgets.QGridLayout()
self.infolay.addWidget(self.wview, 0, 0, 1, 1)
self.infolay.addWidget(self.infotxt, 0, 0, 1, 1)
self.infolay.addWidget(self.infocomb, 1, 0, 1, 1)
...
...
将带有设置的 **QWebEngineView** 添加到布局中的第一个位置。这也使此视图不可见。
- 为了在应用程序中实现
Help选项,我们需要向u_app.py文件中的UApp类添加信号和函数。
向 UApp 类添加信号,如下所示:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.mb3.triggered.connect(self.data)
self.mb4.triggered.connect(self.options)
self.mb5.triggered.connect(self.on_help)
...
...
...
此信号将在选择 Help 选项时连接到 on_help() 函数。现在,我们需要向 UApp 类添加 on_help() 函数。
- 添加
on_help()函数和第一个Online Help选项,如下所示:
...
...
def on_help(self, action):
if action.text() == "Online Help":
self.uwid2 = UWidget()
self.uwid2.setWindowTitle("Online Help")
self.uwid2.infocomb.setVisible(False)
self.uwid2.infotxt.setReadOnly(True)
self.uwid2.infotxt.setVisible(False)
self.uwid2.wview.setVisible(True)
html = open("help.html", "r").read()
self.uwid2.wview.setHtml(html)
self.uwid2.show()
...
此选项选择将设置来自文件的 HTML 并显示小部件。help.html 文件可以是任何创建的 HTML 文件,它代表指向某些有用资源的链接。
- 现在,通过添加
Documentation选项来完成on_help()函数:
...
...
def on_help(self, action):
...
if action.text() == "Documentation":
def get_docs():
if self.uwid3.infocomb.currentIndex() == 0:
try:
self.uwid3.wview.load(
QtCore.QUrl(
"https://docs.python.org/3/"))
except Exception as err:
self.stat_bar.showMessage(str(err))
if self.uwid3.infocomb.currentIndex() == 1:
try:
self.uwid3.wview.load(
QtCore.QUrl(
"https://www.riverbankcomputing.com/static/Docs/PyQt5/"))
except Exception as err:
self.stat_bar.showMessage(str(err))
if self.uwid3.infocomb.currentIndex() == 2:
try:
self.uwid3.wview.load(
QtCore.QUrl(
"https://doc.qt.io/qtforpython/index.html"))
except Exception as err:
self.stat_bar.showMessage(str(err))
self.uwid3 = UWidget()
self.uwid3.setWindowTitle("Documentation")
self.uwid3.infocomb.addItems(
["Python", "PyQt5", "PySide2"])
self.uwid3.infotxt.setReadOnly(True)
self.uwid3.infotxt.setVisible(False)
self.uwid3.wview.setVisible(True)
self.uwid3.show()
self.uwid3.infocomb.activated.connect(get_docs)
...
...
此选项将根据组合框中选择的选项加载 URL 并在控件中可视化这些来源。这些示例是我们之前没有涵盖的使用案例,例如 Qt 的网页功能,建议您使用相关文档了解这些类。此外,根据使用的环境,可能还需要额外的配置和设置。
该 help.html 文件可以在本书的 GitHub 仓库中找到:github.com/PacktPublishing/Hands-On-Qt-for-Python-Developers/tree/master/Chapter17/App/App_PyQt5。
可视化标签页
我们将通过添加一个查看应用程序使用的数据的可能性的简单示例来整合这本书的材料,并填充Visualization标签组件。这是一个数据可视化的演示,可以随时进一步改进。为了创建这个数据可视化,我们将使用一个现有的 CSV 文件,并使用其某一列的值。让我们实施以下步骤:
- 打开
u_tools.py文件,并在所有使用线程实现的类之后添加以下行:
...
class PaintThread(QThread):
sig1 = app_signal(object, str)
def __init__(self, parent=None):
super(PaintThread, self).__init__(parent)
def on_source(self, datas):
self.datas = datas
def run(self):
try:
import pandas
df = pandas.read_csv("data/bigtests.csv",
chunksize=1000,
engine="python")
r = self.datas[1]
h = self.datas[1] / 1000
for ch in df:
wx = self.datas[0] / 1000000
w = ch["User_Name"].values[777] * wx
xy = (float(r), float(w))
self.sig1.emit(xy, '')
time.sleep(0.05)
r -= h
if self.isFinished():
self.quit()
except Exception as err:
self.sig1.emit('', str(err))
if self.isFinished():
self.quit()
...
这个PaintThread类将实现一个线程,该线程将使用 pandas 读取数据,将接收到的数据转换成可以从中解释位置的格式,并将这些值发出以在应用程序的图形场景上实现。
- 将信号添加到
u_tools.py文件中的UTools类:
...
class UTools(object):
...
paint_sig = app_signal(list)
...
...
此信号将用于向PaintThread类发出数据,例如宽度和高度。
- 现在,将
draws()函数添加到UTools类中。这将操作并与PaintThread类通信:
...
...
def draws(self, w=None, h=None):
datas = [w, h]
self.paint_thread = PaintThread()
self.paint_sig.connect(self.paint_thread.on_source)
self.paint_sig.emit(datas)
self.paint_thread.start()
return self.paint_thread
...
此函数将启动线程,使其在图形场景上绘制,同时发出从PaintThread类检索到的宽度和高度的数据。这种线程的构建与之前的构建类似。
- 现在,我们需要打开
u_app.py文件,通过添加一些行来完成此任务。让我们将场景、视图和画家添加到UApp类的__init__()函数中:
...
class UApp(UWindow, UTools):
def __init__(self, parent=None):
...
self.gscene = QtWidgets.QGraphicsScene()
self.gview = UGraphView(self.twid2)
self.painter = QtGui.QPainter()
self.gvlay = QtWidgets.QGridLayout()
self.gvlay.addWidget(self.gview, 0, 0, 1, 1)
self.gvlay.setContentsMargins(0, 0, 0, 0)
self.twid2.setLayout(self.gvlay)
...
self.push_but2.clicked.connect(self.vis)
...
...
...
这将声明图形场景、图形视图、可用的画家,并将一个带有视图的场景添加到第二个标签小部件中,并使用网格布局排列这些元素。我们还需要更改第二个按钮信号连接的调用函数。
- 现在,将
vis()函数添加到UApp类中:
...
...
def vis(self):
self.tabwid.setCurrentIndex(1)
desktop = QtWidgets.QApplication.desktop()
self.setGeometry(desktop.availableGeometry())
self.visualize()
...
...
此函数将设置第二个标签小部件为当前标签小部件。应用程序的几何形状将更改为桌面设备的可用大小。我们将运行此函数来可视化数据。
- 最后,将
visualize()函数添加到UApp类中:
...
...
def visualize(self):
self.gscene.clear()
self.gview.resetCachedContent()
self.gview.setScene(self.gscene)
self.gview.setSceneRect(self.gscene.sceneRect())
self.pen = QtGui.QPen()
self.scw = float(self.tabwid.currentWidget().width() - 30)
self.sch = float(self.tabwid.currentWidget().height() - 30)
try:
dline = self.draws(w=self.scw, h=self.sch)
def to_line(xy, er):
if er == '':
color = QtGui.QColor("#00D9FF")
cmyk = color.toCmyk()
c = cmyk.cyanF()
m = cmyk.magentaF() * float(1/xy[1])
y = cmyk.yellowF() * float(1/xy[1])
k = cmyk.blackF() * float(1/xy[1])
a = cmyk.alphaF()
color.setCmykF(c, m, y, k, a)
self.pen.setColor(color)
self.gscene.addLine(QtCore.QLineF(xy[1],
self.sch, xy[1], xy[0]), self.pen)
else:
self.stat_bar.showMessage(self.actx + ' ' + er)
dline.sig1.connect(to_line, QtCore.Qt.QueuedConnection)
except Exception as err:
self.stat_bar.showMessage(self.actx + ' ' + str(err))
...
...
此函数将使用图形视图和图形场景在标签小部件上可视化数据。将使用在笔中指定的颜色、位置和从数据值解释的高度在场景中添加线条。在点击“确定”后,我们可以看到以下结果:

由于我们只有线性数据,可视化将相对普通,但如果某些数据要使用各种值而不是这种线性形式,我们将得到不同的结果。
部署到嵌入式设备
Qt 库提供了一套丰富的工具集,支持在大多数现代平台和嵌入式设备上实现 GUI 应用程序。例如,在 Linux 系统上,我们可以轻松创建桌面文件并启动此文件,如果需要,从桌面工作区或任何喜欢的文件夹中运行应用程序。uapp.desktop 文件看起来像以下示例,它实现了应用程序的桌面入口:
[Desktop Entry]
Path=/Path/to/the/App/App_PyQt5/
Exec=/Path/to/the/installed/python /Path/to/the/App/App_PyQt5/u_app.py
Icon=/Path/To/the/App/App_PyQt5/Icons/python1.png
Name=UAPP
StartupNotify=true
Terminal=false
Type=Application
在绑定使用方面,PyQt5 可以更改为 PySide2。在 Windows 系统上,这可以通过使用第三方 Python 包(如 PyInstaller 和 py2exe)来实现,这些包将 Python 脚本转换为可执行文件(.exe 文件)并相应地实现功能。此外,PyInstaller 工具也可以用于 macOS X 系统。建议您通过访问 pythonhosted.org/PyInstaller/ 了解 PyInstaller 相关文档。这些工具提供简单的操作,以便快速轻松地创建可执行文件。另一种情况是部署应用程序到移动设备。可以帮助完成这些任务的工具和库通常在商业许可下提供,实际上,PyQt 和 PySide 绑定并不非常适合这些任务。
实现应用程序移动版本的一个更好的方法是使用 Kivy 框架、Toga 跨平台 GUI 工具包等,这些框架专门从事移动开发。官方 Qt 源代码在商业许可下提供嵌入式工具和解决方案,有助于在 Android 和 iOS 移动平台上构建和部署 Qt GUI 应用程序。顺便提一下,基于 QML 的应用程序可以很容易地使用 Qt 实现,例如在 第一章 “Python 和 Qt 简介”中提供的示例。
www.riverbankcomputing.com 提供了带有 pyqtdeploy 库的 PyQt5 GUI 移动解决方案。这实现了 PyQt5 应用程序在 iOS 和 Android 平台上的部署。pyqtdeploy 库是为了将 Python GUI 应用程序、Python 解释器、Python 标准库、Python C 扩展和第三方扩展和包转换为单一、针对特定目标的可执行文件,该文件可以在大多数流行的桌面和移动平台上运行。pyqtdeploy 机制在 BSD 许可下发布,并将详细介绍。要使用它,我们需要在包含 PyQt5 绑定的 Python 安装上使用 pip 安装此包:
- 使用 Python 3.x 版本和 PyQt5 通过
pip在 Anaconda 中安装pyqtdeploy,如下所示:
> pip install pyqtdeploy
- 然后,我们需要在
App/文件夹中(可选)创建pyqtdeploy项目,在命令行/Terminal 中输入以下命令:
> cd Path/to/the/App
> pyqtdeploy pqtd.pdy
pqtd是项目的名称,pqtd.pdy是这个项目的文件。当点击Enter按钮时,pyqtdeploy GUI 窗口将显示,可以选择所需的参数,如下所示:
-
名称:将要创建的应用程序可执行文件的名字。
-
主脚本文件:将被用于调用此应用程序的可执行 Python 脚本文件的文件名。
-
入口点:基于 Setuptools 的应用程序的入口点,如果指定了主脚本文件,则不需要指定。
-
sys.path:用于指定
sys.path的附加路径,例如应用程序目录、ZIP 文件和 EGG。列表包含路径字符串,例如['/Path/to/the/App', '/path/to/the/App/App_PyQt5', '/path/to/the/App/App_PyQt5/qmls', ...]等等。
- 现在我们需要点击 Scan...按钮,选择
App/App_PyQt5/目录,并点击 Include all。我们将得到类似以下截图的应用程序目录树:

- 取消勾选此树中的
data文件夹。然后,我们需要定义将要使用的 PyQt5 模块。为此,选择PyQt Modules标签并选择在应用程序中使用过的模块,类似于以下内容:

- 其中一些是通过提示选择的,这很容易做到。转到 Standard Library 标签并选择所有将要使用的 Python 标准库模块和包,如图所示:

我们可以选择全部并取消勾选sysconfig模块。
- 然后,转到 Other Packages 标签并选择应用程序所需的附加包。正如我们回忆的那样,有
pymysql、couchdb等。为此,点击 Packages Directory 部分顶部,打开将扫描包的目录(通常,这是/Path/to/the/installed/Python/site-packages),查看可用的包,并选择所需的包。然后,点击 Scan,site-packages/directory的所有包都将显示出来。我们需要选择使用的包,如pandas、pymysql、psycopg2、pymongo和couchdb:

- 在位置标签中,我们将配置主机和目标 Python 位置,类似于以下内容:

您的路径将与已安装的 Python 解释器目录相关。现在,我们需要通过点击文件菜单中的 Save 选项来保存之前的操作到 XML 文档。此文件将保存到App/文件夹,文件名为pqtd.pdy。
- 因此,现在特征已经选择并保存,我们需要使用 cmd/Terminal 中的命令来构建此项目,如下所示:
> cd Path/to/the/App/pqtd.pdy
> pyqtdeploy-build pqtd.pdy --target=android-32
可以与--target选项一起使用的架构有android-32、android-64、ios-64、linux-64、macos-64、win-32和win-64平台。现在生成的包可以用于在不同平台上进一步部署。
测试
任何完成的应用程序都需要测试其内部的工作部分和组件。在本节中,我们将介绍使用 Qt 库工具(如QtTest模块)创建的应用程序的单元测试。此外,此模块还允许对 GUI 进行测试扩展。Python 标准库单元测试框架unittest或第三方工具,如pytest,也可以使用。在实际测试中,通常将unittest模块与QtTest模块结合使用。PyQt5 的QSignalSpy类可以内省信号的发射。
QtTest
此模块提供了 Qt 应用程序和库的单元测试实现。要使用此模块,我们需要将以下导入语句添加到将使用测试函数的文件中。最佳做法是在应用程序的App/App_PyQt5/和App/App_PySide2/目录中创建u_tests.py文件,并分别添加以下import部分,如下所示:
- 在 PyQt5 的
u_tests.py文件中,添加以下内容:
...
from PyQt5 import QtTest
...
- 在 PySide2 的
u_tests.py文件中,添加以下内容:
...
from PySide2 import QtTest
...
QtTest模块提供了QTest类,可用于应用程序的单元测试。需要注意的是,PySide2 的QTest命名空间和 PyQt5 的QTest类是不同的。PySide2 的QTest命名空间实现了用于单元测试基于 Qt 的应用程序和库的框架功能,并扩展了 GUI。PyQt5 的QTest类没有实现完整的 Qt 单元测试框架,并假设将使用 Python 的stdlib unittest模块与QTest一起使用。因此,PyQt5 的QTest不能实例化。
QTest (PySide2)
此命名空间实现了 Qt 库的单元测试框架。声明语法如下:
test = QtTest.QTest()
QTest通过以下常用函数改进了功能。完整的列表可以在官方 PySide2 文档中找到(doc.qt.io/qtforpython/PySide2/QtTest/index.html):
-
test.asciiToKey("ascii"): 将参数中指定的 ASCII 字符键值转换为 Qt 键值。 -
test.currentAppName(): 返回当前执行的二进制文件名称。 -
test.currentDataTag(): 返回当前测试数据名称。 -
test.currentTestFailed(): 如果测试函数失败,则返回True。 -
test.currentTestFunction(): 这将返回当前测试函数的名称。 -
test.ignoreMessage(QtMsgType, message): 这忽略qDebug()、qInfo()或qWarning()消息。在全局类型(第一个参数)的消息(第二个参数)返回到输出时,它将从测试日志中删除。如果测试完成且消息未在输出中显示,它将被附加到测试日志中。 -
test.keyToAscii(key): 这将参数中指定的 Qt 键值转换为 ASCII 字符键值。 -
test.qExtractTestData("dirName"): 这从资源中提取指定在参数中的目录到磁盘。 -
test.setBenchmarkResult(float, QTest.QBenchmarkMetric): 这设置基准结果(第一个参数),带有指标(第二个参数),该指标指定 Qt 测试应该如何解释与该测试函数相关的结果。 -
test.toPrettyCString(str, int): 这返回相同的QtCore.QByteArray,但只包含 ASCII 字符。
QTest (PyQt5)
此类包含使 PyQt5 应用程序能够进行单元测试的函数。QTest 类通过以下常用函数提高了功能。完整的列表可以在官方 PyQt5 文档中找到 (www.riverbankcomputing.com/static/Docs/PyQt5/):
test.keyClick(QtWidgets.QWidget, QtCore.Qt.Key, QtCore.Qt.KeyboardModifiers, int): 这模拟在控件(第一个参数)上点击一个键(第二个参数),带有修饰符(第三个参数),并带有测试延迟(第四个参数)以毫秒为单位。
test.keyClicks(QtWidgets.QWidget, str, QtCore.Qt.KeyboardModifiers, int): 这模拟在控件(第一个参数)上按下一个键序列(第二个参数),带有修饰符(第三个参数),并带有测试延迟(第四个参数)以毫秒为单位。
test.keyEvent(QtTest.QTest.KeyAction, QtWidgets.QWidget, QtCore.Qt.Key, QtCore.Qt.KeyboardModifiers, int): 这向控件(第二个参数)发送一个 Qt 键事件,带有键(第三个参数)和相关的动作(第一个参数),以及修饰符(第四个参数),以及测试延迟(第五个参数)以毫秒为单位。
test.keyPress(QtWidgets.QWidget, QtCore.Qt.Key, QtCore.Qt.KeyboardModifiers, int): 这模拟在控件(第一个参数)上按下一个键(第二个参数),带有修饰符(第三个参数),并带有测试延迟(第四个参数)以毫秒为单位。
test.keyRelease(QtWidgets.QWidget, QtCore.Qt.Key, QtCore.Qt.KeyboardModifiers, int): 这模拟在控件(第一个参数)上释放一个键(第二个参数),带有修饰符(第三个参数),并带有测试延迟(第四个参数)以毫秒为单位。
test.mouseClick(QtWidgets.QWidget, QtCore.Qt.MouseButton, QtCore.Qt.KeyboardModifiers, QtCore.QPoint, int): 这模拟了在控件(第一个参数)上使用修饰符(第三个参数)点击鼠标按钮(第二个参数),并带有测试延迟(第五个参数)以毫秒为单位。点击的位置(第四个参数),默认情况下,是控件的中心。
test.mouseDClick(QtWidgets.QWidget, QtCore.Qt.MouseButton, QtCore.Qt.KeyboardModifiers, QtCore.QPoint, int): 这模拟了在控件(第一个参数)上使用修饰符(第三个参数)双击鼠标按钮(第二个参数),并带有测试延迟(第五个参数)以毫秒为单位。默认情况下,位置(第四个参数)是控件的中心。
test.mouseMove(QtWidgets.QWidget, QtCore.QPoint, int): 这将鼠标指针移动到控件(第一个参数),带有测试延迟(第五个参数)以毫秒为单位。它将被移动到位置(第四个参数),默认情况下,是控件的中心。
test.mouseRelease(QtWidgets.QWidget, QtCore.Qt.MouseButton, QtCore.Qt.KeyboardModifiers, QtCore.QPoint, int): 这模拟了在控件(第一个参数)上使用修饰符(第三个参数)释放鼠标按钮(第二个参数),并带有测试延迟(第五个参数)以毫秒为单位。默认情况下,位置(第四个参数)是控件的中心。
test.qSleep(int): 这将暂停一定数量的毫秒,由参数指定,阻塞此测试的执行。
test.qWait(int): 这等待一定数量的毫秒,由参数指定;事件将被处理,并且此测试将保持对事件的响应。
test.qWaitForWindowActive(QtWidgets.QWidget, int): 这等待一定数量的毫秒(第二个参数),直到控件的窗口(第一个参数)变得活跃。
test.qWaitForWindowExposed(QtWidgets.QWidget, int): 这等待一定数量的毫秒(第二个参数),直到控件的窗口(第一个参数)被暴露。
test.touchEvent(QtWidgets.QWidget, QtGui.QTouchDevice): 这为设备(第二个参数)创建并返回一个QtTest.QTest.QTouchEventSequence类型的序列,以模拟控件(第一个参数)的事件。
QTest 示例
如我们所见,PyQt5 绑定仅实现了 Qt 测试框架的一部分。GUI 应用的测试可以通过 PyQt5 相关的简单示例构建来演示,这也可以与 PySide2 绑定一起使用。需要注意的是,QTest (PyQt5)部分中描述的方法对 PySide2 绑定也是可用的。通过一个简单的示例,将以下行添加到u_tests.py文件的import部分:
- 在 PyQt5 的
u_tests.py文件中,添加以下内容:
...
from PyQt5.QtWidgets import QApplication
from PyQt5.Qt import Qt
from u_window import UWindow
import unittest
...
- 在 PySide2 的
u_tests.py文件中,添加以下内容:
...
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import Qt
from u_window import UWindow
import unittest
...
测试元素将是实现 GUI 应用程序窗口的UWindow类的元素。我们可以在这一行添加任何小部件。
- 现在将继承 Python 标准库
unittest模块的TestCase基类的类添加到u_tests.py文件中。
将UTests类添加到u_tests.py文件中,通过在文件中添加调用unittest模块的main()函数的行来完成文件:
...
class UTests(unittest.TestCase):
def setUp(self):
self.app = QApplication([])
self.uwin = UWindow()
self.menu = self.uwin.menuBar()
def test_menu(self):
self.assertEqual(self.uwin.mb1.title(), "&File")
self.menu.actions()[0].trigger()
QtTest.QTest.keyPress(self.uwin, Qt.Key_Enter,
Qt.ControlModifier)
return
def tear_down(self):
pass
unittest.main()
...
setUp()方法使用启动测试所需的实例操作,例如应用程序、导入的UWindow类的类实例以及窗口菜单栏。test_menu()函数实现并完成这个测试,通过tearDown()。
- 现在,我们可以在 cmd/Terminal 中通过输入以下命令来运行
u_tests.py文件:
> python u_tests.py -v
我们将看到类似以下的输出:

我们可以用这种方式测试任何小部件,并根据我们的任务增强当前的结构。
概述
本章完成了本书中创建的 GUI 应用程序。这个应用程序并不假装是解决特殊任务的专用工具,但它可以很容易地扩展和现代化,适用于今天几乎所有常用的 GUI 实现。本书之前已经描述了几乎所有有用的图形元素。将 GUI 部署到各种平台和架构的过程并不容易,需要额外的材料和示例知识。也可能出现一些限制,这取决于设备的版本和支持的环境。因此,建议学习与使用设备相关的需求。测试应用程序需要彻底理解可以测试的元素、为什么以及如何测试。正确实施测试可以帮助避免与应用程序开发相关的大量错误和错误。
本章完成了这本书的内容,读者必须知道接下来要学习什么。此外,Python 的世界非常广阔。


浙公网安备 33010602011771号