乐趣区

关于python:在PyQt中构建-Python-菜单栏菜单和工具栏

摘要:菜单、工具栏和状态栏是大多数 GUI 应用程序的常见且重要的图形组件。您能够应用它们为您的用户提供一种快速访问应用程序选项和性能的办法。

本文分享自华为云社区《Python 和 PyQt:创立菜单、工具栏和状态栏》,作者:Yuchuan。

在应用 Python 和 PyQt 开发图形用户界面 (GUI)应用程序时,您将应用的一些最有用和最通用的图形元素是菜单、工具栏和状态栏。

菜单和工具栏能够使您的应用程序看起来 精美 业余,为用户提供一组可拜访的选项,而状态栏容许您显示无关应用程序状态的相干信息。

在本教程中,您将学习:

• 什么菜单,工具栏和状态栏是
• 如何以编程形式创立菜单、工具栏和状态栏
• 如何应用 PyQt 操作填充 Python 菜单和工具栏
• 如何应用状态栏显示状态信息

此外,您将学习一些编程最佳实际,您能够在应用 Python 和 PyQt 创立菜单、工具栏和状态栏时利用这些实际。

在 PyQt 中构建 Python 菜单栏、菜单和工具栏

一个 菜单栏 是一个 GUI 应用程序的区域主窗口中保留菜单。菜单是选项的下拉列表,能够不便地拜访应用程序的选项。例如,如果您正在创立一个文本编辑器,那么您的菜单栏中可能会有以下一些菜单:

• 一个文件菜单,提供以下的一些菜单选项:
o 新建用于创立新文档
o 关上以关上现有文档
o 关上最近关上最近的文档
o Save 用于保存文档
o Exit 退出应用程序
• 提供以下一些菜单选项的“编辑”菜单:
o Copy 用于复制一些文本
o Paste 用于粘贴一些文本
o Cut 用于剪切一些文本
• 一个帮忙菜单,提供以下一些菜单选项:
o 帮忙内容用于启动用户手册和帮忙内容
o 对于启动对于对话框

您还能够将其中一些选项增加到 工具栏。工具栏是带有有意义图标的按钮面板,可提供对应用程序中最罕用选项的快速访问。在您的文本编辑器示例中,您能够向工具栏增加 New、Open、Save、Copy 和 Paste 等选项。

留神:在本教程中,您将开发一个实现上述所有菜单和选项的示例应用程序。您能够应用此示例应用程序作为创立文本编辑器我的项目的终点。

在本节中,您将学习如何应用 Python 和 PyQt 向 GUI 应用程序增加菜单栏、菜单和工具栏的基础知识。

在持续之前,您将创立一个示例 PyQt 应用程序,您将在本教程中应用该应用程序。在每个局部中,您将向此示例应用程序增加新个性和性能。该应用程序将是一个主窗口格调的应用程序。这意味着它将有一个菜单栏、一个工具栏、一个状态栏和一个地方小部件。

关上您最喜爱的代码编辑器或 IDE 并创立一个名为 sample_app.py. 而后在其中增加以下代码:
import sys

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow

class Window(QMainWindow):
    """Main Window."""
    def __init__(self, parent=None):
        """Initializer."""
        super().__init__(parent)
        self.setWindowTitle("Python Menus & Toolbars")
        self.resize(400, 200)
        self.centralWidget = QLabel("Hello, World")
        self.centralWidget.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.setCentralWidget(self.centralWidget)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = Window()
    win.show()
    sys.exit(app.exec_())

当初 sample_app.py 蕴含创立示例 PyQt 应用程序所需的所有代码。在这种状况下,Window 继承自 QMainWindow. 因而,您正在构建一个主窗口款式的应用程序。

留神:可怜的是,PyQt5 的官网文档有一些不残缺的局部。要解决此问题,您能够查看 PyQt4 文档或原始 Qt 文档。

在类初始化程序中.__init__(),您首先应用 调用父类的初始化程序 super()。而后应用 设置窗口的题目.setWindowTitle()并应用调整窗口大小.resize()。

留神:如果您不相熟 PyQt 应用程序以及如何创立它们,那么您能够查看 Python 和 PyQt:构建 GUI 桌面计算器。

窗口的地方小部件是一个 QLabel 对象,您将应用它来显示音讯以响应某些用户操作。这些音讯将显示在窗口的地方。要做到这一点,你叫.setAlignment()上 QLabel 对象与一对夫妇的对齐标记。
如果您从命令行运行该应用程序,那么您将在屏幕上看到以下窗口:

就是这样!您曾经应用 Python 和 PyQt 创立了一个主窗口格调的应用程序。您将在本教程中行将呈现的所有示例中应用此示例应用程序。

创立菜单栏

在 PyQt 主窗口格调的应用程序中,默认 QMainWindow 提供一个空 QMenuBar 对象。要拜访此菜单栏,您须要调用.menuBar()您的 QMainWindow 对象。此办法将返回一个空的菜单栏。此菜单栏的父级将是您的主窗口对象。

当初返回到您的示例应用程序并在 的定义中增加以下办法 Window:

class Window(QMainWindow):
    # Snip...
    def _createMenuBar(self):
        menuBar = self.menuBar()

这是在 PyQt 中创立菜单栏的首选形式。在这里,menuBar 变量将蕴含一个空的菜单栏,这将是您的主窗口的菜单栏。

留神:PyQt 编程中的一个常见做法是将局部变量用于您不会应用或从其定义方法之外须要的对象。Python 垃圾收集所有超出范围的对象,因而您可能认为 menuBar 在下面的示例中,一旦._createMenuBar() 返回就会隐没。

事实是 PyQt 保留对本地对象的援用,例如 menuBar 应用它们的所有权或父子关系。换句话说,因为 menuBar 它归您的主窗口对象所有,Python 将无奈对其进行垃圾收集。

向 PyQt 应用程序增加菜单栏的另一种办法是创立一个 QMenuBar 对象,而后应用.setMenuBar(). 思考到这一点,您还能够._createMenuBar()按以下形式编写:

from PyQt5.QtWidgets import QMenuBar
# Snip...

class Window(QMainWindow):
    # Snip...
    def _createMenuBar(self):
        menuBar = QMenuBar(self)
        self.setMenuBar(menuBar)

在下面的例子中,menuBar 持有一个 QMenuBar 父级设置为的对象 self,它是应用程序的主窗口。一旦你有了菜单栏对象,你就能够.setMenuBar()将它增加到你的主窗口中。最初,须要留神的是在这个例子中工作,你首先须要进口 QMenuBar 的 PyQt5.QWidgets。

在 GUI 应用程序中,菜单栏会依据底层操作系统显示在不同的地位:

• Windows:在应用程序主窗口的顶部,标题栏下方
• macOS:在屏幕顶部
• Linux:在主窗口顶部或屏幕顶部,取决于您的桌面环境
为应用程序创立菜单栏的最初一步是._createMenuBar()从主窗口的初始化程序调用.__init__():

class Window(QMainWindow):
    """Main Window."""
    def __init__(self, parent=None):
        # Snip...
        self._createMenuBar()

如果您应用这些新更改运行示例应用程序,那么您将看不到应用程序主窗口中显示的菜单栏。那是因为您的菜单栏依然是空的。要查看应用程序主窗口上的菜单栏,您须要创立一些菜单。这就是你接下来要学习的内容。

将菜单增加到菜单栏

菜单是菜单选项的下拉列表,您能够通过单击它们或按键盘快捷键来触发。在 PyQt 中,至多有三种办法能够将菜单增加到菜单栏对象:

  1. QMenuBar.addMenu(menu)将 QMenu 对象 (menu)附加到菜单栏对象。它返回与此菜单关联的操作。
  2. QMenuBar.addMenu(title)创立一个 QMenu 以字符串 (title) 作为题目的新对象并将其附加到菜单栏。菜单栏获得菜单的所有权,该办法返回新 QMenu 对象。
  3. QMenuBar.addMenu(icon, title)创立并追加新的 QMenu 物品与 icon 和 title 一个菜单栏对象。菜单栏获得菜单的所有权,该办法返回新 QMenu 对象。

如果应用第一个选项,则须要先创立自定义 QMenu 对象。为此,您能够应用以下构造函数之一:

  1. QMenu(parent)
  2. QMenu(title, parent)

在这两种状况下,parent 是 QWidget 将持有 QMenu 对象的所有权。您通常会设置 parent 到您将在其中应用菜单的窗口。在第二个构造函数中,title 将保留一个带有形容菜单选项的文本的字符串。

以下是将 File、Edit 和 Help 菜单增加到示例应用程序的菜单栏的办法:

from PyQt5.QtWidgets import QMenu
# Snip...

