类
GtkBuilder
描述 [src]
final class Gtk.Builder : GObject.Object
{
/* No available fields */
}
GtkBuilder
会读取用户界面的 XML 描述并实例化所描述的对象。
若要从用户界面描述创建 GtkBuilder
,请调用 gtk_builder_new_from_file()
、gtk_builder_new_from_resource()
或 gtk_builder_new_from_string()
。
在(特殊情况下)需要将多个源的用户界面描述添加到同一 GtkBuilder
中,可以调用 gtk_builder_new()
以获取空生成器,并通过多次调用 gtk_builder_add_from_file()
、gtk_builder_add_from_resource()
或 gtk_builder_add_from_string()
来填充它。
GtkBuilder
会持有它所构建的所有对象的引用,并在最终确定时释放这些引用。此最终确定会导致销毁非 widget 对象或不包含在顶层窗口中的小部件。对于生成器构建的顶层窗口,用户有责任调用 gtk_window_destroy()
以删除它们和它们包含的所有小部件。
函数 gtk_builder_get_object()
和 gtk_builder_get_objects()
可用于通过在 UI 描述中分配给它们的名称访问界面中的小部件。这些函数返回的顶层窗口会在用户通过 gtk_window_destroy()
明确销毁它们之前一直存在。其他小部件要么是生成器构建的更大层次结构的一部分(在这种情况下,您不必担心它们的声明周期),要么没有父级,在这种情况下,必须将它们添加到某些容器中才能使用它们。需要使用 g_object_ref()
引用非小部件对象才能将它们保留在生成器的生命周期之外。
GtkBuilder UI 定义
GtkBuilder
解析指定为 XML 格式的用户界面的文本描述。如果上下文很清楚,我们会将这些描述称为“GtkBuilder UI 定义”或只是“UI 定义”。
UI 定义的结构
UI 定义文件始终以 UTF-8 编码。
顶级元素是 <interface>
。它可以选择采用 “domain” 属性,该属性将使生成器在指定域中使用 dgettext()
查找已翻译的字符串。这还可以通过在生成器上调用 gtk_builder_set_translation_domain()
来完成。例如
<?xml version="1.0" encoding="UTF-8">
<interface domain="your-app">
...
</interface>
要求
目标工具包版本由 <requires>
元素描述,“lib” 属性指定有问题的窗口小组件库(目前唯一支持的值是 “gtk”),而 “version” 属性指定目标版本的形式为 “<major>
.<minor>
”。如果未满足版本要求,GtkBuilder
将出错。例如
<?xml version="1.0" encoding="UTF-8">
<interface domain="your-app">
<requires lib="gtk" version="4.0" />
</interface>
对象
对象被定义为 <interface>
元素的子对象。
对象由 <object>
元素描述,其中可以包含 <property>
元素以设置属性、将信号连接到处理程序的 <signal>
元素以及描述子对象的 <child>
元素。
通常,由 <object>
元素表示的特定类型的对象由 “class” 属性指定。如果尚未加载该类型,GTK 会尝试通过应用启发式方法从类名中查找 get_type()
函数。在大多数情况下,这都是有效的,但如有必要,可以使用 “type-func” 属性明确指定 get_type()
函数的名称。如果您的 UI 定义引用内部类型,您应该确保在解析 UI 定义之前为每个对象类型调用 g_type_ensure()
。
对象可以使用 “id” 属性获得一个名称,这允许应用程序使用 gtk_builder_get_object()
从生成器中检索它们。为了在 UI 定义的其他部分中将对象用作属性值,还需要使用 ID。对于其自身的用途,GTK 保留了以 ___
(三个连续下划线)开头的 ID。
属性
使用 <property>
元素设置对象的属性非常简单:“name” 属性指定属性的名称,而元素的内容指定值
<object class="GtkButton">
<property name="label">Hello, world</property>
</object>
如果将 “translatable” 属性设置为真值,GTK 将使用 gettext()
(如果生成器已设置翻译域,则使用 dgettext()
)为该值查找翻译。这发生在值被解析之前,因此它可用于任何类型的属性,但它对字符串属性最有帮助。还可以指定一个上下文来说明简短的字符串,以及可能对翻译人员有帮助的评论
<object class="GtkButton">
<property name="label" translatable="yes" context="button">Hello, world</property>
</object>
GtkBuilder
可以分析最常见属性类型的文本表示形式
- 字符
- 字符串
- 整数
- 浮点数
- 布尔值(诸如 “TRUE”、“t”、“yes”、“y”、“1” 的字符串被解释为真值,诸如 “FALSE”、“f”、“no”、“n”、“0” 的字符串被解释为假值)
- 枚举类型(可以用它们的完整 C 标识符(在注册枚举类型时使用的简称)或它们的整数值来指定)
- 标识类型(可以通过其 C 标识符或简称指定,还可以通过“|”与“按位或”结合使用,或使用单个整数值,例如“GTK_INPUT_HINT_EMOJI|GTK_INPUT_HINT_LOWERCASE”或“emoji|lowercase”或 520)。
- 颜色(由
gdk_rgba_parse()
理解的格式表示) GVariant
(可以用g_variant_parse()
理解的格式指定)- pixbufs(可以指定为对象 ID、资源路径或与 Builder 文件或 CWD(如果使用了
gtk_builder_add_from_string()
)相关的图像文件的文件名) - GFile(与 pixbufs 类似,可以指定为对象 ID、URI 或与 Builder 文件或 CWD(如果使用了
gtk_builder_add_from_string()
)相关的文件的文件名)
对象可以引用其名称,并且在默认情况下引用已在本地 XML 片段中声明的对象和通过 gtk_builder_expose_object()
呈现的对象。一般而言,GtkBuilder
允许向本地 XML 中声明的对象进行前向引用;在引用对象之前不必先构建对象。此规则的例外情况是:必须先构建一个对象才能将该对象用作仅限构建的属性的值。
子对象
许多窗口小组件的属性是子窗口小组件,例如 GtkExpander:child
。在这种情况下,在 ui 文件中指定子窗口小组件的首选方式是简单地设置属性。
<object class="GtkExpander">
<property name="child">
<object class="GtkLabel">
...
</object>
</property>
</object>
能包含任意数量子元素的通用容器,例如 GtkBox
,而是使用 <child>
元素。<child>
元素包含描述子对象的 <object>
元素。大多数情况下,子元素是一个容器内的窗口小组件,但子元素还可以是动作组中的动作或树模型中的列。
实现 GtkBuildable
接口的任何对象类型都可以指定如何向其添加子元素。由于 GTK 随附的许多对象和窗口小组件已经实现了 GtkBuildable
接口,因此通常可以使用 <child>
元素添加子元素,而无需担心底层实现。
请参见 GtkWidget
文档,了解使用 GtkBuilder
与窗口小组件配合使用的许多示例,包括使用 <child>
元素设置子对象。
需要注意的特殊情况是一个通用规则,其中只有实现 GtkBuildable
的对象才能指定如何处理 <child>
元素,但是 GtkBuilder
提供了使用 <child>
元素向 GListStore
添加对象的特别支持。例如:
<object class="GListStore">
<property name="item-type">MyObject</property>
<child>
<object class="MyObject" />
</child>
...
</object>
属性绑定
还可以将属性值绑定到另一个对象的属性值,使用属性“bind-source”指定绑定的源对象,以及可选的“bind-property”和“bind-flags”分别指定源属性和源绑定标志。内部GtkBuilder
使用 GBinding
对象来实现这一点。
例如,在下面的示例中,bottom_label
小部件的“label”属性绑定到了top_button
小部件的“label”属性
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkButton" id="top_button">
<property name="label">Hello, world</property>
</object>
</child>
<child>
<object class="GtkLabel" id="bottom_label">
<property name="label"
bind-source="top_button"
bind-property="label"
bind-flags="sync-create" />
</object>
</child>
</object>
有关更多信息,请参阅 g_object_bind_property()
方法的文档。
请注意,在 .ui 文件中设置对象之间绑定关系的另一种方法是使用GtkExpression
方法。有关更多信息,请参阅 GtkExpression
文档。
内部子元素
有时需要引用由 GTK 隐式构建的作为复合小部件一部分的小部件,来设置其属性或添加更多子元素(例如 GtkDialog
的内容区域)。这可以通过将 <child>
元素的“internal-child”属性设置为 true 值来实现。请注意,即使 GtkBuilder
已经构建了内部子元素,它仍然需要一个针对内部子元素的 <object>
元素。
专有子元素
许多小部件都有可以添加子元素的不同位置(例如笔记本窗格中的标签页和页面内容)。这可以通过在 <child>
上指定“type”属性在 UI 定义中反映出来。“type”属性的可能值将描述 UI 定义中特定于小部件的部分的章节中。
信号处理程序和函数指针
信号处理程序使用 <signal>
元素设置。 “name”属性指定信号的名称,而“handler”属性指定要连接到信号的函数。
<object class="GtkButton" id="hello_button">
<signal name="clicked" handler="hello_button__clicked" />
</object>
剩下的属性“after”、“swapped”和“object”与 g_signal_connect_object()
或 g_signal_connect_data()
函数的相应参数具有相同的含义。
- “after”与
G_CONNECT_AFTER
标志匹配,并且将确保在针对信号的默认类闭包后调用处理程序 - “swapped”与
G_CONNECT_SWAPPED
标志匹配,当调用信号处理程序时,将互换实例和闭包参数 - “object”会将信号处理程序绑定到属性引用的对象的生存期
如果没有另外指定,默认情况下,“swapped”将被设置为“yes”,以便于使用“object”。同样允许使用“last_modification_time”属性,但是对于生成器,它没有任何含义。
在为 Windows 编译应用程序时,必须使用 G_MODULE_EXPORT
装饰符声明信号回调,否则它们将不会被放入符号表
G_MODULE_EXPORT void
hello_button__clicked (GtkButton *button,
gpointer data)
{
// ...
}
在 Linux 和 Unix 上,这是没有必要的;相反,应当使用编译器标志中的 -Wl,--export-dynamic
参数编译应用程序,并针对 gmodule-export-2.0
链接。
示例 UI 定义🔗
<interface>
<object class="GtkDialog" id="dialog1">
<child internal-child="content_area">
<object class="GtkBox">
<child internal-child="action_area">
<object class="GtkBox">
<child>
<object class="GtkButton" id="ok_button">
<property name="label" translatable="yes">_Ok</property>
<property name="use-underline">True</property>
<signal name="clicked" handler="ok_button_clicked"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
使用 GtkBuildable 扩展 UI 定义🔗
对象能实现 GtkBuildable
接口,可向 XML 中添加自定义元素和属性。通常,该扩展将记录在每个实现此接口的类型中。
模板🔗
在描述 GtkWidget
时,您可以使用 <template>
标记来描述特定小部件类型绑定的 UI。GTK 将在实例化该类型时自动加载 UI 定义,并将子类和信号处理程序绑定到实例字段和函数 符号。
有关更多信息,请参阅 GtkWidget
文档 中的 详细信息。
信号
继承自 GObject 的信号 (1)
GObject::notify
当它的一个属性通过 g_object_set_property()、g_object_set() 等设置了值时,便会在对象上发出通知信号。