我已经用模板创建了一个自定义Gtk Widget,我想在其他Gtk Builder文件上使用它。
我做了什么:
- 用
<template class="G3JAMinScenes" parent="GtkBox">
写一个。ui文件编写小部件源代码(.c/.h)
当我用g3jamin_scenes_new
创建它时,小部件按预期工作,问题是我想使用Gtk Builder将它添加为窗口的子窗口,所以我写道:
...
<child>
<object class="G3JAMinScenes" parent="GtkBox" id="scnes">
</object>
</child>
...
但是当我尝试运行
时抛出错误Gtk-CRITICAL **: Error building template class 'G3JAMinAppWindow' for an instance of type 'G3JAMinAppWindow': Invalid object type `G3JAMinScenes'
我还没有在任何文档中找到任何官方的答案。我仔细研究了GTK+源代码,发现了一些东西。
当GtkBuilder
看到一个它还不知道的类型时,它试图获得一个返回相关GType
的函数。它将尝试一些启发式方法来确定调用哪个函数。如果您正在使用G_DEFINE_TYPE
系列宏之一,它将生成所需的mywidget_get_type
样式函数。如果你在做一些奇怪的事情,你也可以在你的ui文件中为对象的type-func
属性中指定函数。
但是,对于简单的程序,可能不会工作(至少在Linux上),因为编译器可能不会在动态符号表中导出函数,所以GtkBuilder
将无法找到它。因此,您只剩下几个选项。
- 在应用程序的早期某处调用
- 如果您使用GCC,将最终可执行文件与
-rdynamic
链接。这将把所有的符号放在动态符号表中,所以上面描述的魔法将允许GtkBuilder
找到它。 - 在共享库中构建小部件。我没有尝试过这个,但我相信它应该工作的原因与
-rdynamic
工作相同。
mywidget_get_type()
。这将在GObject
类型系统中注册该类型,并且GtkBuilder
将能够找到它。我使用GtkApplication
的子类,所以我在我的myapp_class_init
中调用它。这感觉有点像一个hack,但我决定采用这个解决方案,因为它似乎应该可移植到任何情况。