class Window(QMainWindow):
    # Snip...
    def _createMenuBar(self):
        menuBar = self.menuBar()
        # Creating menus using a QMenu object
        fileMenu = QMenu("&File", self)
        menuBar.addMenu(fileMenu)
        # Creating menus using a title
        editMenu = menuBar.addMenu("&Edit")
        helpMenu = menuBar.addMenu("&Help")

首先,你导入 QMenu 的 PyQt5.QtWidgets。而后在 中._createMenuBar(),应用 的前两个变体向菜单栏增加三个菜单.addMenu()。第三个变体须要一个图标对象,但您还没有学会如何创立和应用图标。您将在应用 PyQt 中的图标和资源局部中理解如何应用图标。

如果您运行示例应用程序,那么您将看到您当初有一个如下所示的菜单栏:

应用程序的菜单栏有菜单 File、Edit 和 Help。当您单击这些菜单时,它们不会显示菜单选项的下拉列表。那是因为您还没有增加菜单选项。您将在应用操作填充菜单局部中理解如何向菜单增加菜单选项。

最初,请留神 & 蕴含在每个菜单题目中的与符号 () 会在菜单栏显示中创立带下划线的字母。这在定义菜单和工具栏选项的键盘快捷键一节中有更具体的探讨。

创立工具栏

甲工具栏是保留按钮和其余部件,以提供到 GUI 利用的最一般的选项快速访问的可挪动面板。工具栏按钮能够显示图标、文本或两者来示意它们执行的工作。PyQt 中工具栏的基类是 QToolBar. 此类将容许您为 GUI 应用程序创立自定义工具栏。

当您向主窗口款式应用程序增加工具栏时,默认地位在窗口顶部。然而,您能够在以下四个工具栏区域之一中搁置工具栏:

工具栏区域在 PyQt 中被定义为常量。如果您须要应用它们,那么您必须导入 QtfromPyQt5.QtCore 而后像 in 一样应用齐全限定名称 Qt.LeftToolBarArea。

在 PyQt 中,能够通过三种办法向主窗口应用程序增加工具栏:

  1. QMainWindow.addToolBar(title)创立一个新的空 QToolBar 对象并将其窗口题目设置为 title. 此办法将工具栏插入顶部工具栏区域并返回新创建的工具栏。
  2. QMainWindow.addToolBar(toolbar)将 QToolBar 对象 (toolbar) 插入顶部工具栏区域。
  3. QMainWindow.addToolBar(area, toolbar)将 QToolBar 对象 (toolbar) 插入指定的工具栏区域 (area)。如果主窗口已有工具栏,则 toolbar 搁置在最初一个现有工具栏之后。如果 toolbar 曾经存在于主窗口中,那么它只会被挪动到 area.

如果您应用最初两个选项之一,那么您须要本人创立工具栏。为此,您能够应用以下构造函数之一:

  1. QToolBar(parent)
  2. QToolBar(title, parent)

在这两种状况下,parent 代表 QWidget 将领有工具栏所有权的对象。您通常会将工具栏所有权设置为将在其中应用工具栏的窗口。在第二个构造函数中,title 将是一个带有工具栏窗口题目的字符串。PyQt 应用这个窗口题目来构建一个默认的上下文菜单,容许你暗藏和显示你的工具栏。

当初您能够返回到您的示例应用程序并将以下办法增加到 Window:

from PyQt5.QtWidgets import QToolBar
# Snip...

class Window(QMainWindow):
    # Snip...
    def _createToolBars(self):
        # Using a title
        fileToolBar = self.addToolBar("File")
        # Using a QToolBar object
        editToolBar = QToolBar("Edit", self)
        self.addToolBar(editToolBar)
        # Using a QToolBar object and a toolbar area
        helpToolBar = QToolBar("Help", self)
        self.addToolBar(Qt.LeftToolBarArea, helpToolBar)

首先,您 QToolBar 从 PyQt5.QtWidgets. 而后,在 中._createToolBars(),您首先应用题目创立文件工具栏.addToolBar()。接下来,您创立一个 QToolBar 带有题目的对象,”Edit” 并应用.addToolBar()不传递工具栏区域将其增加到工具栏。在这种状况下,编辑工具栏位于顶部工具栏区域。最初,创立帮忙工具栏并应用 将其搁置在左侧工具栏区域 Qt.LeftToolBarArea。

实现这项工作的最初一步是._createToolBars()从 的初始化程序调用 Window:

class Window(QMainWindow):
    """Main Window."""
    def __init__(self, parent=None):
        # Snip...
        self._createToolBars()

._createToolBars()对初始化器外部的调用 Window 将创立三个工具栏并将它们增加到您的主窗口中。以下是您的应用程序当初的外观:

当初,菜单栏正下方有两个工具栏,窗口左侧有一个工具栏。每个工具栏都有一条双虚线。当您将鼠标移到虚线上时,指针会变成一只手。如果单击并按住虚线,则能够将工具栏挪动到窗口上的任何其余地位或工具栏区域。

如果右键单击工具栏,PyQt 将显示一个上下文菜单,容许您依据须要暗藏和显示现有工具栏。

到目前为止,您的应用程序窗口中有三个工具栏。这些工具栏依然是空的——您须要增加一些工具栏按钮能力使它们起作用。为此,您能够应用 PyQt actions,它们是 QAction. 您将在前面的局部中学习如何在 PyQt 中创立操作。当初,您将学习如何在 PyQt 应用程序中应用图标和其余资源。

在 PyQt 中应用图标和资源

在 Qt 库包含 Qt 的资源零碎,这是减少的二进制文件,如图标,图像,翻译文件和其余资源对应用程序的一种便捷形式。

要应用资源零碎,您须要在资源汇合文件或.qrc 文件中列出您的资源。一个.qrc 文件是一个 XML 蕴含地位,或文件门路,文件系统中的每个资源的。

假如您的示例应用程序有一个 resources 目录,其中蕴含您要在应用程序的 GUI 中应用的图标。您有 New、Open 等选项的图标。您能够创立一个.qrc 蕴含每个图标门路的文件:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
    <file alias="file-new.svg">resources/file-new.svg</file>
    <file alias="file-open.svg">resources/file-open.svg</file>
    <file alias="file-save.svg">resources/file-save.svg</file>
    <file alias="file-exit.svg">resources/file-exit.svg</file>
    <file alias="edit-copy.svg">resources/edit-copy.svg</file>
    <file alias="edit-cut.svg">resources/edit-cut.svg</file>
    <file alias="edit-paste.svg">resources/edit-paste.svg</file>
    <file alias="help-content.svg">resources/help-content.svg</file>
</qresource>
</RCC>

每个 <file> 条目必须蕴含文件系统中资源的门路。指定的门路绝对于蕴含.qrc 文件的目录。在下面的例子中,resources 目录须要和.qrc 文件在同一个目录下。

alias 是一个可选属性,它定义了一个简短的代替名称,您能够在代码中应用它来拜访每个资源。
一旦您领有应用程序的资源,您就能够运行 pyrcc5 针对您的.qrc 文件的命令行工具。pyrcc5 随 PyQt 一起提供,并且必须在装置 PyQt 后在您的 Python 环境中齐全失常运行。

pyrcc5 读取一个.qrc 文件并生成一个 Python 模块,其中蕴含所有资源的二进制代码:

$ pyrcc5 -o qrc_resources.py resources.qrc

此命令将读取 resources.qrc 并生成 qrc_resources.py 蕴含每个资源的二进制代码。您将可能通过导入在 Python 代码中应用这些资源 qrc_resources。

留神:如果运行时呈现问题 pyrcc5,请确保您应用的是正确的 Python 环境。如果您在 Python 虚拟环境中装置 PyQt,那么您将无奈 pyrcc5 在该环境之外应用。

这 qrc_resources.py 是对应于您的代码片段 resources.qrc:

# -*- coding: utf-8 -*-

# Resource object code
#
# Created by: The Resource Compiler for PyQt5 (Qt v5.9.5)
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore

qt_resource_data = b"\
\x00\x00\x03\xb1\
\x3c\
\x73\x76\x67\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\
...

随着 qrc_resources.py 在中央,你能够将其导入到你的应用程序,并通过键入一个冒号(请参阅各资源:),而后无论是它的 alias 或它的门路。例如,要应用 file-new.svg 其别名进行拜访,您能够应用 拜访字符串 “:file-new.svg”。如果您没有 alias,则能够通过带有拜访字符串的门路拜访它 ”:resources/file-new.svg”。

如果您有别名,但因为某种原因您想通过其门路拜访给定资源,那么您可能必须从拜访字符串中删除冒号能力使其失常工作。

