GTK 中操作概述 [src]

本章详细介绍了 GTK 如何使用操作将可激活的 UI 元素连接到回调。GTK 继承了底层架构,其中包括 GActionGMenu,用于从 GIO 库中描述抽象操作和菜单。

操作基础知识

GAction 主要是一种方法,用于告知工具包程序中某个功能,并为其提供名称。

操作纯功能性。它们不包含任何表示性信息。

一个操作具有四条与其关联的信息

  • 作为标识符的名称(通常是小写、未翻译的英语字符串)
  • 启用标志,指示该操作可否激活(类似于控件的“敏感”属性)
  • 对于有状态操作(例如用于切换的布尔值),一个可选的状态值
  • 一个可选的参数类型,在激活操作时使用

一个操作支持两种操作。你可以激活它,这需要传递正确类型的参数。而对于有状态操作,你可以请求将操作状态更改为正确类型的新状态值。

以下是一些有关操作的规则

  • 名称不可变(即它永远不会改变),且永远不会为 NULL
  • 启用标志可以改变
  • 参数类型不可变
  • 参数类型可选:它可以为 NULL
  • 如果参数类型为 NULL,则操作激活必须在没有参数(即:一个 NULL 的 GVariant 指针)的情况下完成
  • 如果参数类型不为 NULL,则参数必须有此类型
  • 状态可以改变,但它不能改变类型
  • 如果该操作在创建时是有状态的,那么它将始终有一个状态,而且它将始终具有完全相同的类型(例如布尔值或字符串)
  • 如果该操作在创建时是无状态的,那么它将永远不能有一个状态
  • 你只能对有状态操作请求状态更改,且只能请求将状态更改为与现有状态相同类型的某个值

一个操作没有任何表示性信息,例如标签、图标或从中创建控件的方法。

操作状态和参数

应用程序中的大多数操作将是没有任何参数的无状态操作。它们通常显示为没有特殊装饰的菜单项。一个示例为“退出”。

有状态操作用于表示具有某种密切关联的状态的操作。一个很好的示例是一个“全屏”操作。对于这种情况,你希望在全屏选项处于活动时在菜单项旁边看到一个复选标记。这通常称为切换操作,它有一个布尔值状态。按照惯例,切换操作没有用于激活的参数类型:激活操作始终切换状态。

另一个常见情况是操作表示给定类型的可能值的枚举(通常为字符串)。这通常称为单选操作,通常在用户界面中表示为单选按钮或单选菜单项,有时为组合框。一个很好的例子是“文字对齐”可能的取值“左”、“中”和“右”。根据惯例,这些类型的操作的参数类型等于它们的状态类型,而使用特定参数值激活它们等效于将它们的状态更改为该 值。

处理单选按钮的这种方法不同于许多其他操作系统,例如 GtkAction。使用 GAction 时,“文字对齐”只有一个操作,“左”、“中”和“右”是该操作可能的 state。没有三个单独的“左对齐”、“中对齐”和“右对齐”操作。

动作的最后一种常见类型是带参数的状态操作。这通常用于诸如“打开书签”之类的动作,其中动作的参数是待打开的书签的标识符。

由于某些类型的动作在没有参数时无法调用,因此通常在从将调用的位置(例如将状态设置为特定值或从打开特定书签的菜单项)引用操作时指定参数非常重要。在这些上下文中,用于操作参数的值通常称为目标 操作。

即使切换操作具有状态,它们也没有参数。因此,在引用它们时不需要目标值 — 它们将在激活时始终切换 on。

允许使用 GAction(例如 GMenuModelGtkActionable)的大多数 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”形式仅在从诸如 GMenuGtkActionable 小组件(其中动作的范围尚未了解)的位置引用动作时使用。

GtkApplicationGtkApplicationWindow 实现 GActionMap 接口,因此您可直接向它们添加动作。对于其他小组件,请使用 gtk_widget_insert_action_group() 向其中添加动作。

如果您想同时插入几个动作,使用 GActionEntry 通常更快捷且简单。

将动作连接到小组件

通过设置 ::action-name 属性,可以连接任何实现 GtkActionable 接口的小组件到动作。如果动作有参数,您还需设置 ::action-target 属性。实现 GtkActionable 的小组件包括 GtkSwitchGtkButton 以及它们各自的子类。

获取连接到动作的小组件的另一种方法是使用 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
激活上下文中的默认小组件(通常为 GtkWindowGtkDialogGtkPopover
clipboard.cut、clipboard.copy、clipboard.paste
通常在上下文菜单中使用的对条目、文本视图和标签的剪贴板操作
selection.delete、selection.select-all
对条目、文本视图和标签的选择操作
color.select、color.customize
GtkColorChooserWidget 中操作颜色。这些动作不同寻常,因为它们具有非平凡的参数类型 (dddd)。