类
GtkWidget
描述 [源]
abstract class Gtk.Widget : GObject.InitiallyUnowned
implements Gtk.Accessible, Gtk.Buildable, Gtk.ConstraintTarget {
/* No available fields */
}
所有小部件的基类。
它管理小部件的生命周期、布局、状态和样式。
高度宽度几何管理
GTK 使用高度宽度(和宽度高度)几何管理系统。高度宽度意味着小部件可以根据它获得多少水平空间来改变其所需的垂直空间(类似地,宽度高度也是如此)。最常见的例子是一个标签,它会重新排列以填充可用的宽度,折行到更少的行,因此需要更少的高度。
高度宽度的几何管理通过以下两种虚拟方法在 GTK 中实现
在实现高度宽度以及在使用它的小部件实现中要记住一些重要事项。
如果您实现了一个直接支持高度宽度或宽度高度的几何管理的小部件(包括其子小部件)的 GtkWidget
子类,则必须实现该虚拟函数 Gtk.WidgetClass.get_request_mode
并返回小部件的首选请求模式。该虚拟函数的默认实现返回 GTK_SIZE_REQUEST_CONSTANT_SIZE
,这意味着小部件将始终将其 Gtk.WidgetClass.measure
实现中的 for_size 值传递为 -1。
几何管理系统将一次性查询一次小部件层次结构的方向。当查询小部件的最小尺寸时,通常会在顶级窗口选择的 GtkSizeRequestMode
中进行两次初始遍历。
例如,在查询正 GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH
模式时
首先,界面中每个小部件的默认最小宽度和自然宽度将使用带有水平方向的 gtk_widget_measure()
方法进行计算,其中 for_size 参数设为 -1。因为每个小部件的首选宽度依赖于其子部件的首选宽度,这种信息会在层次结构中向上传播,最终为整个顶层窗口确定一个最小宽度和自然宽度。接下来,顶层窗口将使用最小宽度查询该宽度相关的最小高度,使用带有垂直方向的 gtk_widget_measure()
方法,其中 for_size 参数为刚才计算出的宽度。这同样是一个高度递归的操作。通常,用于最小宽度的最小高度用于设置顶层窗口的最小尺寸限制。
在顶层窗口初始请求其两个维度的大小后,它可以分配一个合理的大小(或者使用 gtk_window_set_default_size()
设置的已指定大小)。在递归分配过程中,需要注意的是,当小部件为它们的子部件分配大小的时候,请求循环将递归执行。每个小部件分配大小后,会先在其子部件之间共享一个方向的空白空间,然后为每个子部件的目标分配宽度或高度请求相应的尺寸。这样,一个部件通常需要在实际分配大小之前达到多次请求尺寸。一个部件最终分配的尺寸可能与其请求的尺寸不同。因此,GtkWidget
缓存了一些结果,以避免在一个分配周期中针对同一尺寸重复查询。
如果一个部件需要在其分配的空间中智能地使用尺寸,那么它必须支持两种 GtkSizeRequestMode
的请求,即使那个部件仅在单方向上交换尺寸。
例如,一个执行高度以宽度和宽度以高度自动换行的 GtkLabel
小部件不会期望有带有垂直方向的 Gtk.WidgetClass.measure
方法调用,因为这个调用专门针对宽度以高度请求。在这种情况下,标签必须返回其自身可能的最小宽度所需的高度。遵循这一规则,任何处理高度以宽度或宽度以高度请求的部件都会分配足够的空间来适应其内容。
以下是介绍一个 GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH
小部件通常如何处理宽度以高度请求的一些示例
static void
foo_widget_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum_size,
int *natural_size,
int *minimum_baseline,
int *natural_baseline)
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
// Calculate minimum and natural width
}
else // VERTICAL
{
if (i_am_in_height_for_width_mode)
{
int min_width, dummy;
// First, get the minimum width of our widget
GTK_WIDGET_GET_CLASS (widget)->measure (widget, GTK_ORIENTATION_HORIZONTAL, -1,
&min_width, &dummy, &dummy, &dummy);
// Now use the minimum width to retrieve the minimum and natural height to display
// that width.
GTK_WIDGET_GET_CLASS (widget)->measure (widget, GTK_ORIENTATION_VERTICAL, min_width,
minimum_size, natural_size, &dummy, &dummy);
}
else
{
// ... some widgets do both.
}
}
}
在尺寸请求或分配过程中,一个部件往往需要获得自身请求。例如,在计算高度时,它可能还需要计算宽度。或者在确定如何使用分配时,小部件可能需要知道其自然尺寸。在这些情况下,小部件应小心地直接调用其虚拟方法,就像上述代码示例一样。
在你的 Gtk.WidgetClass.size_allocate
实现中不允许使用包装函数 gtk_widget_measure()
。这些函数返回一个请求,它已被 GtkSizeGroup
所调整,小部件的对齐和扩展标志,以及其 CSS 风格。
如果一个部件在其虚拟方法实现中使用了包装器,那么调整(如小部件边缘)将会被应用两次。因此,GTK 不允许这样做,如果在尝试执行时 GTK 会发出警告。
当然,如果你要获取另一个小部件(如子部件)的尺寸请求,你必须使用 gtk_widget_measure()
;否则,你将无法正确考虑小部件边缘、GtkSizeGroup
等等。
GTK 还支持小部件的基线垂直对齐。这意味着小部件将被定位,使得同一行中小部件的版式基线是对齐的。这种情况发生在小部件支持基线、使用基线对齐、并且位于支持基线且具有自然“行”的基线对齐小部件内,或者由其祖父母分配给它的基线。
小部件的基线对齐支持也是通过 Gtk.WidgetClass.measure
虚拟函数实现的。这允许您报告最小和自然大小。
如果一个小部件最终进行基线对齐,它将分配与 GTK_ALIGN_FILL
相似的父级所有空间,但选定的基线可以通过 gtk_widget_get_baseline()
查找。如果基线值不是 -1,则需要调整小部件的位置,使得基线出现在该位置。
GtkWidget 作为 GtkBuildable
GtkWidget
对 GtkBuildable
接口的实现支持各种自定义元素,用于指定小部件的额外方面,这些方面没有直接表达为属性。
如果小部件使用 GtkLayoutManager
,GtkWidget
支持自定义的 <layout>
元素,用于定义布局属性
<object class="GtkGrid" id="my_grid">
<child>
<object class="GtkLabel" id="label1">
<property name="label">Description</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
<property name="row-span">1</property>
<property name="column-span">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="description_entry">
<layout>
<property name="column">1</property>
<property name="row">0</property>
<property name="row-span">1</property>
<property name="column-span">1</property>
</layout>
</object>
</child>
</object>
GtkWidget
允许通过自定义的 <style>
元素将样式信息,如样式类与小部件关联
<object class="GtkButton" id="button1">
<style>
<class name="my-special-button-class"/>
<class name="dark-button"/>
</style>
</object>
GtkWidget
允许通过自定义的 <accessibility>
元素定义可访问性信息,如属性、关系和状态
<object class="GtkButton" id="button1">
<accessibility>
<property name="label">Download</property>
<relation name="labelled-by">label1</relation>
</accessibility>
</object>
从模板 XML 构建组合小部件
GtkWidget
提供了一些自动化创建复合小部件的“模板”过程的工具。
要使用 GtkBuilder
XML 创建组合小部件,必须在类初始化时使用 gtk_widget_class_set_template()
将接口描述与小部件类相关联。
复合模板描述中预期的接口描述符号与常规 GtkBuilder
XML 略有不同。
与常规界面描述不同,gtk_widget_class_set_template()
将期望到 <template>
标签作为 <interface>
标签的直接子标签。该 <template>
标签必须指定“class”属性,该属性必须是小部件的类型名称。可选地,可以指定“parent”属性以指定小部件类型的直接父类型;GtkBuilder
会忽略此属性,但可以由 UI 设计工具使用,以在实际类型不存在时检查给定的类型具有何种属性和内部子项。
包含在 <template>
标签内的 XML 行为就像它被添加到定义小部件本身的 <object>
标签中一样。您可以通过在 <template>
标签中插入 <property>
标签来设置小部件的属性,也可以通过添加 <child>
标签以正常方式添加小部件的子项并在正常情况下扩展小部件。
此外,也可以以常规方式在最初的 <template>
标签前后添加 <object>
标签,以便定义辅助对象,这些对象可能被作为 <template>
标签子项声明的其他小部件引用。
由于与 <object>
标签不同,<template>
标签不包含“id”属性,如果您需要在适用元素内容中引用模板将创建的对象的实例本身,只需引用模板类名。
以下是一个模板定义的示例,其中在 <signal>
标签中包含了这方面的示例
<interface>
<template class="FooWidget" parent="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">4</property>
<child>
<object class="GtkButton" id="hello_button">
<property name="label">Hello World</property>
<signal name="clicked" handler="hello_button_clicked" object="FooWidget" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton" id="goodbye_button">
<property name="label">Goodbye World</property>
</object>
</child>
</template>
</interface>
通常,您将模板片段放入与您的项目捆绑在一起的场景文件中,使用 GResource
。为了加载模板,您需要从您的 GtkWidget
类型类的初始化中调用 gtk_widget_class_set_template_from_resource()
static void
foo_widget_class_init (FooWidgetClass *klass)
{
// ...
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
"/com/example/ui/foowidget.ui");
}
您还需要从实例初始化函数调用 gtk_widget_init_template()
static void
foo_widget_init (FooWidget *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
// Initialize the rest of the widget...
}
以及从销毁函数调用 gtk_widget_dispose_template()
static void
foo_widget_dispose (GObject *gobject)
{
FooWidget *self = FOO_WIDGET (gobject);
// Dispose objects for which you have a reference...
// Clear the template children for this widget type
gtk_widget_dispose_template (GTK_WIDGET (self), FOO_TYPE_WIDGET);
G_OBJECT_CLASS (foo_widget_parent_class)->dispose (gobject);
}
您可以使用 gtk_widget_get_template_child()
函数访问在模板中定义的小部件,但通常您将使用与模板定义中小部件相同的名称在您的类型实例私有数据结构中声明一个指针,并使用该名称调用 gtk_widget_class_bind_template_child_full()
(或其包装宏之一 gtk_widget_class_bind_template_child()
和 gtk_widget_class_bind_template_child_private()
),例如
typedef struct {
GtkWidget *hello_button;
GtkWidget *goodbye_button;
} FooWidgetPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (FooWidget, foo_widget, GTK_TYPE_BOX)
static void
foo_widget_dispose (GObject *gobject)
{
gtk_widget_dispose_template (GTK_WIDGET (gobject), FOO_TYPE_WIDGET);
G_OBJECT_CLASS (foo_widget_parent_class)->dispose (gobject);
}
static void
foo_widget_class_init (FooWidgetClass *klass)
{
// ...
G_OBJECT_CLASS (klass)->dispose = foo_widget_dispose;
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
"/com/example/ui/foowidget.ui");
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass),
FooWidget, hello_button);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass),
FooWidget, goodbye_button);
}
static void
foo_widget_init (FooWidget *widget)
{
gtk_widget_init_template (GTK_WIDGET (widget));
}
您还可以使用 gtk_widget_class_bind_template_callback_full()
(或其包装宏 gtk_widget_class_bind_template_callback()
) 将定义在模板中的信号回调与类作用域内可见的函数连接起来,例如
// the signal handler has the instance and user data swapped
// because of the swapped="yes" attribute in the template XML
static void
hello_button_clicked (FooWidget *self,
GtkButton *button)
{
g_print ("Hello, world!\n");
}
static void
foo_widget_class_init (FooWidgetClass *klass)
{
// ...
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
"/com/example/ui/foowidget.ui");
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), hello_button_clicked);
}
后代
- GtkActionBar
- GtkAppChooserButton
- GtkAppChooserWidget
- GtkAspectFrame
- GtkBox
- GtkButton
- GtkCalendar
- GtkCellView
- GtkCenterBox
- GtkCheckButton
- GtkColorButton
- GtkColorChooserWidget
- GtkColorDialogButton
- GtkColumnView
- GtkComboBox
- GtkDragIcon
- GtkDrawingArea
- GtkDropDown
- GtkEditableLabel
- GtkEntry
- GtkExpander
- GtkFileChooserWidget
- GtkFixed
- GtkFlowBox
- GtkFlowBoxChild
- GtkFontButton
- GtkFontChooserWidget
- GtkFontDialogButton
- GtkFrame
- GtkGLArea
- GtkGraphicsOffload
- GtkGrid
- GtkHeaderBar
- GtkIconView
- GtkImage
- GtkInfoBar
- GtkInscription
- GtkLabel
- GtkLevelBar
- GtkListBase
- GtkListBox
- GtkListBoxRow
- GtkMediaControls
- GtkMenuButton
- GtkNotebook
- GtkOverlay
- GtkPaned
- GtkPasswordEntry
- GtkPicture
- GtkPopover
- GtkPopoverMenuBar
- GtkProgressBar
- GtkRange
- GtkRevealer
- GtkScaleButton
- GtkScrollbar
- GtkScrolledWindow
- GtkSearchBar
- GtkSearchEntry
- GtkSeparator
- GtkShortcutLabel
- GtkShortcutsShortcut
- GtkSpinButton
- GtkSpinner
- GtkStack
- GtkStackSidebar
- GtkStackSwitcher
- GtkStatusbar
- GtkSwitch
- GtkText
- GtkTextView
- GtkTreeExpander
- GtkTreeView
- GtkVideo
- GtkViewport
- GtkWindow
- GtkWindowControls
- GtkWindowHandle
实例方法
从 GtkAccessible 继承的方法 (19)
gtk_accessible_announce
请求用户的屏幕阅读器宣布给定信息。
since: 4.14
gtk_accessible_get_accessible_parent
检索可访问对象的父对象。
since: 4.10
gtk_accessible_get_accessible_role
检索可访问对象的角色。
gtk_accessible_get_at_context
检索给定可访问对象的实现。
since: 4.10
gtk_accessible_get_bounds
查询此可访问的坐标和维度。
since: 4.10
gtk_accessible_get_first_accessible_child
检索可访问对象的第一子对象。
since: 4.10
gtk_accessible_get_next_accessible_sibling
检索可访问对象的下一个兄弟对象。
since: 4.10
gtk_accessible_get_platform_state
查询平台状态,例如焦点。
since: 4.10
gtk_accessible_reset_property
将可访问属性重置为其默认值。
gtk_accessible_reset_relation
将可访问关系重置为其默认值。
gtk_accessible_reset_state
将可访问状态重置为其默认值。
gtk_accessible_set_accessible_parent
设置可访问对象的父和兄弟。
since: 4.10
gtk_accessible_update_next_accessible_sibling
更新下一个可访问兄弟。
since: 4.10
gtk_accessible_update_property
更新可访问属性列表。
gtk_accessible_update_property_value
更新可访问属性数组。
gtk_accessible_update_relation
更新可访问关系列表。
gtk_accessible_update_relation_value
更新可访问关系数组。
gtk_accessible_update_state
更新可访问状态列表。
gtk_accessible_update_state_value
更新可访问状态数组。
从 GtkBuildable 继承的方法 (1)
信号
从 GObject 继承的信号(1)
GObject::notify
当对象的一个属性通过 g_object_set_property(), g_object_set(), 等等设置值时,发出通知信号。
类结构
struct GtkWidgetClass {
GInitiallyUnownedClass parent_class;
void (* show) (
GtkWidget* widget
);
void (* hide) (
GtkWidget* widget
);
void (* map) (
GtkWidget* widget
);
void (* unmap) (
GtkWidget* widget
);
void (* realize) (
GtkWidget* widget
);
void (* unrealize) (
GtkWidget* widget
);
void (* root) (
GtkWidget* widget
);
void (* unroot) (
GtkWidget* widget
);
void (* size_allocate) (
GtkWidget* widget,
int width,
int height,
int baseline
);
void (* state_flags_changed) (
GtkWidget* widget,
GtkStateFlags previous_state_flags
);
void (* direction_changed) (
GtkWidget* widget,
GtkTextDirection previous_direction
);
GtkSizeRequestMode (* get_request_mode) (
GtkWidget* widget
);
void (* measure) (
GtkWidget* widget,
GtkOrientation orientation,
int for_size,
int* minimum,
int* natural,
int* minimum_baseline,
int* natural_baseline
);
gboolean (* mnemonic_activate) (
GtkWidget* widget,
gboolean group_cycling
);
gboolean (* grab_focus) (
GtkWidget* widget
);
gboolean (* focus) (
GtkWidget* widget,
GtkDirectionType direction
);
void (* set_focus_child) (
GtkWidget* widget,
GtkWidget* child
);
void (* move_focus) (
GtkWidget* widget,
GtkDirectionType direction
);
gboolean (* keynav_failed) (
GtkWidget* widget,
GtkDirectionType direction
);
gboolean (* query_tooltip) (
GtkWidget* widget,
int x,
int y,
gboolean keyboard_tooltip,
GtkTooltip* tooltip
);
void (* compute_expand) (
GtkWidget* widget,
gboolean* hexpand_p,
gboolean* vexpand_p
);
void (* css_changed) (
GtkWidget* widget,
GtkCssStyleChange* change
);
void (* system_setting_changed) (
GtkWidget* widget,
GtkSystemSetting settings
);
void (* snapshot) (
GtkWidget* widget,
GtkSnapshot* snapshot
);
gboolean (* contains) (
GtkWidget* widget,
double x,
double y
);
}
无描述可提供。
类成员
parent_class: GInitiallyUnownedClass
对象类结构需要是部件类结构中的第一个元素,以便类机制能正确工作。这允许将 GtkWidgetClass 指针转换为 GObjectClass 指针。
show: void (* show) ( GtkWidget* widget )
widget 显示时发出的信号。
hide: void (* hide) ( GtkWidget* widget )
widget 隐藏时发出的信号。
map: void (* map) ( GtkWidget* widget )
当 widget 即将映射时发出的信号,即当 widget 可见(通过 gtk_widget_set_visible() 控制)以及其所有父部件到顶级部件也可见时。
unmap: void (* unmap) ( GtkWidget* widget )
当小部件即将解除映射时发出的信号,这意味着它或其任意父级小部件(直到顶层小部件)已被设置为隐藏。
realize: void (* realize) ( GtkWidget* widget )
当小部件与
GdkSurface
关联时发出的信号,这意味着已调用gtk_widget_realize()
或小部件已被映射(即,它将被绘制)。unrealize: void (* unrealize) ( GtkWidget* widget )
当与小部件关联的 GdkSurface 被销毁时发出的信号,这意味着已调用
gtk_widget_unrealize()
或小部件已被解除映射(即,它将被隐藏)。root: void (* root) ( GtkWidget* widget )
当小部件被添加到
GtkRoot
小部件时调用。必须链式调用。unroot: void (* unroot) ( GtkWidget* widget )
当小部件即将从其
GtkRoot
小部件中移除时调用。必须链式调用。size_allocate: void (* size_allocate) ( GtkWidget* widget, int width, int height, int baseline )
调用以设置分配,如果小部件没有布局管理器。
state_flags_changed: void (* state_flags_changed) ( GtkWidget* widget, GtkStateFlags previous_state_flags )
当小部件状态改变时发出的信号,参看 gtk_widget_get_state_flags()。
direction_changed: void (* direction_changed) ( GtkWidget* widget, GtkTextDirection previous_direction )
当小部件的文本方向改变时发出的信号。
get_request_mode: GtkSizeRequestMode (* get_request_mode) ( GtkWidget* widget )
调用以获取请求模式,如果小部件没有布局管理器。这允许小部件告诉其父容器它是否更喜欢在
GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH
或GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT
模式下分配。GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH
表示小部件更喜欢首先调用GtkWidgetClass.measure()
获取默认宽度(for_size 为 -1),然后再次获取对应默认宽度的长度。GTK_SIZE_REQUEST_CONSTANT_SIZE
禁用小部件的任何高度对宽度或宽度对高度几何管理,是默认返回值。注意,任何进行高度对宽度或宽度对高度交换的小部件都必须正确响应传递给GtkWidgetClass.measure
的 for_size 值 >= -1,对于两种可能的方位。measure: void (* measure) ( GtkWidget* widget, GtkOrientation orientation, int for_size, int* minimum, int* natural, int* minimum_baseline, int* natural_baseline )
调用以获取小部件的最小和自然大小,如果小部件没有布局管理器。根据方向参数,传递的 for_size 可以解释为宽度或高度。小部件将不会被分配小于其最小大小。
mnemonic_activate: gboolean (* mnemonic_activate) ( GtkWidget* widget, gboolean group_cycling )
如果
group_cycling
为FALSE
,则激活widget
;如果group_cycling
为TRUE
,则仅捕获焦点。grab_focus: gboolean (* grab_focus) ( GtkWidget* widget )
使
widget
在其内部的GtkWindow
中获得键盘焦点。focus: gboolean (* focus) ( GtkWidget* widget, GtkDirectionType direction )
gtk_widget_child_focus() 的虚函数。
set_focus_child: void (* set_focus_child) ( GtkWidget* widget, GtkWidget* child )
设置小部件的焦点子项。必须链式调用。
类方法
gtk_widget_class_install_property_action
在 widget_class
上安装名为 action_name
的动作,并将其状态绑定到 property_name
属性的值。