要在您的操作中应用图标,您首先须要导入您的资源模块:
import qrc_resources

导入蕴含资源的模块后,您能够在应用程序的 GUI 中应用这些资源。

留神:Linters、编辑器和 IDE 可能会将上述 import 语句标记为未应用,因为您的代码不会蕴含对它的任何显式应用。某些 IDE 可能会更进一步并主动删除该行。

在这些状况下,您必须笼罩您的 linter、编辑器或 IDE 的倡议,并将该导入保留在您的代码中。否则,您的应用程序将无奈显示您的资源。

要应用资源零碎创立图标,您须要实例化 QIcon,将别名或门路传递给类构造函数:
newIcon = QIcon(":file-new.svg")

在此示例中,您将 QIcon 应用文件创建一个对象,该对象 file-new.svg 位于您的资源模块中。这提供了一种在整个 GUI 应用程序中应用图标和资源的便捷形式。

当初返回到您的示例应用程序并更新最初一行._createMenuBar():

from PyQt5.QtGui import QIcon

import qrc_resources
# Snip...

class Window(QMainWindow):
    # Snip...
    def _createMenuBar(self):
        menuBar = self.menuBar()
        # Using a QMenu object
        fileMenu = QMenu("&File", self)
        menuBar.addMenu(fileMenu)
        # Using a title
        editMenu = menuBar.addMenu("&Edit")
        # Using an icon and a title
        helpMenu = menuBar.addMenu(QIcon(":help-content.svg"), "&Help")

要使此代码失常工作,您首先须要 QIcon 从 PyQt5.QtGui. 您还须要导入 qrc_resources. 在最初突出显示的行中,您从资源模块中增加了一个 helpMenu 应用图标 help-content.svg。
如果您应用此更新运行示例应用程序,您将取得以下输入:

应用程序的主窗口当初在其帮忙菜单上显示一个图标。当您单击该图标时,菜单会显示文本 Help。在菜单栏中应用图标并不常见,但 PyQt 容许您这样做。

在 PyQt 中为 Python 菜单和工具栏创立操作

PyQt 动作是示意应用程序中给定命令、操作或动作的对象。当您须要为不同的 GUI 组件(例如菜单选项、工具栏按钮和键盘快捷键)提供雷同的性能时,它们十分有用。

您能够通过实例化 QAction. 创立操作后,您须要将其增加到小部件中能力在实践中应用它。

您还须要将您的操作与某些性能分割起来。换句话说,您须要将它们连贯到触发操作时要运行的函数或办法。这将容许您的应用程序执行操作以响应 GUI 中的用户操作。

口头是相当多才多艺的。它们容许您跨菜单选项、工具栏按钮和键盘快捷键重复使用并放弃同步雷同的性能。这在整个应用程序中提供了统一的行为。

例如,当用户单击关上 … 菜单选项、单击关上工具栏按钮或按键盘上的 Ctrl+ O 时,他们可能心愿应用程序执行雷同的操作。

QAction 提供了一个形象,容许您跟踪以下元素:

• 菜单选项上的文字
• 工具栏按钮上的文本
• 工具栏选项上的帮忙提醒(工具提醒)
• 这是什么帮忙提醒
• 状态栏上的帮忙提醒(状态提醒)
• 与选项关联的键盘快捷键
• 与菜单和工具栏选项相关联的图标
• 动作 enabled 或 disabled 状态
• 动作 on 或 off 状态

要创立操作,您须要实例化 QAction. 至多有三种通用办法能够做到这一点:

  1. QAction(parent)
  2. QAction(text, parent)
  3. QAction(icon, text, parent)

在所有三种状况下,都 parent 示意领有操作所有权的对象。此参数能够是任何 QObject. 最佳实际是将操作创立为您将在其中应用它们的窗口的子项。

在第二个和第三个构造函数中,text 保留操作将在菜单选项或工具栏按钮上显示的文本。

操作文本在菜单选项和工具栏按钮上的显示方式不同。例如,文本 &Open… 显示为关上 … 菜单中的选项,如关上的工具栏按钮。

在第三个构造函数中,icon 是一个 QIcon 保留动作图标的对象。此图标将显示在菜单选项中文本的左侧。图标在工具栏按钮中的地位取决于工具栏的.toolButtonStyle 属性,能够采纳以下值之一:

您还能够设置该操作的文本和图标通过各自的 setter 办法,.setText()和.setIcon()。

留神:无关 QAction 属性的残缺列表,您能够查看文档。

以下是如何应用 的不同构造函数为示例应用程序创立一些操作 QAction:

from PyQt5.QtWidgets import QAction
# Snip...

class Window(QMainWindow):
    # Snip...
    def _createActions(self):
        # Creating action using the first constructor
        self.newAction = QAction(self)
        self.newAction.setText("&New")
        # Creating actions using the second constructor
        self.openAction = QAction("&Open...", self)
        self.saveAction = QAction("&Save", self)
        self.exitAction = QAction("&Exit", self)
        self.copyAction = QAction("&Copy", self)
        self.pasteAction = QAction("&Paste", self)
        self.cutAction = QAction("C&ut", self)
        self.helpContentAction = QAction("&Help Content", self)
        self.aboutAction = QAction("&About", self)

在 中._createActions(),您为示例应用程序创立了一些操作。这些操作将容许您向应用程序的菜单和工具栏增加选项。

请留神,您将操作创立为实例属性,因而您能够._createActions()应用 self. 这样,您就能够在菜单和工具栏上应用这些操作。

留神:在 中._createActions(),您不应用的第三个构造函数,QAction 因为如果您还看不到操作,则应用图标是没有意义的。您将在应用操作填充工具栏局部中理解如何向操作增加图标。

下一步是调用._createActions()form 的初始化程序 Window:

class Window(QMainWindow):
    """Main Window."""
    def __init__(self, parent=None):
        # Snip...
        self._createActions()
        self._createMenuBar()
        self._createToolBars()

如果您当初运行该应用程序,那么您将不会在 GUI 上看到任何更改。这是因为在将操作增加到菜单或工具栏之前不会显示它们。请留神,您在调用._createActions()之前先调用._createMenuBar(),._createToolBars()因为您将在菜单和工具栏上应用这些操作。

如果您向菜单增加操作,则该操作将成为菜单选项。如果向工具栏增加操作,则该操作将成为工具栏按钮。这就是接下来几节的主题。

在 PyQt 中为 Python 菜单增加选项

如果要向 PyQt 中的给定菜单增加选项列表,则须要应用操作。到目前为止,您曾经学习了如何应用 QAction. 在 PyQt 中创立菜单时,操作是一个要害组件。

在本节中,您将学习如何应用操作来填充带有菜单选项的菜单。

用动作填充菜单

要应用菜单选项填充菜单,您将应用操作。在菜单中,操作示意为一个程度选项,其中至多有一个描述性文本,如 New、Open、Save 等。菜单选项还能够在其左侧显示一个图标,并在其右侧显示快捷键序列,例如 Ctrl+S。

您能够 QMenu 应用向对象增加操作.addAction()。此办法有多种变体。他们中的大多数被认为是即时创立操作。在本教程中,然而,你要应用的变动.addAction()是 QMenu 从继承 QWidget。这是此变体的签名:

QWidget.addAction(action)
参数 action 示意 QAction 要增加到给定 QWidget 对象的对象。应用 的这种变体.addAction(),您能够事后创立您的操作,而后依据须要将它们增加到您的菜单中。

留神:QWidget 还提供.addActions(). 此办法采纳一系列操作并将它们附加到以后小部件对象。

应用此工具,您能够开始向示例应用程序的菜单增加操作。为此,您须要更新._createMenuBar():

class Window(QMainWindow):
    # Snip...
    def _createMenuBar(self):
        menuBar = self.menuBar()
        # File menu
        fileMenu = QMenu("&File", self)
        menuBar.addMenu(fileMenu)
        fileMenu.addAction(self.newAction)
        fileMenu.addAction(self.openAction)
        fileMenu.addAction(self.saveAction)
        fileMenu.addAction(self.exitAction)
        # Edit menu
        editMenu = menuBar.addMenu("&Edit")
        editMenu.addAction(self.copyAction)
        editMenu.addAction(self.pasteAction)
        editMenu.addAction(self.cutAction)
        # Help menu
        helpMenu = menuBar.addMenu(QIcon(":help-content.svg"), "&Help")
        helpMenu.addAction(self.helpContentAction)
        helpMenu.addAction(self.aboutAction)

通过对 的更新._createMenuBar(),您能够向示例应用程序的三个菜单增加许多选项。

