PyQt5 教程及示例:使用 Python 中的 PyQt 设计 GUI

什么是 PyQt?

PyQt 是开源小部件工具包 Qt 的 Python 绑定,它也可用作跨平台应用程序开发框架。Qt 是一个流行的 C++ 框架,用于为所有主要的桌面、移动和嵌入式平台(支持 Linux、Windows、MacOS、Android、iOS、Raspberry Pi 等)编写 GUI 应用程序。

PyQt 是由总部位于英国的公司 Riverbank Computing 开发和维护的免费软件,而 Qt 由一家名为 The Qt Company 的芬兰公司开发。

PyQT 的特点

以下是 PyQt 的重要功能

学习 PyQt,它包含六百多个类,涵盖了一系列功能,例如

  • 图形用户界面
  • SQL 数据库
  • Web 工具包
  • XML 处理
  • 网络

这些功能可以组合起来创建高级 UI 以及独立应用程序。所有行业的许多大公司都在使用 Qt。例如 LG、Mercedes、AMD、Panasonic、Harman 等。

PyQt 版本

PyQt 有两个版本:PyQt4 和 PyQt5。PyQt4 为 Qt 框架的 4.x 和 5.x 版本提供了绑定代码,而 PyQt5 仅为 5.x 版本提供绑定。因此,PyQt5 不向后兼容旧版本的已弃用模块。在此 Qt GUI 教程中,将使用 PyQt5 来演示示例。除了这两个版本之外,

Riverbank Computing 还提供 PyQt3D,即 Qt3D 框架的 Python 绑定。Qt3D 是一个应用程序框架,用于创建具有 2D/3D 渲染的实时模拟系统。

如何安装 PyQt5

在本 PyQt5 教程中,我们将介绍安装 PyQt 的两种方法

  • 使用 Wheel 文件
  • 从源代码构建和安装

Qt(发音为 cute)是一个复杂的系统,PyQt 代码库的底层包含已编译的 C++ 和 Python 代码。因此,与许多其他 Python 库相比,从源代码构建和安装它是一个复杂的过程。但是,您可以使用 wheel 轻松安装 PyQt5。

使用 wheel 进行安装

Wheel 是新的标准 Python 打包和分发格式。简单来说,wheel 是一个具有特殊名称和 .whl 文件扩展名的 ZIP 存档。可以使用 pip(Python 的包管理器)安装 wheel,pip 默认包含在最新版本的 Python 中。

因此,如果您安装了 Python 3.4 或更高版本,则已拥有 pip。但是,如果您使用的是旧版本 Python,则必须先下载并安装 pip,然后再继续。您可以在此链接上搜索相关说明:https://pypi.ac.cn/project/pip/

要安装 PyQt5,

第 1 步) 打开命令提示符。
在 Windows 计算机上打开命令提示符或 PowerShell。

install PyQt5

第 2 步) 输入以下命令。

 pip install PyQt5

第 3 步) 安装成功。
此 PyQt5 教程中的此步骤将下载 PyQt5 whl 包(约 50 MB)并将其安装在您的系统上。

install PyQt5

或者,您也可以为安装在计算机上的 Python 版本下载 Windows 二进制文件。

完成后,继续本 PyQt5 教程的下一部分,编写您的第一个 GUI 应用程序。

PyQt 基本概念和程序

现在您已在计算机上成功安装了 PyQt5,您可以开始编写 Python GUI 设计应用程序了。

在本 PyQt5 教程中,让我们从一个简单的应用程序开始,它将在屏幕上显示一个空窗口。

启动您的 python IDLE 并输入以下内容

程序 1

import sys
from PyQt5.QtWidgets import QApplication, QWidget
if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = QWidget()
    w.resize(300,300)
    w.setWindowTitle("Guru99")
    w.show()
    sys.exit(app.exec_())

将其另存为 app.py(名称无关紧要),然后按 F5 运行程序。或者,只需双击保存的文件即可启动应用程序。如果您一切顺利,将打开一个新窗口,标题为 Guru99,如下图所示。

Basic PyQt Concepts

太棒了!它有效。虽然不多,但足以掌握基本知识。现在在本 PyQt 教程中,让我们详细看看您程序中的每一行代码。

from PyQt5.QtWidgets import QApplication, QWidget

