GTK 中操作概述 [src]
本章详细介绍了 GTK 如何使用操作将可激活的 UI 元素连接到回调。GTK 继承了底层架构,其中包括 GAction
和 GMenu
,用于从 GIO 库中描述抽象操作和菜单。
操作基础知识
GAction
主要是一种方法,用于告知工具包程序中某个功能,并为其提供名称。
操作纯功能性。它们不包含任何表示性信息。
一个操作具有四条与其关联的信息
- 作为标识符的名称(通常是小写、未翻译的英语字符串)
- 启用标志,指示该操作可否激活(类似于控件的“敏感”属性)
- 对于有状态操作(例如用于切换的布尔值),一个可选的状态值
- 一个可选的参数类型,在激活操作时使用
一个操作支持两种操作。你可以激活它,这需要传递正确类型的参数。而对于有状态操作,你可以请求将操作状态更改为正确类型的新状态值。
以下是一些有关操作的规则
- 名称不可变(即它永远不会改变),且永远不会为
NULL
- 启用标志可以改变
- 参数类型不可变
- 参数类型可选:它可以为
NULL
- 如果参数类型为
NULL
,则操作激活必须在没有参数(即:一个NULL
的 GVariant 指针)的情况下完成 - 如果参数类型不为
NULL
,则参数必须有此类型 - 状态可以改变,但它不能改变类型
- 如果该操作在创建时是有状态的,那么它将始终有一个状态,而且它将始终具有完全相同的类型(例如布尔值或字符串)
- 如果该操作在创建时是无状态的,那么它将永远不能有一个状态
- 你只能对有状态操作请求状态更改,且只能请求将状态更改为与现有状态相同类型的某个值
一个操作没有任何表示性信息,例如标签、图标或从中创建控件的方法。
操作状态和参数
应用程序中的大多数操作将是没有任何参数的无状态操作。它们通常显示为没有特殊装饰的菜单项。一个示例为“退出”。
有状态操作用于表示具有某种密切关联的状态的操作。一个很好的示例是一个“全屏”操作。对于这种情况,你希望在全屏选项处于活动时在菜单项旁边看到一个复选标记。这通常称为切换操作,它有一个布尔值状态。按照惯例,切换操作没有用于激活的参数类型:激活操作始终切换状态。
另一个常见情况是操作表示给定类型的可能值的枚举(通常为字符串)。这通常称为单选操作,通常在用户界面中表示为单选按钮或单选菜单项,有时为组合框。一个很好的例子是“文字对齐”可能的取值“左”、“中”和“右”。根据惯例,这些类型的操作的参数类型等于它们的状态类型,而使用特定参数值激活它们等效于将它们的状态更改为该 值。
处理单选按钮的这种方法不同于许多其他操作系统,例如 GtkAction
。使用 GAction
时,“文字对齐”只有一个操作,“左”、“中”和“右”是该操作可能的 state。没有三个单独的“左对齐”、“中对齐”和“右对齐”操作。
动作的最后一种常见类型是带参数的状态操作。这通常用于诸如“打开书签”之类的动作,其中动作的参数是待打开的书签的标识符。
由于某些类型的动作在没有参数时无法调用,因此通常在从将调用的位置(例如将状态设置为特定值或从打开特定书签的菜单项)引用操作时指定参数非常重要。在这些上下文中,用于操作参数的值通常称为目标 操作。
即使切换操作具有状态,它们也没有参数。因此,在引用它们时不需要目标值 — 它们将在激活时始终切换 on。
允许使用 GAction
(例如 GMenuModel
和 GtkActionable
)的大多数 API 都允许使用详细的操作名称。这是一种使用单个 字符串指定操作名称和操作目标的便捷方式。
如果操作目标是一个没有特殊字符(即:只有字母数字、“_”和“.”)的字符串,那么可以使用“justify 右对齐”形式的详细操作名称,以指定目标为 left 的对齐操作。
如果操作目标不是字符串或包含特殊字符,可以使用更通用的格式“action-name(5)”,其中“5”是任何有效的文本格式 GVariant(即:可以被 g_variant_parse() 解析的字符串)。另一个示例是 “open-bookmark(‘http://gnome.org/)’”。
您可以使用 g_action_parse_detailed_name()
和 g_action_print_detailed_name()
来转换详细的操作名称和拆分的操作名称和目标值,但通常不需要。大多数 API 都将提供使用 targets 指定操作的两种方法。
操作作用域
操作始终采用它们 操作的特定对象为作用域。
在 GTK 中,操作通常采用应用程序或窗口为作用域,但任何小部件都可以与它关联操作。
采用窗口为作用域的操作应该是那些专门影响该窗口的操作。这些操作类似于“全屏”和“关闭”,或者在窗口包含文档时类似于“保存”和 “打印”。
影响整个应用程序而不是某个特定窗口的操作的作用域是应用程序。这些操作类似于“关于”和 “首选项”。
如果特定操作适用于窗口,那么它的作用范围就是特定窗口。换句话说,如果你的应用程序有一个适用于窗口的“全屏”操作,并且它有三个窗口,那么它将有三个全屏操作:每个窗口一个 全屏操作。
为每个窗口使用单独的操作,以便每个窗口都可以为操作的每个实例拥有单独的状态,并且能够按窗口 对操作的启用状态进行控制。
通过 GActionMap
接口或使用 gtk_widget_insert_action_group() 将动作添加到它们相关的范围(应用程序、窗口或小组件)。可以通过使用 gtk_widget_class_install_action() 全局添加对小组件类所有实例都将相同的动作。
动作组和动作映射
动作很少独立出现。通常有成组的相关动作,它们由 GActionGroup
接口的实例表示。
动作映射是动作组的变体,允许在查找时更改动作名称。在 GTK 中,约定是向动作名称添加前缀表示动作的范围,例如“app.”表示指定应用程序范围的动作或“win.”表示指定窗口范围的动作。
当在 GActionMap 中引用动作时,仅使用动作本身的名称(例如:“quit”,而不是“app.quit”)。“app.quit”形式仅在从诸如 GMenu
或 GtkActionable
小组件(其中动作的范围尚未了解)的位置引用动作时使用。
GtkApplication
和 GtkApplicationWindow
实现 GActionMap
接口,因此您可直接向它们添加动作。对于其他小组件,请使用 gtk_widget_insert_action_group()
向其中添加动作。
如果您想同时插入几个动作,使用 GActionEntry
通常更快捷且简单。
将动作连接到小组件
通过设置 ::action-name 属性,可以连接任何实现 GtkActionable
接口的小组件到动作。如果动作有参数,您还需设置 ::action-target 属性。实现 GtkActionable
的小组件包括 GtkSwitch
、GtkButton
以及它们各自的子类。
获取连接到动作的小组件的另一种方法是使用 GMenu
菜单模型创建菜单。GMenu
提供一种描述典型菜单的抽象方法:项目嵌套组,其中每个项目可有标签、图标和动作。
在 GTK 中,GMenu
的典型用法是使用 gtk_application_set_menubar() 设置应用程序菜单栏。另一种可能更常见的用法是使用 gtk_menu_button_set_menu_model() 为菜单按钮创建弹出窗口。
与传统菜单不同,从菜单模型创建的菜单没有与菜单项关联的键盘加速器。相反,GtkApplication
提供 gtk_application_set_accels_for_action()
API 将键盘快捷方式与动作关联。
激活
当连接有动作的小组件被激活时,GTK 通过在小组件层级中向上搜索来查找要激活的动作,以查找匹配的动作,最后在 GtkApplication
上结束。
内置动作
GTK 在许多地方将其自身的用途用于动作。应用程序有时可以激活这些内置动作,并且当创建您自己的动作时,您应避免与它们产生命名冲突。
- default.activate
- 激活上下文中的默认小组件(通常为
GtkWindow
、GtkDialog
或GtkPopover
) - clipboard.cut、clipboard.copy、clipboard.paste
- 通常在上下文菜单中使用的对条目、文本视图和标签的剪贴板操作
- selection.delete、selection.select-all
- 对条目、文本视图和标签的选择操作
- color.select、color.customize
- 在
GtkColorChooserWidget
中操作颜色。这些动作不同寻常,因为它们具有非平凡的参数类型 (dddd)。