当初文件菜单有四个选项:

  1. 新建用于创立新文件
  2. Open… 用于关上现有文件
  3. Save 用于保留对文件所做的更改
  4. 退出以敞开应用程序

在编辑菜单中有三个选项:

  1. 将内容复制到零碎剪贴板
  2. Paste 用于从零碎剪贴板粘贴内容
  3. Cut 用于将内容剪切到零碎剪贴板

在帮忙菜单中有两个选项:

  1. 用于启动应用程序帮忙手册的帮忙内容
  2. 对于用于显示对于对话框

选项在菜单中从上到下显示的程序对应于您在代码中增加选项的程序。

如果您运行该应用程序,您将在屏幕上看到以下窗口:

如果您单击某个菜单,则该应用程序会显示一个蕴含您之前看到的选项的下拉列表。

创立 Python 子菜单

有时您须要在 GUI 应用程序中应用子菜单。子菜单是一个嵌套的菜单,当您将光标移到给定的菜单选项上时会显示该菜单。要将子菜单增加到应用程序,您须要调用.addMenu()容器菜单对象。

假如您须要在示例应用程序的 Edit 菜单中增加一个子菜单。您的子菜单将蕴含用于查找和替换内容的选项,因而您将其称为 Find and Replace。该子菜单将有两个选项:

  1. 查找 … 以查找一些内容
  2. 替换 … 用于查找旧内容并将其替换为新内容

以下是将此子菜单增加到示例应用程序的办法:

class Window(QMainWindow):
    # Snip...
    def _createMenuBar(self):
        # Snip...
        editMenu.addAction(self.cutAction)
        # Find and Replace submenu in the Edit menu
        findMenu = editMenu.addMenu("Find and Replace")
        findMenu.addAction("Find...")
        findMenu.addAction("Replace...")
        # Snip...

在突出显示的第一行中,您应用 on 将 QMenu 带有文本的对象增加 ”Find and Replace” 到“编辑”菜单。下一步是应用您迄今为止所做的操作填充子菜单。如果您再次运行示例应用程序,您将在 Edit 菜单下看到一个新的菜单选项:.addMenu()editMenu

在编辑菜单当初有一个新的条目称为查找和替换。当您将鼠标悬停在这个新菜单选项上时,会呈现一个子菜单,为您提供两个新选项,Find… 和 Replace…。就是这样!您曾经创立了一个子菜单。

在 PyQt 中向工具栏增加选项

在应用 Python 和 PyQt 构建 GUI 应用程序时,工具栏是一个十分有用的组件。您能够应用工具栏向您的用户提供一种快速访问应用程序中最罕用选项的办法。您还能够向工具栏增加诸如旋转框和组合框之类的小部件,以容许用户间接从应用程序的 GUI 批改某些属性和变量。

在以下几节中,您将学习如何应用操作向工具栏增加选项或按钮,以及如何应用.addWidget().

用动作填充工具栏

要将选项或按钮增加到工具栏,您须要调用.addAction()。在本节中,你会依附的变动.addAction()是 QToolBar 从继承 QWidget。因而,您将.addAction()应用动作作为参数进行调用。这将容许您在菜单和工具栏之间共享您的操作。

创立工具栏时,您通常会面临决定向其中增加哪些选项的问题。通常,您只想将最罕用的操作增加到工具栏。

如果返回到示例应用程序,您会记得您增加了三个工具栏:

  1. File
  2. Edit
  3. Help

在文件工具栏中,您能够增加如下选项:
• New
• Open
• Save

在编辑工具栏中,您能够增加以下选项:
• Copy
• Paste
• Cut

通常,当您要向工具栏增加按钮时,首先要抉择要在每个按钮上应用的图标。这不是强制性的,但它是最佳实际。抉择图标后,您须要将它们增加到相应的操作中。

以下是向示例应用程序的操作增加图标的办法:

class Window(QMainWindow):
    # Snip...
    def _createActions(self):
        # File actions
        self.newAction = QAction(self)
        self.newAction.setText("&New")
        self.newAction.setIcon(QIcon(":file-new.svg"))
        self.openAction = QAction(QIcon(":file-open.svg"), "&Open...", self)
        self.saveAction = QAction(QIcon(":file-save.svg"), "&Save", self)
        self.exitAction = QAction("&Exit", self)
        # Edit actions
        self.copyAction = QAction(QIcon(":edit-copy.svg"), "&Copy", self)
        self.pasteAction = QAction(QIcon(":edit-paste.svg"), "&Paste", self)
        self.cutAction = QAction(QIcon(":edit-cut.svg"), "C&ut", self)
        # Snip...

要将图标增加到您的操作,请更新突出显示的行。在 的状况下 newAction,您应用.setIcon(). 在其余的操作中,您应用带有 icon、atitle 和 parent 对象作为参数的构造函数。

一旦您抉择的操作具备图标,您能够通过调用.addAction()工具栏对象将这些操作增加到相应的工具栏:

class Window(QMainWindow):
    # Snip...
    def _createToolBars(self):
        # File toolbar
        fileToolBar = self.addToolBar("File")
        fileToolBar.addAction(self.newAction)
        fileToolBar.addAction(self.openAction)
        fileToolBar.addAction(self.saveAction)
        # Edit toolbar
        editToolBar = QToolBar("Edit", self)
        self.addToolBar(editToolBar)
        editToolBar.addAction(self.copyAction)
        editToolBar.addAction(self.pasteAction)
        editToolBar.addAction(self.cutAction)

通过此更新._createToolBars(),您能够将新建、关上和保留选项的按钮增加到文件工具栏。您还能够将 Copy、Paste 和 Cut 选项的按钮增加到“编辑”工具栏。

留神:按钮在工具栏上从左到右显示的程序对应于您在代码中增加按钮的程序。

如果您当初运行示例应用程序,您将在屏幕上看到以下窗口:

示例应用程序当初显示两个工具栏,每个工具栏都有几个按钮。您的用户能够单击这些按钮以快速访问应用程序最罕用的选项。

留神:当您第一次._createToolBars()在创立工具栏局部回信时,您创立了一个帮忙工具栏。此工具栏旨在展现如何应用不同的.addToolBar().

在 的上述更新中._createToolBars(),您去掉了帮忙工具栏,只是为了使示例简短明了。

请留神,因为您在菜单和工具栏之间共享雷同的操作,因而菜单选项也会在其左侧显示图标,这在生产力和资源应用方面是一个微小的胜利。这是应用 PyQt 操作通过 Python 创立菜单和工具栏的劣势之一。

向工具栏增加小部件

在某些状况下,您会发现将特定小部件(如旋转框、组合框或其余)增加到工具栏很有用。一个常见的例子是大多数文字处理器应用的组合框,容许用户更改文档的字体或所选文本的大小。

要将小部件增加到工具栏,您首先须要创立小部件,设置其属性,而后调用.addWidget()工具栏对象,将小部件作为参数传递。

假如您想向示例应用程序 QSpinBox 的“编辑”工具栏增加一个对象,以容许用户更改某些内容的大小,可能是字体大小。您须要更新._createToolBars():

from PyQt5.QtWidgets import QSpinBox
# Snip...

class Window(QMainWindow):
    # Snip...
    def _createToolBars(self):
        # Snip...
        # Adding a widget to the Edit toolbar
        self.fontSizeSpinBox = QSpinBox()
        self.fontSizeSpinBox.setFocusPolicy(Qt.NoFocus)
        editToolBar.addWidget(self.fontSizeSpinBox)

在这里,您首先导入旋转框类。而后您创立一个 QSpinBox 对象,将其设置 focusPolicy 为 Qt.NoFocus,最初将其增加到您的编辑工具栏。

留神:在下面的代码中,您将 focusPolicy 旋转框的属性设置为,Qt.NoFocus 因为如果此小部件取得焦点,则应用程序的键盘快捷键将无奈失常工作。

当初,如果您运行该应用程序,那么您将取得以下输入:

此处,“编辑”工具栏显示了一个 QSpinBox 对象,您的用户能够应用该对象来设置应用程序上的字体大小或任何其余数字属性。

自定义工具栏

PyQt 工具栏非常灵活且可定制。您能够在工具栏对象上设置一堆属性。下表显示了一些最有用的属性:

所有这些属性都有一个关联的 setter 办法。例如,您能够应用.setAllowedAreas()to set allowedAreas、.setFloatable()to setfloatable 等。

当初,假如您不心愿用户在窗口四周挪动文件工具栏。在这种状况下,您能够设置 movable 为 False 应用.setMovable():

class Window(QMainWindow):
    # Snip...
    def _createToolBars(self):
        # File toolbar
        fileToolBar = self.addToolBar("File")
        fileToolBar.setMovable(False)
        # Snip...