此语句将创建 GUI 所需的所有模块导入到当前命名空间。QtWidgets 模块包含您将在本 Python Qt 教程中使用的所有主要小部件。

app = QApplication(sys.argv)

在这里,您正在创建一个 QApplication 类的对象。这是 PyQt5 的必需步骤;每个 UI 应用程序都必须创建一个 QApplication 实例,作为应用程序的入口点。如果未创建,将显示错误。

sys.argv 是您可以通过命令行将应用程序启动到应用程序的命令行参数列表,或者在自动化界面时使用。

在此 PyQt5 示例中,您没有向 QApplications 传递任何参数。因此,您也可以用下面的代码替换它,甚至不需要导入 sys 模块。

app = QApplication([])
w = QWidget()

接下来,我们创建一个 QWidget 类的对象。QWidget 是 Qt 中所有 UI 对象的基类,实际上您在应用程序中看到的几乎所有内容都是一个小部件。这包括对话框、文本、按钮等。允许您设计复杂用户界面的特性是小部件可以嵌套,也就是说,您可以在一个小部件内放置另一个小部件,而该小部件又位于另一个小部件内。您将在下一节中看到这一点。

w.resize(300,300)

QWidget 类的 resize 方法允许您设置任何小部件的尺寸。在这种情况下,您已将窗口大小调整为 300px x 300px。

在这里,您应该记住,小部件可以嵌套在一起,最外层的小部件(即没有父小部件的小部件)称为窗口。

w.setWindowTitle("Guru99")

setWindowTitle() 方法允许您传递一个字符串作为参数,该参数将窗口标题设置为您传递的字符串。在 PyQt5 示例中,标题栏将显示 Guru99。

w.show()

show() 仅将小部件显示在监视器屏幕上。

sys.exit(app.exec_())

app.exec_() 方法启动 Qt/C++ 事件循环。如您所知,PyQt 主要用 C++ 编写,并使用事件循环机制来实现并行执行。app.exec_() 将控件交给 Qt,Qt 仅在用户从 GUI 中关闭应用程序时退出。这就是为什么 Ctrl+C 不会像其他 python 程序那样退出应用程序的原因。由于 Qt 控制着应用程序,因此 Python 事件不会被处理,除非我们在应用程序内部进行设置。另请注意,exec 方法的名称中有一个下划线;这是因为 exec() 已经是 Python 中的一个关键字,下划线解决了命名冲突。

超越空窗口

在上一个部分中,您学习了如何创建基本的 Qt 小部件。现在是时候创建一些更复杂、用户可以真正交互的界面了。再次启动您的 IDLE 并输入以下内容。

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QMessageBox

def dialog():
    mbox = QMessageBox()

    mbox.setText("Your allegiance has been noted")
    mbox.setDetailedText("You are now a disciple and subject of the all-knowing Guru")
    mbox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
            
    mbox.exec_()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = QWidget()
    w.resize(300,300)
    w.setWindowTitle("Guru99")
    
    label = QLabel(w)
    label.setText("Behold the Guru, Guru99")
    label.move(100,130)
    label.show()

    btn = QPushButton(w)
    btn.setText('Beheld')
    btn.move(110,150)
    btn.show()
    btn.clicked.connect(dialog)

    
    w.show()
    sys.exit(app.exec_())

将文件另存为 appone.py 或任何您喜欢的名称,然后按 F5 运行程序。如果您没有犯任何错误,IDLE 将打开一个新窗口,其中包含一些文本和一个按钮,如下所示。

Beyond empty Windows

  1. 一旦您点击第一个窗口中的按钮,将弹出一个新的消息框,其中包含您写入的文本。
  2. 您现在可以点击“隐藏详细信息”/“显示详细信息”按钮来切换其他文本的可见性。

如您所见,由于我们没有为消息框设置任何窗口标题,因此 Python 本身提供了一个默认标题。

既然它有效,让我们看看您添加到先前 PyQt5 示例中的额外代码。

from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QMessageBox

这会导入您在 PyQt5 示例中使用的一些额外小部件,即 QLabel、QPushButton 和 QMessageBox。

def dialog():
    mbox = QMessageBox()

    mbox.setText("Your allegiance has been noted")
    mbox.setDetailedText("You are now a disciple and subject of the all-knowing Guru")
    mbox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
            
    mbox.exec_()

