20.7 菜单上是什么

    我们的温度转换 GUI 上有一些按钮,用来完成转换。很多程序还会提供一个菜单来完成某些功能。有时这些工作也可以通过点击一个按钮来完成,那为什么要采用两种不同方法完成同样的事情呢?

    空标题文档 - 图1

    是这样的,有些用户更习惯使用菜单,而不喜欢点击按钮。复杂的程序可能会有很多功能,如果不使用菜单就会需要很多的按钮,这会使 GUI 变得杂乱无章。另外,菜单还可以通过键盘来操作,有些人发现,与把手从键盘拿开再使用鼠标相比,直接使用菜单速度会更快。

    下面来增加一些菜单项,为用户提供另外一种完成温度转换的途径。我们也可以添加 File > Exit(文件 > 退出),几乎每个程序都有这个菜单项。

    PyQt 内置了一种创建和编辑菜单的方式。如果你在 Designer 的左上角找一下,会看到 Type Here(在此输入),这就是创建菜单的地方。在很多程序中,第一个菜单项都是 File(文件)菜单,所以我们也从这个菜单开始。点击写有 Type Here 的区域,输入 File,然后按回车(Enter)。你应该可以看到 File 菜单出现了,同时在其旁边和下面还有可以输入更多菜单的区域,如下图所示。

    空标题文档 - 图2

    增加菜单项

    在 File 菜单下,我们要添加一个 Exit(退出)菜单项。在 File 下方写有 Type Here 的区域输入 Exit,然后按回车。

    现在我们来添加一个菜单项用于转换温度(假如用户不想使用按钮的话)。在 File 菜单右侧写有 Type Here 的区域,输入 Convert,然后在下方分别创建两个菜单项:C to F(摄氏转华氏)和 F to C(华氏转摄氏)。完成之后的样子应该像下图这样:

    空标题文档 - 图3

    如果你看一下 Qt Designer 窗口右上角的对象查看器(Object Inspector),会看到这样的东西(如下图所示):

    空标题文档 - 图4

    你可以看到 File 和 Convert(转换)菜单,以及 Exit、C to F 和 F to C 菜单项。在 PyQt 的术语中,菜单项是 QAction 类的实例。这样命名是有含义的,因为你希望在选中菜单项的时候有一些“行为”(action)发生。

    将你修改过的 Designer 文件保存为 tempconv_menu.ui。

    在 Mac 上,你还需要将菜单栏对象的 nativeMenuBar 属性勾选掉。(它应该是属性编辑器中的最后一个属性。)否则菜单会与 Python 的主菜单冲突,PyQt 程序的File(文件)菜单会消失。

    现在你有了菜单项(或者说行为),你需要将它们的事件绑定(或连接)到事件处理器。对于 C to F 和 F to C 菜单项来说,我们已经有了事件处理器,即我们之前为按钮编写的事件处理器。我们希望点击菜单项时发生的事情和点击按钮一样。所以只需要将菜单项和之前的事件处理器连接起来即可。

    对于菜单项(行为)来说,我们希望处理的不是 clicked 事件,而是一个 triggered 事件。我们需要连接到事件处理器的菜单项叫做 action_CtoF,而我们要连接的事件处理器则是按钮的事件处理器,叫做 btn_CtoF_clicked。将菜单项和事件处理器连接起来的代码是这样的:

    self.action_CtoF.triggered.connect(self.btn_CtoF_clicked)

    同样,还有一个 FtoC 菜单项。

    对于 Exit 菜单项而言,我们需要创建一个新的事件处理器来绑定事件。我们将事件处理器命名为 menuExit_selected,连接事件的代码是这样的:

    self.actionExit.triggered.connect(self.menuExit_selected)

    Exit 菜单项的事件处理器的函数体其实只有一行代码,将窗口关闭即可:

    def menuExit_selected(self):
    self.close()

    最后,将当前加载的 UI 文件(第三行)改为添加菜单之后保存的文件,即 tempconv_menu.ui。

    做完上面这些修改之后,整个代码应该如下面的代码清单所示。

    代码清单 20-4 带菜单的完整的温度转换程序

    空标题文档 - 图5

    热键

    我们在前面说过,有些人喜欢用菜单而不喜欢用按钮,一个原因是菜单可以在不使用鼠标的情况下直接使用键盘操作。现在,我们的菜单已经可以用鼠标来操作了,但是还不能用键盘来操作。我们需要为菜单添加热键。

    热键(也叫快捷键)让你可以使用键盘来选中菜单项。在 Windows 和 Linux 下,通过 Alt 键来激活菜单系统。(我们会马上讲到 Mac OS。)当按下 Alt 键时,你会看到各个菜单项中有个字母变成高亮显示了,通常会有一条下划线。划线的字母即是可以用来激活菜单的键。比如,要进入 File 菜单,就按 Alt-F。也就是说,先按住 Alt 键,再按 F 键,即可看到 File 菜单中的各项,同时也可以看到每个菜单项的热键是什么。在 Python Shell 窗口中试一下(见下图)。

    空标题文档 - 图6

    要打开一个新窗口,则使用 Alt-F-N。(按下 Alt 键,按 F 键,再按 N 键。)

    现在,我们来为温度转换 GUI 程序定义菜单的热键。要定义热键,只需在想让其成为热键的字母前加上 & 字符即可。你可以在菜单(比如 File)的 Title 属性或者菜单项(比如 Exit)的 Text 属性中完成。对于 File 菜单来说,一般使用 F 作为热键;对于 Exit 菜单项来说,一般使用 X 作为热键。所以将 File 改为 &File,将 Exit 改为 E&xit。

    空标题文档 - 图7

    我们需要为 Convert 菜单项指定热键。我们为 Convert 使用 C,Celsius to Fahrenheit 使用 C,华氏转摄氏使用 F 吧。所以我们将对应的文本分别改为 &Convert、&C to F 和 &F to C。热键组合分别是 Alt-C-C 和 Alt-C-F。

    在 Qt Designer 中定义完热键之后,就不需要再做其他事情了,即没有新的代码需要编写。PyQt 和操作系统会处理热键的下划线和键盘输入。你只需保存 UI 文件即可,你可以将它存为一个不同的名字,比如 tempconv_menu_hotkeys.ui。如果使用了不同的名字,记得修改代码清单 20-4 中的第三行来加载这个 UI 文件:

    form_class = uic.loadUiType( "tempconv_menu_hotkeys.ui" )[0]

    空标题文档 - 图8

    答案是“没有”。因为所有的 Mac 电脑自诞生之日起就有鼠标(或者触摸板),所以 Mac OS 会假设你会使用鼠标来操作菜单。在 Mac OS 上,菜单项没有键盘快捷键或者热键系统。很多功能都有快捷键,而且其中有一些会和菜单项对应。但你并不能像在 Windows 上那样直接使用热键操作菜单系统。

    这就是温度转换 GUI 的全部内容。在第 22 章,我们将会使用 PyQt 来实现一个 Hangman 游戏。

    你学到了什么

    在这一章,我们学到了以下内容。

    • PyQt。

    • Qt Designer。

    • 构成 GUI 的组件——按钮、文本等。

    • 事件处理器——让组件具体做事情。

    • 菜单项和热键。

    测试题

    1. 构成 GUI 的按钮、文本域等元素有哪 3 个名字?

    2. 要进入一个菜单,可以与 ALT 同时按下哪个字母?

    3. Qt Designer 文件的文件名末尾必须加上什么?

    4. 使用 PyQt 的 GUI 中可以包含哪 5 种组件类型?

    5. 要让组件(如按钮)完成某项工作,它需要有一个 __

    6. 菜单中使用哪个特殊字符来定义热键?

    7. PyQt 中微调框的内容总是一个 _

    动手试一试

    1. 我们在第 1 章建立了一个基于文本的猜数程序,另外在第 6 章建立了这个程序的一个简单的 GUI 版本。试着使用 PyQt 建立这个猜数程序的 GUI 版本。

    2. 前面出现微调框无法显示低于 0 的值的问题(卡特在代码清单 20-2 中找出了这个 bug),你发现了吗?修改微调框属性来解决这个问题。确保对范围上下界都做修改,使微调框不仅能显示非常高的温度,也能显示非常低的温度。(也许你的用户除了想转换冥王星上的温度,还想转换水星和金星上的温度呢!)