突出显示的线使这里变得神奇。当初您的用户无奈在应用程序窗口四周挪动工具栏:

该文件的工具栏不显示双虚线了,所以你的用户将无奈将其挪动。请留神,编辑工具栏依然是可挪动的。您能够应用雷同的办法更改工具栏上的其余属性,并依据您的须要自定义它们。

组织菜单和工具栏选项

为了在 GUI 应用程序中减少清晰度并改善用户体验,您能够应用分隔符来组织菜单选项和工具栏按钮。分隔符出现为分隔或分隔菜单选项的水平线或分隔工具栏按钮的垂直线。

要在菜单、子菜单或工具栏对象中插入或增加分隔符,您能够调用.addSeparator()这些对象中的任何一个。

例如,您能够应用分隔符将“文件”菜单上的“退出”选项与其余选项离开,以明确“退出”与菜单上的其余选项在逻辑上无关。您还能够应用分隔符将“编辑”菜单上的“查找和替换”选项与遵循雷同规定的其余选项离开。

转到您的示例应用程序并._createMenuBar()依照以下代码进行更新:

class Window(QMainWindow):
    # Snip...
    def _createMenuBar(self):
        # File menu
        # Snip...
        fileMenu.addAction(self.saveAction)
        # Adding a separator
        fileMenu.addSeparator()
        fileMenu.addAction(self.exitAction)
        # Edit menu
        # Snip...
        editMenu.addAction(self.cutAction)
        # Adding a separator
        editMenu.addSeparator()
        # Find and Replace submenu in the Edit menu
        findMenu = editMenu.addMenu("Find and Replace")
        # Snip...

在突出显示的第一行中,在“文件”菜单中的“保留”和“退出”选项之间增加一个分隔符。在第二个突出显示的行中,增加一个分隔符,将“查找和替换”选项与“编辑”菜单中的其余选项离开。以下是这些增加的工作原理:

您的“文件”菜单当初显示一条水平线,将“编辑”选项与菜单中的其余选项离开。在编辑菜单中还显示,在选项的下拉列表中的最初一个分隔符。分隔符的连贯应用能够奇妙地进步菜单和工具栏的清晰度,使您的 GUI 应用程序更加用户敌对。

作为练习,您能够转到 的定义._createToolBars()并增加一个分隔符,将 QSpinBox 对象与工具栏上的其余选项离开。

在 PyQt 中构建上下文或弹出菜单

上下文菜单,也称为弹出菜单,是一种非凡类型的菜单,它会响应某些用户操作(例如右键单击给定的小部件或窗口)而呈现。这些菜单提供了一小部分选项,这些选项在您应用的操作系统或应用程序的给定上下文中可用。

例如,如果您右键单击 Windows 计算机的桌面,您将取得一个菜单,其中蕴含与操作系统的特定上下文或空间绝对应的选项。如果您右键单击文本编辑器的工作区,您将取得一个齐全不同的上下文菜单,具体取决于您应用的编辑器。

在 PyQt 中,您有多种创立上下文菜单的选项。在本教程中,您将理解其中两个选项:

  1. 将 contextMenuPolicy 特定小部件的属性设置为 Qt.ActionsContextMenu
  2. 通过解决应用程序窗口上的上下文菜单事件 contextMenuEvent()

第一个选项是两者中最常见和用户敌对的,因而您将首先理解它。

第二个选项略微简单一些,并且依赖于解决用户事件。在 GUI 编程中,事件是应用程序上的任何用户操作,例如单击按钮或菜单、从组合框中抉择我的项目、在文本字段中输出或更新文本、按下键盘上的键等.

通过上下文菜单策略创立上下文菜单

所有派生自的 PyQt 图形组件或小部件都 QWidget 继承了一个名为 contextMenuPolicy. 此属性管制小部件如何显示上下文菜单。此属性最罕用的值之一是 Qt.ActionsContextMenu。这使得小部件将其外部操作列表显示为上下文菜单。

要使小部件依据其外部操作显示上下文菜单,您须要运行两个步骤:

  1. 应用 向小部件增加一些操作 QWidget.addAction()。
  2. 设置 contextMenuPolicy 于 Qt.ActionsContextMenu 上应用的小工具.setContextMenuPolicy()。

设置 contextMenuPolicy 为 Qt.ActionsContextMenu 使具备操作的小部件在上下文菜单中显示它们。这是应用 Python 和 PyQt 创立上下文菜单的一种十分疾速的办法。

应用这种技术,您能够向示例应用程序的地方小部件增加上下文菜单,并为您的用户提供一种快速访问某些应用程序选项的办法。为此,您能够将以下办法增加到 Window:

class Window(QMainWindow):
    # Snip...
    def _createContextMenu(self):
        # Setting contextMenuPolicy
        self.centralWidget.setContextMenuPolicy(Qt.ActionsContextMenu)
        # Populating the widget with actions
        self.centralWidget.addAction(self.newAction)
        self.centralWidget.addAction(self.openAction)
        self.centralWidget.addAction(self.saveAction)
        self.centralWidget.addAction(self.copyAction)
        self.centralWidget.addAction(self.pasteAction)
        self.centralWidget.addAction(self.cutAction)

在 中._createContextMenu(),您首先设置 contextMenuPolicy 为 Qt.ActionsContextMenu 应用 setter 办法.setContextMenuPolicy()。而后.addAction()像平常一样向小部件增加操作。最初一步是._createContextMenu()从 的初始化程序调用 Window:

class Window(QMainWindow):
    """Main Window."""
    def __init__(self, parent=None):
        # Snip...
        self._createToolBars()
        self._createContextMenu()

如果您在增加这些内容后运行示例应用程序,那么当您右键单击该应用程序的地方小部件时,您会看到它显示一个上下文菜单:

当初,您的示例应用程序有一个上下文菜单,只有您右键单击应用程序的地方小部件,就会弹出该菜单。地方小部件舒展以占据窗口中的所有可用空间,因而您不仅限于右键单击标签文本以查看上下文菜单。

最初,因为您在整个应用程序中应用雷同的操作,上下文菜单上的选项显示雷同的图标集。

通过事件处理创立上下文菜单

在 PyQt 中创立上下文菜单的另一种办法是解决应用程序主窗口的上下文菜单事件。为此,您须要运行以下步骤:

  1. 笼罩对象.contextMenuEvent()上的事件处理程序办法 QMainWindow。
  2. 创立一个 QMenu 传递小部件(上下文小部件)作为其父对象的对象。
  3. 用动作填充菜单对象。
  4. 应用 QMenu.exec()事件.globalPos()作为参数启动菜单对象。

这种治理上下文菜单的形式有点简单。然而,它使您能够很好地管制调用上下文菜单时产生的状况。例如,您能够依据应用程序的状态等启用或禁用菜单选项。

留神:在持续本节之前,您须要禁用您在上一节中编写的代码。为此,只需转到的初始化程序 Window 并正文掉调用 self._createContextMenu().

以下是如何从新实现示例应用程序的上下文菜单,笼罩主窗口对象上的事件处理程序办法:

class Window(QMainWindow):
    # Snip...
    def contextMenuEvent(self, event):
        # Creating a menu object with the central widget as parent
        menu = QMenu(self.centralWidget)
        # Populating the menu with actions
        menu.addAction(self.newAction)
        menu.addAction(self.openAction)
        menu.addAction(self.saveAction)
        menu.addAction(self.copyAction)
        menu.addAction(self.pasteAction)
        menu.addAction(self.cutAction)
        # Launching the menu
        menu.exec(event.globalPos())

在 中 contextMenuEvent(),您首先创立一个 QMenu 对象 ( menu)centralWidget 作为其父小部件。接下来,您应用.addAction. 最初,调用.exec()上 QMenu 的对象,以显示在屏幕上。

的第二个参数.contextMenuEvent()示意该办法捕捉的事件。在这种状况下,event 将右键单击应用程序的地方小部件。

在对 的调用中.exec(),您将其 event.globalPos()用作参数。当用户单击 PyQt 窗口或小部件时,此办法返回鼠标指针的全局地位。鼠标地位将通知.exec()窗口上显示上下文菜单的地位。

如果您应用这些新更改运行示例应用程序,那么您将取得与上一节中雷同的后果。

组织上下文菜单选项

与菜单和工具栏不同,在上下文菜单中,您不能应用.addSeparator()增加分隔符并依据它们之间的关系在视觉上分隔菜单选项。在组织上下文菜单时,您须要创立一个分隔符操作:

separator = QAction(parent)
separator.setSeparator(True)

.setSeparator(True)对动作对象的调用将把该动作变成一个分隔符。实现分隔符操作后,您须要应用 将其插入上下文菜单中的正确地位 QMenu.addAction()。

