(这是关于 GTK 4 中自定义小部件的系列文章的第三部分。 第一部分,第二部分)。
推荐使用小部件
正如我们之前所说,“一切都是小部件”。例如,我们建议您使用 GtkLabel 而不是手动渲染 pango 布局,或者使用 GtkImage 而不是手动加载和渲染 pixbuf。使用现成的小部件可以确保您获得所有预期的行为,例如选择处理、上下文菜单或高 DPI 支持。而且这比您自己完成所有操作要容易得多。
委托布局
snapshot() 和 measure() 函数的默认实现会自动处理子小部件。自定义小部件的主要职责是根据需要排列子小部件。在 GTK 3 中,这将通过实现 size_allocate() 函数来完成。您仍然可以这样做。但在 GTK 4 中,更方便的替代方法是使用布局管理器。GTK 提供了许多预定义的布局管理器,例如 GtkBoxLayout、GtkCenterLayout、GtkGridLayout 等。
可以通过多种方式设置布局管理器,最简单的方法是在 class_init 函数中设置布局管理器类型
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_GRID_LAYOUT);
然后,GTK 将自动实例化并使用这种类型的布局管理器。
布局管理器将其子小部件包装在它们自己的“布局子”对象中,这些对象可以具有影响布局的属性。这是子属性的替代方案。就像子属性一样,您可以在 ui 文件中设置这些“布局属性”
<child> <object class="GtkLabel"> <property name="label">Image:</property> <layout> <property name="left-attach">0</property> </layout> </object> </child>
添加子项
使用模板是将子项添加到小部件的最便捷方式。在 GTK 4 中,这适用于任何小部件,而不仅仅是容器。如果出于某种原因,您需要手动创建子小部件,则最好在 init() 函数中完成
void demo_init (DemoWidget *demo) { demo->label = gtk_label_new ("Image:"); gtk_widget_set_parent (demo->label, GTK_WIDGET (demo)); }
执行此操作时,重要的是设置正确的父子关系,使您的子小部件成为整体小部件层次结构的一部分。并且需要在 dispose() 函数中撤消此设置
void demo_dispose (GObject *object) { DemoWidget *demo = DEMO_WIDGET (object); g_clear_pointer (&demo->label, gtk_widget_unparent); GTK_WIDGET_CLASS (demo_widget_parent_class)->dispose (object); }
新的可能性
布局管理器很好地将布局任务与小部件机制的其余部分隔离,这使得试验新的布局更容易。
例如,GTK 4 包括 GtkConstraintLayout,它使用约束求解器根据小部件大小和位置的一组约束创建布局。
要了解有关 GTK 4 中约束的更多信息,请阅读 GtkConstraintLayout 的文档。
展望
在下一篇文章中,我们将了解 GTK 4 中的小部件如何处理输入。