ProgramacionGTKenC/CapituloVIII
Contenido |
Conceptos avanzados en GTK+
Hemos quedado con un monton de dudas hasta el momento acerca de algunos de los ejemplos presentados anteriormente.
Cubramos cada uno de ellos aqui, de menor a mayor complejidad.
Habiamos visto que cada uno de los widgets recibe (y emite) señales. Estas son tomadas por el subsistema de GTK+ y ejecuta las funciones pertinentes, permitiendo que los programas dejen de ser aburridos y ejecuten mas acciones, con o sin la ayuda del usuario.
Una señal que se ha visto seguido es la asociada al widget boton:
g_signal_connect ((GObject *) boton_n,"clicked", (GCallback * ) funcion_n, NULL);
esto es que la funcion "funcion_n" es ejecutada al momento de hacer clic en el boton "boton_n".
Antiguamente (y en varios ejemplos antiguos) se ve que la funcion se llamaba gtk_signal_connect(). Esta es una funcion que se depreco desde la version 2.x de GTK+.
No crean que es la unica señal que es capaz de recibir el boton (ni otros widgets). Antes de continuar, hay que entender un poco la jerarquia de objetos de GTK+.
Objetos
Habia dicho de un principio que todos los widgets son herencia de GObject, y a GtkWidget, y esta es una de las razones que la declaracion de los widgets en codigo pueda ser:
GtkWidget * widget1; GtkWidget * widget2; ...
Ser "hijos" de GObject les permite, por ejemplo, la emision y recepcion de señales (de ahi la funcion g_object_signal).
Los GObjects es el tipo fundamental para los atributos y objetos en GTK+. Esto permite tener una serie de fundaciones (funciones base) para la construccion de objetos, acceso a metodos y soporte de señales.
Un GObject posee solo cuatro funciones basicas:
- get_property()
- set_property()
- dispose()
- finalize()
Solo nos centraremos en las primeras dos.
Habiamos visto hace algunas entregas atras que podemos cambiar algunas propiedades de los widgets.
Un ejemplo simple:
gtk_window_set_title((GtkWindow *) ventana, "titulo de la ventana");
Esto solo cambia el titulo de la ventana a "titulo de la ventana".
Revisando un poco la documentacion de GTK+, se puede ver que el widget de ventana posee la propiedad "title" (titulo). Esta la podemos cambiar con la funcion anterior (gtk_window_set_title). Pero como un widget es un GObject, podemos cambiar la propiedad "title" usando una funcion de GObject:
g_object_set_property((Gobject *) ventana, "title", "titulo de la ventana");
Ademas, las funciones de GObject nos permiten cambiar multiples propiedades de un widget!
g_object_set((GObject *) ventana, "title", "titulo de la ventana", "default-height", 100, "default-width", 200, "accept-focus", TRUE, "destroy-with-parent", TRUE, NULL);
La unica señal que puede recibir un GObject es "notify", que es usada para emitir advertencias acerca de propiedades no esperadas o no soportadas por el objeto. Por ejemplo, si queremos preguntar por "title" en un widget de boton.
GtkWidgets
Los GtkWidgets son capaces de recibir muchas señales. La lista completa es:
- accel-closures-changed
- button-press-event
- button-release-event
- can-activate-accel
- child-notify
- client-event
- configure-event
- delete-event
- destroy-event
- direction-changed
- drag-begin
- drag-data-delete
- drag-data-get
- drag-data-received
- drag-drop
- drag-end
- drag-leave
- drag-motion
- enter-notify-event
- event
- event-after
- expose-event
- focus
- focus-in-event
- focus-out-event
- grab-broken-event
- grab-focus
- grab-notify
- hide
- hierarchy-changed
- key-press-event
- key-release-event
- leave-notify-event
- map
- map-event
- mnemonic-activate
- motion-notify-event
- no-expose-event
- parent-set
- popup-menu
- property-notify-event
- proximity-in-event
- proximity-out-event
- realize
- screen-changed
- scroll-event
- selection-clear-event
- selection-get
- selection-notify-event
- selection-received
- selection-request-event
- show
- show-help
- size-allocate
- size-request
- state-changed
- style-set
- unmap
- unmap-event
- unrealize
- visibility-notify-event
- window-state-event
Cada una de estas señales posee una funcion tipo asociada. Por ejemplo, "selection-get":
void user_function (GtkWidget * widget, GtkSelectionData * data, guint info, guint time, gpointer user_data);
mientras que "grab-broken-event"
gboolean user_function (GtkWidget * widget, GdkEvent * event, gpointer user_data);
Todas las funciones tienen como primer argumento "GtkWidget * widget", que es el widget que origina la señal, y como ultimo argumento "gpointer data" que es un tipo de dato cualquiera (un puntero).
Usando El Widget Correcto
Algunas veces, al momento de programar, la originalidad empieza a salir a flote y se empieza a jugar con codigo.
Aqui van algunos ejemplos.
Una ventana dentro de un boton
Este ejemplo es bastante ridiculo, pero vamos a sacarlo a colacion :)
#include <gtk/gtk.h> int main (int argc, char * argv[]) { GtkWidget * ventana1; GtkWidget * boton1; GtkWidget * ventana2; gtk_init(&argc, &argv); ventana1 = gtk_window_new(GTK_WINDOW_TOPLEVEL); ventana2 = gtk_window_new(GTK_WINDOW_TOPLEVEL); boton1 = gtk_button_new(); gtk_container_add((GtkContainer *) ventana1, boton1); gtk_container_add((GtkContainer *) boton1, ventana2); gtk_widget_show_all(ventana1); gtk_main(); }
El lindo SIGSEGV (segmentation fault) es por la siguiente linea:
gtk_container_add((GtkContainer *) boton1, ventana2);
A pesar que el boton es un contenedor, hay algunas restricciones al momento de incrustar widgets.