如果您回顾一下您的示例应用程序,那么您可能心愿在视觉上将来自 File 菜单的选项与来自 Edit 菜单的选项离开。为此,您能够更新.contextMenuEvent():

class Window(QMainWindow):
    # Snip...
    def contextMenuEvent(self, event):
        # Snip...
        menu.addAction(self.saveAction)
        # Creating a separator action
        separator = QAction(self)
        separator.setSeparator(True)
        # Adding the separator to the menu
        menu.addAction(separator)
        menu.addAction(self.copyAction)
        # Snip...

在前两行突出显示的行中,您创立了分隔符操作。在第三个突出显示的行中,您应用 将分隔符操作增加到菜单中.addAction()。

这将在文件选项和编辑选项之间增加一条水平线。以下是增加此内容的上下文菜单的外观:

当初,您的上下文菜单蕴含一条水平线,可直观地将来自 File 的选项与来自 Edit 的选项离开。这样,您改良了菜单的视觉品质并提供了更好的用户体验。

在菜单和工具栏中连贯信号和插槽

在 PyQt 中,您应用信号和槽为 GUI 应用程序提供性能。每次在 PyQt 小部件上产生诸如鼠标单击、按键或窗口大小调整等事件时,它们都会发出信号。

一个插槽是一个 Python 可调用,您能够连贯到一个小部件的信号,以响应用户事件执行某些操作。

如果连贯了一个信号和一个插槽,那么每次发出信号时都会主动调用该插槽。如果给定的信号未连贯到插槽,则在发出信号时不会产生任何事件。

为了让你的菜单选项和工具栏按钮在用户点击它们时启动一些操作,你须要将底层操作的信号与一些自定义或内置插槽连接起来。

QAction 物体能够收回各种信号。然而,菜单和工具栏中最罕用的信号是.triggered()。每次用户单击菜单选项或工具栏按钮时都会收回此信号。要.triggered()与插槽连贯,您能够应用以下语法:

action = QAction("Action Text", parent)
# Connect action's triggered() with a slot
action.triggered.connect(slot)

在这个例子中,slot 是一个 Python 可调用的。换句话说,slot 能够是一个函数、一个办法、一个类或一个实现 的类的实例.__call__()。

您的示例应用程序中曾经有一组操作。当初,您须要对每次用户单击菜单选项或工具栏按钮时调用的插槽进行编码。转到的定义 Window 并增加以下办法:

class Window(QMainWindow):
    # Snip...
    def newFile(self):
        # Logic for creating a new file goes here...
        self.centralWidget.setText("<b>File > New</b> clicked")

    def openFile(self):
        # Logic for opening an existing file goes here...
        self.centralWidget.setText("<b>File > Open...</b> clicked")

    def saveFile(self):
        # Logic for saving a file goes here...
        self.centralWidget.setText("<b>File > Save</b> clicked")

    def copyContent(self):
        # Logic for copying content goes here...
        self.centralWidget.setText("<b>Edit > Copy</b> clicked")

    def pasteContent(self):
        # Logic for pasting content goes here...
        self.centralWidget.setText("<b>Edit > Paste</b> clicked")

    def cutContent(self):
        # Logic for cutting content goes here...
        self.centralWidget.setText("<b>Edit > Cut</b> clicked")

    def helpContent(self):
        # Logic for launching help goes here...
        self.centralWidget.setText("<b>Help > Help Content...</b> clicked")

    def about(self):
        # Logic for showing an about dialog content goes here...
        self.centralWidget.setText("<b>Help > About...</b> clicked")

这些办法将表演示例应用程序的插槽的角色。每次用户单击相应的菜单选项或工具栏按钮时都会调用它们。

一旦有了提供性能的插槽,就须要将它们与动作的.triggered()信号连接起来。这样,应用程序将依据用户事件执行操作。要进行这些连贯,请转到示例应用程序并将以下办法增加到 Window:

class Window(QMainWindow):
    # Snip...
    def _connectActions(self):
        # Connect File actions
        self.newAction.triggered.connect(self.newFile)
        self.openAction.triggered.connect(self.openFile)
        self.saveAction.triggered.connect(self.saveFile)
        self.exitAction.triggered.connect(self.close)
        # Connect Edit actions
        self.copyAction.triggered.connect(self.copyContent)
        self.pasteAction.triggered.connect(self.pasteContent)
        self.cutAction.triggered.connect(self.cutContent)
        # Connect Help actions
        self.helpContentAction.triggered.connect(self.helpContent)
        self.aboutAction.triggered.connect(self.about)

此办法会将您所有操作的.triggered()信号与其各自的插槽或回调连接起来。通过此更新,您的示例应用程序将在 QLabel 您设置为地方小部件的对象上显示一条音讯,告诉您单击了哪个菜单选项或工具栏按钮。

在 的状况下 exitAction,您将其 triggered()信号与内置插槽连贯 QMainWindow.close()。这样,如果您抉择 File → Exit,那么您的应用程序将敞开。

最初,转到 的初始化程序 Window 并增加对 的调用._connectActions():

class Window(QMainWindow):
    """Main Window."""
    def __init__(self, parent=None):
        # Snip...
        # self._createContextMenu()
        self._connectActions()

通过此最终更新,您能够再次运行该应用程序。以下是所有这些更改的工作原理:

如果单击菜单选项、工具栏按钮或上下文菜单选项,则应用程序窗口地方的标签会显示一条音讯,批示已执行的操作。此性能在学习环境之外不是很有用,但它能够让您理解如何在用户与 GUI 交互时让您的应用程序执行事实世界的操作。

最初,当您抉择 File → Exit 时,应用程序将敞开,因为 的.triggered()信号 exitAction 已连贯到内置插槽 QMainWindow.close()。

作为练习,您能够尝试为查找和替换子菜单中的查找 … 和替换 … 选项创立自定义插槽,而后将它们的信号连贯到这些插槽以使其失效。您还能够尝试应用您在本节中编写的插槽并尝试用它们做新的事件。.triggered()

动静填充 Python 菜单

为应用程序创立菜单时,有时须要应用创立应用程序 GUI 时未知的选项填充这些菜单。例如,文本编辑器中的“关上最近”菜单显示最近关上的文档列表。您无奈在创立应用程序的 GUI 时填充此菜单,因为每个用户都会关上不同的文档,并且无奈提前晓得此信息。

在这种状况下,您须要动静填充菜单以响应用户操作或应用程序的状态。QMenu 有一个称为.aboutToShow()您能够连贯到自定义插槽的信号,以在菜单对象显示在屏幕上之前动静填充它。

要持续开发示例应用程序,假如您须要在文件下创立一个关上最近的子菜单,并用最近关上的文件或文档动静填充它。为此,您须要运行以下步骤:

  1. 在 File 下创立 Open 最近的子菜单。
  2. 编写动静生成操作以填充菜单的自定义插槽。
  3. 将.aboutToShow()菜单信号与自定义插槽连贯。

上面是创立子菜单的代码:

class Window(QMainWindow):
    # Snip...
    def _createMenuBar(self):
        # Snip...
        fileMenu.addAction(self.openAction)
        # Adding an Open Recent submenu
        self.openRecentMenu = fileMenu.addMenu("Open Recent")
        fileMenu.addAction(self.saveAction)
        # Snip...

在突出显示的行中,您在“文件”菜单下增加一个题目为 的子菜单 ”Open Recent”。这个子菜单还没有菜单选项。您须要动态创建操作以填充它。

您能够通过编写一种办法来动态创建操作并将它们增加到子菜单来实现此目标。这是一个示例,显示了您能够应用的个别逻辑:

from functools import partial
# Snip...

class Window(QMainWindow):
    # Snip...
    def populateOpenRecent(self):
        # Step 1. Remove the old options from the menu
        self.openRecentMenu.clear()
        # Step 2. Dynamically create the actions
        actions = []
        filenames = [f"File-{n}" for n in range(5)]
        for filename in filenames:
            action = QAction(filename, self)
            action.triggered.connect(partial(self.openRecentFile, filename))
            actions.append(action)
        # Step 3. Add the actions to the menu
        self.openRecentMenu.addActions(actions)

在 中.populateOpenRecent(),首先应用 删除菜单中的旧选项(如果有).clear()。而后增加用于动态创建和连贯操作的逻辑。最初,您应用 将操作增加到菜单中.addActions()。

在 for 循环中,您应用 functools.partial()来连贯.triggered()信号,.openRecentFile()因为您想 filename 作为参数传递给.openRecentFile()。当将信号与须要额定参数的插槽连贯时,这是一种十分有用的技术。要使其失常工作,您须要 partial()从 functools.