在这里,您定义了一个名为 dialog 的方法,该方法创建了一个消息框小部件,并为按钮和其他字段设置了一些文本。

当特定小部件(在此例中为 btn PushButton)中的按钮被按下时,对话框方法将从程序的 main 块调用。在该按钮上触发的点击事件会导致此函数执行。这样的函数在 Qt 中称为槽(slot),您将在接下来的段落中了解更多关于信号(signal)和(slot)的信息。

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = QWidget()
    w.resize(300,300)
    w.setWindowTitle("Guru99")

这是应用程序的主要部分,与前面的示例一样,您首先创建一个 QApplication 实例,然后创建一个简单的小部件,即 QWidget 的实例。

label = QLabel(w)
    btn = QPushButton(w)

您在此应用程序中添加了两个新小部件:QLabel 和 QPushButton。QLabel 用于在小部件内打印不可编辑的文本或占位符,而 QPushButton 用于创建可点击的按钮。

这里最关键的一点是,当您创建 label 和 btn 对象时,您将窗口对象 (w) 传递给 QLabel 和 QPushButton 的构造函数。这就是 PyQt5 中的嵌套工作原理。要在一个小部件内创建另一个小部件,您需要将父小部件的引用传递给子项的构造函数。

label.move(100,130)
btn.move(110,150)

move() 用于设置小部件相对于其父小部件的位置。在第一种情况下,标签将从窗口的左侧移动 100 像素,从顶部移动 130 像素。

类似地,按钮将从窗口的左侧移动 110 像素,从顶部移动 150 像素。此示例是实现布局的粗略方法,通常不在生产中使用;它仅在此处用于学习目的。Qt 支持不同的布局,您将在本 PyQt 教程的后续部分中详细介绍。

btn.clicked.connect(dialog)

最后,这是 Qt 中信号和槽的一个示例。在基于 GUI 的应用程序中,函数会根据用户执行的操作(如鼠标悬停在元素上或单击按钮)来执行。这些操作称为事件。请记住,app.exec_() 方法将控件转移到 Qt事件循环。事件循环的目的就是监听事件并做出响应。

每当发生事件时,例如用户单击按钮,相应的 Qt 小部件就会发出信号。这些信号可以连接到Python 函数(如本示例中的 dialog 函数),以便在信号触发时执行该函数。在 Qt 术语中,这些函数称为

因此,响应事件信号的槽函数的触发基本语法如下

 widget.signal.connect(slot)

这意味着,每当小部件触发信号时,连接的函数都将被执行。总之,Qt 使用信号和槽在对象之间进行通信,并促进组件的可重用性和交互性。

现在您知道如何嵌套小部件和实现交互(使用信号和槽)了,这里有一个您可以在 PyQt 应用程序中使用的有用小部件和其他类的列表。

组件和窗口部件

PyQt 中有大量小部件可用于创建 GUI 应用程序。但是,在 PyQt5 中,类已重新组织到不同的模块中,并且许可也得到了修订。

因此,对 PyQt5 的结构有一个高层次的了解至关重要。在本节中,您将了解 PyQt5 的内部组织,并了解 PyQt5 提供的各种模块、库和 API 类。

PyQt5 目录结构

PyQt5 Directory Structure

这些是 Python 的 Qt 绑定(特别是 PyQt5)使用的基本模块。

  • Qt:它将下面提到的所有类/模块合并到一个模块中。它会显著增加应用程序使用的内存。但是,仅导入一个模块会使框架更容易管理。
  • QtCore:包含其他模块使用的核心非图形类。这是实现 Qt 事件循环、信号和槽连接等的地方。
  • QtWidgets:包含 Pyqt5 中的大多数小部件。
  • QtGui:包含 GUI 组件并扩展了 QtCore 模块。
  • QtNetwork:包含通过 Qt 实现网络编程的类。它支持 TCP 服务器、TCP 套接字、UDP 套接字、SSL 处理、网络会话和 DNS 查询。
  • QtMultimedia 提供低级多媒体功能。
  • QtSql:实现 SQL 数据库的数据库集成。支持 ODBC、MySQL、Oracle、SQLite 和 PostgreSQL。

PyQt5 小部件

