2010-06-09 10 views
7

¿Hay alguna manera, usando la biblioteca Gtk en C, de clonar un botón Gtk (por ejemplo) y empaquetarlo en otro lugar de la aplicación? Sé que no puedes empacar el mismo widget dos veces. Y que este código, obviamente, no iba a funcionar, pero muestra lo que sucede cuando intento una copia superficial del botón:¿Hay una buena manera de copiar un widget 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)); 

No es que crea un código vbox y lo empaqueta en una ventana y se ejecuta gtk_main circundante() . Esto resultará en estos difíciles de entender los mensajes de error:

(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)) 

En la misma línea, si tuviera que escribir mi propia GObject (no necesariamente un widget GTK), hay una buena manera de escribir un constructor de copia. Estoy pensando que debería ser una interfaz con ganchos opcionales y basada principalmente en las propiedades, manejando la jerarquía de la clase de alguna manera.

que me gustaría hacer esto:

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

Si GtkButton podría utilizar una interfaz copiable teórico.

+0

Puedes crear una interfaz GObject que haga lo que se puede "copiar" proporcionando los enganches y esas cosas ... Aunque no quisiera escribirlo, probablemente terminaría siendo complicado ... – Spudd86

Respuesta

3

Un clon throught propiedades es una solución viable:

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; 
} 

La clonación de un widget que no es trivial, sin embargo, pero el enfoque anterior se puede utilizar en la mayoría de los casos (en un GtkButton seguro).

No me importaría que muchos estados no estén expuestos a las propiedades (todos los widgets adecuados deben estar completamente definidos por propiedades para ser utilizables con GtkBuilder) pero una gran cantidad de casos dificultará una clonación robusta (interfaces y contenedores siendo los primeros que vienen a mi mente).

+0

Gracias, esto es lo mejor que puede haber para un constructor de copia general en un GObject (y funciona para mis necesidades). – Jake

+1

También no desea establecer las propiedades 'GtkWidget :: margin' y' GtkWidget :: expand'; sobrescriben otras propiedades. – ptomato

+0

Si bien esto podría parecer que funciona tanto como lo probaste, no es "viable" en el sentido de ser una recomendación segura para las personas, por las múltiples razones dadas en la otra respuesta y sus comentarios. Por lo tanto, no es "lo mejor que podría haber para un constructor de copia general en un GObject" y no es la respuesta real a la pregunta. (_'Hay una buena manera? No, pero aquí hay un truco inimaginablemente frágil .'_) –

4

No lo creo. Hasta donde yo sé, no hay garantía de que los widgets mantengan todo su estado en propiedades, a las que se puede acceder desde el exterior. Si un widget "oculta" el estado al no exportarlo, no hay forma de que pueda copiarlo desde el exterior.

Técnicamente, los widgets pueden simplemente incluir campos en su núcleo struct que no se ve desde fuera de la aplicación, por lo que ni siquiera se puede copiar los bits usando una muda memcpy(), a menos que esté dispuesto a especificar el byte -contestar contando manualmente y usando un literal.

Dicho esto, también es bastante posible que suficientes widgets expongan suficiente estado a través de las propiedades que una copia seguirá funcionando, y tal vez solo muestre problemas técnicos menores. Sin duda sería un truco bastante genial. Recomendaría preguntar directamente a los desarrolladores principales de GTK +, tal vez en la lista de correo gtk-devel-list.

+0

Buena respuesta para es prudente, pero tal vez no lo suficientemente prudente! Una copia bit a bit no funcionaría, más aún, por la misma razón que uno debe escribir constructores de copia específicos en, p. Ej. C++: porque si la fuente contiene referencias a otros objetos, una copia bit a bit crearía referencias adicionales a los mismos, pero sin incrementar su recuento de referencias, lo que daría lugar a uso-después-libre, doble-libre y toda otra forma de horror. Además, estoy bastante seguro de que los desarrolladores de GTK + no estarían interesados ​​en esto, por las razones que hemos dado aquí, y tampoco por IMO. –

Cuestiones relacionadas