留神:本示例第二步中的逻辑并没有真正加载最近关上的文件列表。它只是创立了 list 五个假如文件中的一个,其惟一目标是展现实现此技术的办法。

下一步是连贯.aboutToShow()的信号.openRecentMenu 到.populateOpenRecent()。为此,请在开端增加以下行._connectActions():

class Window(QMainWindow):
    # Snip...
    def _connectActions(self):
        # Snip...
        self.aboutAction.triggered.connect(self.about)
        # Connect Open Recent to dynamically populate it
        self.openRecentMenu.aboutToShow.connect(self.populateOpenRecent)

在突出显示的行中,您将.aboutToShow 信号与连贯.populateOpenRecent()。这可确保您的菜单在显示之前就被填充。

当初您须要编码.openRecentFile()。这是当您的用户单击任何动态创建的操作时您的应用程序将调用的办法:

class Window(QMainWindow):
    # Snip...
    def openRecentFile(self, filename):
        # Logic for opening a recent file goes here...
        self.centralWidget.setText(f"<b>{filename}</b> opened")

此办法将更新 QLabel 您用作示例应用程序的地方小部件的对象的文本。

以下是动态创建的子菜单在实践中的工作形式:

当您的鼠标指针悬停在关上最近菜单上时,菜单会收回.aboutToShow()信号。这会导致调用.populateOpenRecent(),从而创立并连贯操作。如果单击文件名,您将看到地方标签相应地更改以显示音讯。

定义菜单和工具栏选项的键盘快捷键

键盘快捷键是 GUI 应用程序中的一项重要性能。键盘快捷键是一个组合键,您能够在键盘上按下它以快速访问应用程序中的一些最常见选项。

以下是键盘快捷键的一些示例:
• Ctrl+ 将 C 某些内容复制到剪贴板。
• Ctrl+ V 从剪贴板粘贴一些货色。
• Ctrl+ Z 吊销上次操作。
• Ctrl+ O 关上文件。
• Ctrl+ S 保留文件。

在上面的局部中,您将学习如何向应用程序增加键盘快捷键以进步用户的工作效率和体验。

应用按键序列

到目前为止,您曾经理解到这 QAction 是一个用于填充菜单和工具栏的多功能类。QAction 还提供了一种用户敌对的形式来定义菜单选项和工具栏按钮的键盘快捷键。

QAction 施行.setShortcut(). 此办法将 QKeySequence 对象作为参数并返回键盘快捷键。
QKeySequence 提供了几个构造函数。在本教程中,您将理解其中两个:

  1. QKeySequence(ks, format)将基于字符串的键序列 (ks) 和格局 (format) 作为参数并创立一个 QKeySequence 对象。
  2. QKeySequence(key)承受一个 StandardKey 常量作为参数并创立一个 QKeySequence 与底层平台上的键序列匹配的对象。

第一个构造函数辨认以下字符串:

• “Ctrl”
• “Shift”
• “Alt”
• “Meta”

您能够通过将这些字符串与字母、标点符号、数字、命名键(Up、Down、Home)和功能键(”Ctrl+S”、”Ctrl+5″、”Alt+Home”、”Alt+F4″)组合来创立基于字符串的键序列。您最多能够在逗号分隔列表中传递四个基于字符串的键序列。

注:无关在不同平台上的规范快捷的残缺参考,请参阅规范快捷键局部中的 QKeySequence 文档。

如果您正在开发多平台应用程序并心愿保持每个平台的规范键盘快捷键,则第二个构造函数很不便。

例如,QKeySequence.Copy 将返回用于将对象复制到剪贴板的平台规范键盘快捷键。

留神:无关 PyQt 提供的规范密钥的残缺参考,请参阅 QKeySequence.StandardKey 文档。

有了对于如何在 PyQt 中为操作定义键盘快捷键的个别背景,您能够返回示例应用程序并增加一些快捷键。为此,您须要更新._createActions():

from PyQt5.QtGui import QKeySequence
# Snip...

class Window(QMainWindow):
    # Snip...
    def _createActions(self):
        # File actions
        # Snip...
        # Using string-based key sequences
        self.newAction.setShortcut("Ctrl+N")
        self.openAction.setShortcut("Ctrl+O")
        self.saveAction.setShortcut("Ctrl+S")
        # Edit actions
        # Snip...
        # Using standard keys
        self.copyAction.setShortcut(QKeySequence.Copy)
        self.pasteAction.setShortcut(QKeySequence.Paste)
        self.cutAction.setShortcut(QKeySequence.Cut)
        # Snip...

您首先须要导入 QKeySequence. 在外面._createActions(),前三个突出显示的行应用基于字符串的键序列创立键盘快捷键。这是向您的操作增加键盘快捷键的疾速办法。在后三个突出显示的行中,您用于 QKeySequence 提供规范键盘快捷键。

如果您运行带有这些增加的示例应用程序,那么您的菜单将如下所示:

您的菜单选项当初会在其右侧显示键盘快捷键。如果您按这些组合键中的任何一个,那么您将执行相应的操作。

应用键盘加速器

您能够应用另一种代替办法将键盘快捷键或键盘加速器增加到应用程序的菜单选项中。

您可能曾经留神到,当您为菜单或菜单选项设置文本时,通常会 & 在文本中插入一个与符号 ()。这样做是为了当显示在菜单或菜单选项的文本中时,紧跟在&符号之后的字母将带有下划线。例如,如果您在“文件”菜单 ()的题目中的字母 F 之前搁置一个与号,则在显示菜单题目时 F 将带有下划线。”&File”

留神:如果您须要在菜单文本上显示与号符号,则须要应用双与号 (&&) 来回避此符号的默认性能。

在菜单栏的状况下,应用与号容许您通过 Alt 与菜单题目中带下划线的字母组合按下来调用任何菜单。

启动菜单后,您能够通过按选项文本中带下划线的字母来拜访任何菜单选项。例如,在文件中,您能够通过按字母 E 拜访退出选项。

留神:当您应用与号来提供键盘加速器时,请记住在同一菜单下不能有两个选项共享雷同的拜访字母。

如果您将 C 设置为 Copy 选项的拜访字母,则不能将 C 设置为 Cut 选项的拜访字母。换句话说,在给定的菜单下,拜访字母必须是惟一的。

此性能将容许您为喜爱应用键盘来解决您的应用程序的用户提供疾速键盘加速器。此技术对于不提供显式键盘快捷键的选项特地有用。

创立菜单和工具栏:最佳实际和技巧

当您应用 Python 和 PyQt 创立菜单和工具栏时,您应该遵循一些通常被认为是 GUI 编程最佳实际的规范。这是一个疾速列表:

1. 依照广泛承受的顺序排列菜单 。例如,如果您有一个文件菜单,那么它应该是从左到右的第一个菜单。如果你有一个编辑菜单,那么它应该是第二个。帮忙应该是最左边的菜单,依此类推。
2. 应用您正在开发的应用程序类型的罕用选项填充您的菜单。例如,在文本编辑器中,文件菜单通常包含诸如 New、Open、Save 和 Exit 之类的选项。编辑菜单通常包含复制、粘贴、剪切、吊销等选项。
3. 对罕用选项应用规范键盘快捷键。例如,应用 Ctrl+ C 进行复制,Ctrl+ V 用于粘贴,Ctrl+ X 用于切割,等等。
4. 应用分隔符分隔不相干的选项。这些视觉提醒将使您的应用程序更易于导航。
5. 将省略号 (…) 增加到启动其余对话框的选项的题目。例如,应用 Save As… 而不是 Save As,应用 About… 而不是 About,等等。
6. & 在菜单选项中应用与号 () 来提供方便的键盘加速器。例如,”&Open 代替 ”Open”,”&Exit” 代替 ”Exit”。

如果您遵循这些准则,那么您的 GUI 应用程序将为您的用户提供相熟且迷人的体验。

在 PyQt 中构建 Python 状态栏

甲状态栏是程度面板通常在 GUI 应用程序搁置在底部的主窗口。它的次要目标是显示无关应用程序以后状态的信息。状态栏也能够分为多个局部,以显示每个局部的不同信息。

依据 Qt 文档,状态指示器分为三种类型:

  1. 长期 指示器会在短时间内占据简直整个状态栏以显示工具提醒文本、菜单项和其余工夫敏感信息。
  2. 一般 指示器占据状态栏的一部分并显示用户可能心愿定期参考的信息,例如文字处理器中的字数统计。这些可能会被长期指标临时暗藏。
  3. 永恒 指示器始终显示在状态栏中,即便长期指示器被激活也是如此。它们用于显示无关应用程序以后模式的重要信息,例如按下 Caps Lock 键的工夫。

