带有模板 UI 的自定义 Gtk Widget

Vic*_*lio 5 gtk gtkbuilder subclassing gtk3

我已经使用模板创建了一个自定义 Gtk Widget,并且我想在其他 Gtk Builder 文件上使用它。

我做了什么:

  • 编写了一个 .ui 文件<template class="G3JAMinScenes" parent="GtkBox">
  • 编写小部件源代码(.c/.h)

当我使用小部件按预期工作时创建它时g3jamin_scenes_new,问题是我想使用 Gtk Builder 将其添加为窗口的子级,所以我写道:

...
<child>
    <object class="G3JAMinScenes" parent="GtkBox" id="scnes">
    </object>
</child>
...
Run Code Online (Sandbox Code Playgroud)

但当我尝试运行时它会抛出错误:

Gtk-CRITICAL **: Error building template class 'G3JAMinAppWindow' for an instance of type 'G3JAMinAppWindow': Invalid object type `G3JAMinScenes'
Run Code Online (Sandbox Code Playgroud)

小智 3

我在任何文档中都找不到对此的任何官方答案。我深入研究了 GTK+ 源代码并发现了一些东西。

GtkBuilder看到它还不知道的类型时,它会尝试获取一个返回相关GType. 它将尝试一些启发式方法来确定要调用哪个函数。如果您正在使用宏系列之一G_DEFINE_TYPE,它将生成mywidget_get_type所需的必要样式函数。type-func如果您正在做一些奇怪的事情,您还可以在 ui 文件中的对象的属性中指定函数。

但是,对于简单的程序来说,可能无法运行(至少在 Linux 上),因为编译器可能不会导出动态符号表中的函数,因此GtkBuilder无法找到它。所以你有几个选择。

  1. mywidget_get_type()在申请的早期打电话给某个地方。这将在类型系统中注册该类型GObject并且GtkBuilder能够找到它。我正在使用 的子类GtkApplication,因此我在我的myapp_class_init. 这感觉有点像黑客,但我选择了这个解决方案,因为它似乎应该可以移植到任何情况。
  2. 如果您使用的是 GCC,请将最终的可执行文件链接到-rdynamic. 这会将所有符号放入动态符号表中,因此上述魔法将允许GtkBuilder找到它。
  3. 在共享库中构建您的小部件。我还没有尝试过这个,但我相信它应该能起到同样的作用-rdynamic

  • 您不应在某处调用“mywidget_get_type()”,而应该在小部件类的实例初始化函数中使用“g_type_ensure()”和内部子级的类型。例如:https://git.gnome.org/browse/gtk+/tree/gtk/gtkfilechooserwidget.c#n8598 (7认同)