以下是 PyQt5 中最常用的小部件列表

  • QLineEdit:这是一个输入字段,允许用户输入单行文本。
    line = QLineEdit()
  • QRadioButton:这是一个带可选择按钮的输入字段,类似于 HTML 中的单选按钮。
    rad = QRadioButton("button title")
    rad.setChecked(True)  #to select the button by default.
  • QComboBox:它用于显示带有可选项目列表的下拉菜单。
    drop = QComboBox(w)
    drop.addItems(["item one", "item two", "item three"])
  • QCheckBox:在标签前面显示一个可选择的方框,如果选中则打勾,类似于单选按钮。
    check = QCheckBox("button title")
  • QMenuBar:它在窗口顶部显示一个水平菜单栏。您只能向此栏添加 QMenu 类的对象。这些 QMenu 对象可以进一步包含字符串、QAction 对象或其他 QMenu 对象。
  • QToolBar:它是一个水平条或窗格,可以在窗口内移动。它可能包含按钮和其他小部件。
  • QTab:它用于将窗口的内容分解为多个页面,这些页面可以通过小部件顶部的不同选项卡访问。它包含两个部分:选项卡栏和选项卡页面。
  • QScrollBar:它用于创建滚动条,允许用户在窗口内上下滚动。它包括一个可移动的滑块、一个滑块轨道和两个向上或向下滚动滑块的按钮。
    scroll = QScrollBar()
  • QSplitter:分隔器用于分隔窗口的内容,以便将小部件正确分组,不会显得混乱。QSplitter 是 PyQt5 中可用的主要布局处理程序之一,用于水平和垂直分隔内容。
  • QDock:停靠小部件是一个子窗口,具有两个属性
  • 它可以移动到主窗口内,并且
  • 它可以停靠在父窗口外部,移到屏幕上的另一个位置。

布局和主题

在之前的 PyQt5 示例中,您仅使用了 move() 和 resize() 方法来设置 GUI 中小部件的位置。

但是,PyQt 拥有一个强大的布局管理引擎,可用于为应用程序创建高级用户界面。在本节中,您将学习 Qt 中用于创建和管理布局的两个重要类。

  1. QBoxLayout
  2. QGridLayout

QBoxLayout

QBoxLayout 用于将布局的子小部件对齐到水平或垂直行。两个相关的类继承自 QBoxLayout 是

  • QHBoxLayout:用于将子小部件水平排列。
  • QVBoxLayout:用于将子小部件垂直排列。

例如,使用 QHBoxLayout 对齐的三个按钮将是这样的。

QBoxLayout

import sys
from PyQt5.QtWidgets import *

if __name__ == "__main__":

    app = QApplication([])
    w = QWidget()
    w.setWindowTitle("Musketeers")

    btn1 = QPushButton("Athos")
    btn2 = QPushButton("Porthos")
    btn3 = QPushButton("Aramis")

    hbox = QHBoxLayout(w)

    hbox.addWidget(btn1)
    hbox.addWidget(btn2)
    hbox.addWidget(btn3)

    w.show()

    sys.exit(app.exec_())

在 QVBoxLayout 中它们将是这样的。

QBoxLayout

import sys
from PyQt5.QtWidgets import *

if __name__ == "__main__":

    app = QApplication([])
    w = QWidget()
    w.setWindowTitle("Musketeers")

    btn1 = QPushButton("Athos")
    btn2 = QPushButton("Porthos")
    btn3 = QPushButton("Aramis")

    vb = QVBoxLayout(w)

    vb.addWidget(btn1)
    vb.addWidget(btn2)
    vb.addWidget(btn3)

    w.show()

    sys.exit(app.exec_())

此时唯一需要解释的函数是 addWidget() 方法。它用于将小部件插入 HBox 或 VBox 布局。它也用于其他布局,其中它接受不同数量的参数,您将在下一节中看到。小部件将按照您插入的顺序出现在布局内。

QGridLayout

QGridLayout 用于创建接口,其中小部件以网格形式(如矩阵或二维数组)布局。要将元素插入网格布局,您可以使用矩阵表示来定义网格中的行数和列数以及这些元素的位置。

例如,要创建 3*3 网格(即具有三行三列的网格),您将编写以下代码

Import sys
from PyQt5.QtWidgets import *

if __name__ == "__main__":
    app = QApplication([])

    w = QWidget()

    grid = QGridLayout(w)

    for i in range(3):
        for j in range(3):
            grid.addWidget(QPushButton("Button"),i,j)


    w.show()
    sys.exit(app.exec_())

这将是输出