您能够应用以下选项之一向主窗口款式的应用程序增加状态栏:

• 调用.statusBar()你的 QMainWindow 对象。.statusBar()创立并返回主窗口的空状态栏。
• 创立一个 QStatusBar 对象,而后.setStatusBar()应用状态栏对象作为参数调用主窗口。这样,.setStatusBar()将您的状态栏对象设置为主窗口的状态栏。

在这里,您有两种代替实现来向示例应用程序增加状态栏:

# 1. Using .statusBar()
def _createStatusBar(self):
    self.statusbar = self.statusBar()

# 2. Using .setStatusBar()
def _createStatusBar(self):
    self.statusbar = QStatusBar()
    self.setStatusBar(self.statusbar)

两种实现产生雷同的后果。然而,大多数状况下,您将应用第一个实现来创立状态栏。请留神,要使第二个实现工作,您须要 QStatusBar 从 PyQt5.QtWidgets.

将上述实现之一增加到您的应用程序 Window,而后调用._createStatusBar()类初始值设定项。通过这些增加,当您再次运行您的应用程序时,您将看到一个如下所示的窗口:

您的应用程序当初在其主窗口底部有一个状态栏。状态栏简直不可见,但如果仔细观察,您会留神到窗口右下角有一个小的虚线三角形。

显示长期状态音讯

状态栏的次要目标是向应用程序的用户显示状态信息。要在状态栏中显示长期状态音讯,您须要应用 QStatusBar.showMessage(). 此办法采纳以下两个参数:

  1. message 将状态批示音讯作为字符串保留。
  2. timeout 保留音讯将显示在状态栏上的毫秒数。

如果 timeout 是 0,这是其默认值,则音讯将保留在状态栏上,直到您调用.clearMessage()或.showMessage()状态栏上。

如果您的状态栏上有一条流动音讯并且您.showMessage()用新音讯呼叫,那么新音讯将覆盖或替换旧音讯。

转到您的示例应用程序并将以下行增加到._createStatusBar():

class Window(QMainWindow):
    # Snip...
    def _createStatusBar(self):
        self.statusbar = self.statusBar()
        # Adding a temporary message
        self.statusbar.showMessage("Ready", 3000)

最初一行._createStatusBar()将使您的应用程序 Ready 在应用程序的状态栏上显示一条音讯 3000 几毫秒:

运行应用程序时,状态栏会显示音讯 Ready。之后 3000 毫秒,此音讯隐没,状态栏被革除,并筹备展示出新的状态信息。

在状态栏中显示永恒音讯

您还能够在应用程序的状态栏上显示永恒音讯。一条永恒音讯让用户理解应用程序的一些个别状态。例如,在文本编辑器中,您可能心愿显示一条永恒音讯,其中蕴含无关以后关上文件的文本编码的信息。

要将永恒音讯增加到状态栏,请应用 QLabel 对象来保留音讯。而后通过调用将标签增加到状态栏.addPermanentWidget()。此办法将给定的小部件永恒增加到以后状态栏。小部件的父级设置为状态栏。

.addPermanentWidget() 采纳以下两个参数:

  1. widget保留要增加到状态栏的小部件对象。这个角色的一些罕用小部件 QLabel,QToolButton 以及 QProgressBar。
  2. stretch用于随着状态栏的增长和膨胀计算小部件的适合大小。它默认为 0,这意味着小部件将占用起码的空间。

请记住,永恒小部件不会被长期音讯遮蔽或替换。.addPermanentWidget()在状态栏的右侧定位小部件。

留神:您.addPermanentWidget()不仅能够应用在状态栏上显示永恒音讯,还能够向用户显示进度条以监控给定操作的持续时间。您还能够在状态栏上提供按钮,以容许用户在文本编辑器上更改文件编码等属性。

当您在状态栏上应用这些类型的小部件时,尽量保持应用最罕用的小部件来满足您正在开发的应用程序类型。这样,您的用户就会有宾至如归的感觉。

假如您想将示例利用程序转换为文本编辑器,并且您想向状态栏增加一条音讯,以显示无关以后文件字数的信息。为此,您能够创立一个调用的办法.getWordCount(),而后应用.addPermanentWidget()和 QLabel 对象增加永恒音讯:

class Window(QMainWindow):
    # Snip...
    def getWordCount(self):
        # Logic for computing the word count goes here...
        return 42

该办法增加了计算以后打开文档中字数的逻辑。当初,您能够将此信息显示为永恒音讯:
class Window(QMainWindow):

# Snip...
  def _createStatusBar(self):
      self.statusbar = self.statusBar()
      # Adding a temporary message
      self.statusbar.showMessage("Ready", 3000)
      # Adding a permanent message
      self.wcLabel = QLabel(f"{self.getWordCount()} Words")
      self.statusbar.addPermanentWidget(self.wcLabel)

在最初两行中,您首先创立一个 QLabel 对象 (wcLabel) 来保留无关字数的音讯。要创立音讯,请应用 f -string,在其中插入对 的调用.getWordCount()以获取字数信息。而后应用 将标签增加到状态栏.addPermanentWidget()。

在这种状况下,您将 QLabel 对象创立为实例属性,因为须要依据用户对以后文件所做的更改来更新字数。

如果您应用此更新运行应用程序,那么您将在状态栏的右侧看到字数统计音讯:

状态栏会显示一条音讯,告诉用户假如以后文件中的字数。在状态栏中向用户显示永恒信息或其余选项的能力十分有用,能够帮忙您极大地改善应用程序的用户体验。

向操作增加帮忙提醒

在创立 GUI 应用程序时,向用户提供无关利用程序界面特定性能的帮忙提醒十分重要。帮忙提醒是短消息,可为用户提供无关应用程序提供的某些选项的疾速指南。

PyQt 操作容许您定义以下类型的帮忙提醒:

状态提醒 是当用户将鼠标指针悬停在菜单选项或工具栏按钮上时应用程序显示在状态栏上的帮忙提醒。默认状况下,状态提醒蕴含一个空字符串。
工具提醒 是当用户将鼠标指针悬停在工具栏按钮或小部件上时应用程序显示为浮动音讯的帮忙提醒。默认状况下,工具提醒蕴含标识手头操作的文本。

留神:PyQt 还提供了 What’s This 帮忙提醒,您能够在小部件和动作中应用它来显示对小部件或动作提供的性能的更丰盛的形容。然而,该主题超出了本教程的范畴。

要理解帮忙提醒的工作原理,您能够向示例应用程序增加一些状态提醒和工具提醒。转到._createActions()并增加以下代码行:

class Window(QMainWindow):
    # Snip...
    def _createActions(self):
        # File actions
        # Snip...
        self.saveAction.setShortcut("Ctrl+S")
        # Adding help tips
        newTip = "Create a new file"
        self.newAction.setStatusTip(newTip)
        self.newAction.setToolTip(newTip)
        # Edit actions
        self.copyAction = QAction(QIcon(":edit-copy.svg"), "&Copy", self)
        # Snip...

三个突出显示的即将音讯设置 ”Create a new file” 为“新建”选项的状态和工具提醒。如果您当初运行该应用程序,您将看到 New 选项向用户显示了一个简短但描述性的帮忙提醒:

当您单击 File 菜单并将鼠标指针放在 New 上时,您能够看到状态栏左侧显示的帮忙提醒音讯。另一方面,如果您将鼠标指针移到“新建”工具栏按钮上,则您能够在状态栏上看到音讯,也能够在鼠标指针旁边看到一个小的浮动框。

通常,向 Python 菜单和工具栏增加帮忙提醒被认为是最佳实际。它将使您的 GUI 应用程序更易于用户导航和学习。作为最初的练习,您能够持续向示例应用程序的其余操作增加帮忙提醒,并查看实现后的成果。

论断

菜单、工具栏和状态栏是大多数 GUI 应用程序的常见且重要的图形组件。您能够应用它们为您的用户提供一种快速访问应用程序选项和性能的办法。它们还使您的应用程序看起来精美和业余,并为您的用户提供杰出的体验。

在本教程中,您学习了如何:

• 以编程形式创立菜单、工具栏和状态栏
• 应用 PyQt 操作填充菜单和工具栏
• 应用状态栏提供状态信息

在此过程中,您学习了一些在 GUI 应用程序中增加和应用菜单、工具栏和状态栏时值得思考的最佳编程实际。

您还编写了一个示例应用程序,在其中利用了您对菜单和工具栏的所有常识。您能够通过单击上面的框来获取该应用程序的残缺源代码和其余资源:

点击关注,第一工夫理解华为云陈腐技术~

退出移动版