有没有一个很好的方法来复制Gtk小部件?

有没有办法,使用C中的Gtk库来克隆Gtk按钮(例如),并将其打包到应用程序中的其他位置。 我知道你不能两次打包相同的小部件。 并且这段代码显然不起作用,但显示当我尝试按钮的浅表副本时会发生什么:

GtkButton *a = g_object_new(GTK_TYPE_BUTTON, "label", "o_0", NULL); GtkButton *b = g_memdup(a, sizeof *a); gtk_box_pack_start_defaults(GTK_BOX(vbox), GTK_WIDGET(b)); 

周围的代码创建了一个vbox并将其打包在一个窗口中并运行gtk_main()。 这将导致这些难以理解的错误消息:

 (main:6044): Gtk-CRITICAL **: gtk_widget_hide: assertion `GTK_IS_WIDGET (widget)' failed (main:6044): Gtk-CRITICAL **: gtk_widget_realize: assertion `GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed ** Gtk:ERROR:/build/buildd/gtk+2.0-2.18.3/gtk/gtkwidget.c:8431:gtk_widget_real_map: assertion failed: (GTK_WIDGET_REALIZED (widget)) 

同样,如果我要编写自己的GObject(不一定是Gtk小部件),是否有一种编写复制构造函数的好方法。 我认为它应该是一个带有可选钩子的接口,主要基于属性,以某种方式处理类的层次结构。

我想这样做:

 GtkButton *b = copyable_copy(COPYABLE(a)); 

如果GtkButton可以使用理论上的可复制接口。

克隆通过属性是一个可行的解决方案:

 GObject * g_object_clone(GObject *src) { GObject *dst; GParameter *params; GParamSpec **specs; guint n, n_specs, n_params; specs = g_object_class_list_properties(G_OBJECT_GET_CLASS(src), &n_specs); params = g_new0(GParameter, n_specs); n_params = 0; for (n = 0; n < n_specs; ++n) if (strcmp(specs[n]->name, "parent") && (specs[n]->flags & G_PARAM_READWRITE) == G_PARAM_READWRITE) { params[n_params].name = g_intern_string(specs[n]->name); g_value_init(&params[n_params].value, specs[n]->value_type); g_object_get_property(src, specs[n]->name, &params[n_params].value); ++ n_params; } dst = g_object_newv(G_TYPE_FROM_INSTANCE(src), n_params, params); g_free(specs); g_free(params); return dst; } 

克隆小部件并不是那么简单,但上述方法在大多数情况下都是可用的(在GtkButton上肯定)。

我并不关心那些没有暴露属性的状态(所有适当的小部件应该由属性完全定义以便可以与GtkBuilder一起使用)但是很多GtkBuilder情况会使得强大的克隆变得非常困难(接口和容器是第一个我想到了)。

我不这么认为。 据我所知,无法保证小部件将所有状态保存在属性中,您可以从外部访问。 如果小部件通过不导出来“隐藏”状态,则无法从外部复制它。

从技术上讲,小部件只能在其核心struct包含您从实现之外看不到的字段,因此除非您愿意指定字节数,否则您甚至无法使用dumb memcpy()复制这些位。通过手动计数和使用文字。

话虽如此,很有可能足够的小部件通过属性暴露出足够的状态,副本仍然会起作用,并且可能只会出现轻微的故障。 这肯定是一个非常酷的黑客。 我建议直接询问核心GTK +开发人员,也许是在gtk-devel-list邮件列表上。