QGridLayout

网格布局中的 addWidget() 方法接受以下参数

  • 您想添加到网格的对象小部件
  • 对象的 x 坐标
  • 对象的 y 坐标
  • 行跨度(默认为 0)
  • 列跨度(默认为 0)

为了更好地理解,您可以像下面这样手动插入每个小部件

import sys
from PyQt5.QtWidgets import *

if __name__ == "__main__":
    app = QApplication([])

    w = QWidget()

    grid = QGridLayout(w)
    grid.addWidget(QPushButton("Button one"),0,0)
    grid.addWidget(QPushButton("Button two"),0,1)
    grid.addWidget(QPushButton("Button three"),1,0)
    grid.addWidget(QPushButton("Button four"),1,1)


    w.show()
    sys.exit(app.exec_())

网格将看起来像这样

QGridLayout

您还可以将 rowspan 和 colspan 参数传递给 addWidget() 以跨越更多行或列。

例如,

grid.addWidget(QPushButton("Button five"),2,0,1,0)

这将创建一个跨越两列的按钮。

QGridLayout

主题

PyQt5 附带了一些内置主题,您可以在应用程序中使用它们。在 QApplication 实例上调用的 setStyle() 方法用于为您的应用程序设置特定主题。

例如,添加以下代码行会将您的应用程序主题从默认主题更改为 Fusion

app.setStyle("Fusion")

之前的示例在 Fusion 主题下将是这样的。

Themes

setPalette() 方法是另一个有用的应用程序主题功能。以下是使用 setPalette() 更改不同小部件颜色的代码。

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPalette

if __name__ == "__main__":
    app = QApplication([])
    app.setStyle("Fusion")
    
    qp = QPalette()
    qp.setColor(QPalette.ButtonText, Qt.black)
    qp.setColor(QPalette.Window, Qt.black)
    qp.setColor(QPalette.Button, Qt.gray)
    app.setPalette(qp)

    w = QWidget()

    grid = QGridLayout(w)
    grid.addWidget(QPushButton("Button one"),0,0)
    grid.addWidget(QPushButton("Button two"),0,1)
    grid.addWidget(QPushButton("Button three"),1,0)
    grid.addWidget(QPushButton("Button four"),1,1)


    w.show()
    sys.exit(app.exec_())

结果如下。

Themes

要使用 setPalette() 方法,您首先需要定义一个调色板。这是通过创建 QPalette 类的对象来完成的。

 qp = QPalette()

请注意,QPalette 类属于 QtGui 模块,您需要导入它才能使其正常工作。创建 QPalette 对象后,使用 setColor() 方法传递要更改颜色的小部件的名称和要设置的颜色。

 qp.setColor(QPalette.Window, Qt.black)

这将将窗口颜色更改为黑色。定义好颜色方案后,使用 setPalette() 函数将调色板应用于您的应用程序。

app.setPalette(qp)

这就是您想为应用程序创建基本主题所需的一切。PyQt 还允许您使用样式表来定义小部件的外观。如果您熟悉 CSS,您可以使用 Qt 样式表为您的应用程序轻松定义高级样式。

摘要

  • PyQt 是 C++ UI 框架 Qt 的 Python 绑定。
  • PyQt4 和 PyQt5 是 Riverbank Computing 开发的两个主要版本。
  • PyQt 框架的主要模块是
    1. Qt
    2. QtCore
    3. QtWidgets
    4. QtGui
    5. QtSql
    6. QtNetwork
  • PyQt 支持各种小部件,例如
    1. 按钮
    2. 文本标签
    3. 文本字段
    4. 单选按钮和复选框
    5. 工具栏和菜单栏
    6. Webkit
    7. 选项卡
    8. 停靠窗口
  • 在 PyQt 中,交互是通过信号实现的。
  • 事件是用户在 GUI 中执行的操作(例如单击按钮)。
  • 当事件发生在小部件上时,相应的小部件会发出信号
  • 是连接到信号的函数,在信号发出时执行。
  • PyQt 拥有强大的布局引擎,支持高级布局设计和管理。以下是 PyQt 中两个常用的布局方案
    1. 盒式布局
    2. 网格布局
  • PyQt 设计器允许您为 GUI 应用程序创建自定义主题,并内置支持样式表。
  • Qt creator Python 可用于创建用户界面以及独立应用程序。