La biblioteca libglade

Glade permite generar código a partir de las interfaces diseñadas, sin embargo su práctica no es recomendada y es por eso que se omite en este libro. La alternativa es emplear las funcionalidades provistas por la biblioteca libglade, la cual se encarga de cargar y procesar los archivos XML de las interfaces durante la ejecución del programa.

A través de libglade se logra la separación entre la interfaz de usuario y la lógica del programa.

Ejemplo básico de uso de libglade

Ejemplo 1. Primer ejemplo con GTK

	#include <gtk/gtk.h>
	#include <glade/glade.h>

	void some_signal_handler_func(GtkWidget *widget, gpointer user_data) {
	  /* Algún código útil */
	}

	int main(int argc, char *argv[]) {
		GladeXML *xml;

		gtk_init(&argc, &argv);

		/* Cargar la interfaz de usuario */
		xml = glade_xml_new("filename.glade", NULL, NULL);

		/* Conectar las señales de la interfaz */
		glade_xml_signal_autoconnect(xml);

		/* Iniciar el ciclo principal */
		gtk_main();

		return 0;
	}
	    

Compilación

Desde el shell

  	$ gcc -o main main.c `pkg-config --cflags --libs libglade-2.0`
	  	

Usando autoconf

	PKG_CHECK_MODULES(MYPROG, libglade-2.0 libgnomeui-2.0 >= 1.110.0)
	AC_SUBST(MYPROG_CFLAGS)
	AC_SUBST(MYPROG_LIBS)
		

Un ejemplo más elaborado

El siguiente ejemplo constituye una elaboración del anterior. El ejercicio consiste en disponer de 3 widgets GtkEntry, GtkLabel y GtkButton llamados entry, label y button respectivamente, de tal forma que el usuario modifique el texto de entry y al presionar el botón se modifique el widget label.

El ejercicio permitirá mezclar varios conceptos ya aprendidos, a saber:

  • Paso de otros widget a las señales

  • Validación de g_assert

  • Diseño de intefaz con Glade

  • Emplear distintos caminos para llegar a una misma interfaz con Glade

Figura 6. Ventana resultante para el ejericicio

Ventana resultante para el ejericicio

Figura 7. Construcción paso a paso con cajas

Construcción paso a paso con cajas
Construcción paso a paso con cajas
Construcción paso a paso con cajas
  1. Crear una nueva ventana.

  2. Insertar una caja vertical con 2 filas.

    1. Definir ancho de borde 4.

    2. Definir espaciado 4.

  3. Insertar una entrada de texto en la primera fila del vbox.

    1. Renombrar a entry (en vez de entry1).

    2. Definir Texto como "Ingresar texto".

    3. Activar como predeterminado (Activates default). Esto dejará el foco en este widget al momento de cargar la ventana.

  4. Insertar una caja horizontal con 2 columnas en la segunda fila del vbox y definir espaciado 4.

  5. Insertar un boton en la primera columna.

    1. Renombrarlo a button (en vez de button1).

    2. Definir la etiqueta como "Cambiar texto".

    3. Definir como predeterminado (en la paleta comunes). Esto habilitará al botón para ser ejecutado cuando se presione la tecla Return en la ventana (acción predeterminada).

    4. Definir una función para la señal clicked En la paleta "Señales" elegir "clicked" para Señal. El manejador es el nombre de la función dentro del programa que se ejecutará al momento de efectuar click sobre el botón. En esta ocasión dejaremos el nombre propuesto por Glade: "on_button_clicked". Para que los cambios tengan efecto es necesario presionar el botón "Añadir". De la misma forma, si se modifica alguno de esos valores, es necesario presionar el botón "Actualizar", de los contrario los cambios no se verán reflejados.

  6. Insertar una etiqueta en la segunda columna de hbox1.

    1. Renombrar a label (en vez de label1).

    2. Definir Texto como "Ingresar texto".

  7. Redimensionar la ventana para que cuadre con los controles. Al momento de ejecutar la ventana, se ajustará automáticamente al tamaño de los controles, independientemente de la forma en que se muestra en Glade. Sin embargo, es buena práctica realizar el redimensionamiento para trabajar de la misma forma en que se verá en la aplicación. Si se desea modificar a un tamaño distinto y mayor al tamaño mínimo dado por los widgets, entonces es necesario sobrescribir los valores de los campos Ancho y Altura para el widget ventana (ver paleta "Comunes").

Figura 8. Construcción paso a paso con tabla

Construcción paso a paso con tabla
Construcción paso a paso con tabla
Construcción paso a paso con tabla
  1. Crear una nueva ventana.

  2. Insertar una tabla con 2 filas y 2 columnas.

    1. Definir ancho de borde 4.

    2. Definir espaciado de filas 4.

    3. Definir espaciado de columnas 4.

  3. Insertar una entrada de texto en la primera fila y primera columna de la tabla.

    1. Renombrar a entry (en vez de entry1).

    2. Definir Texto como "Ingresar texto".

    3. Activar como predeterminado (Activates default). Esto dejará el foco en este widget al momento de cargar la ventana.

    4. Definir Interlineado de columnas 2 (paleta Empaquetado). Las opciones de interlinado permiten que el widget ocupe mas de una "celda" dentro de la tabla.

  4. Insertar un boton en la primera columna de la seguna de fila de la tabla.

    1. Renombrarlo a button (en vez de button1).

    2. Definir la etiqueta como "Cambiar texto".

    3. Definir como predeterminado (en la paleta comunes). Esto habilitará al botón para ser ejecutado cuando se presione la tecla Return en la ventana (acción predeterminada).

    4. Definir una función para la señal clicked En la paleta "Señales" elegir "clicked" para Señal. El manejador es el nombre de la función dentro del programa que se ejecutará al momento de efectuar click sobre el botón. En esta ocasión dejaremos el nombre propuesto por Glade: "on_button_clicked". Para que los cambios tengan efecto es necesario presionar el botón "Añadir". De la misma forma, si se modifica alguno de esos valores, es necesario presionar el botón "Actualizar", de los contrario los cambios no se verán reflejados.

    5. Deshabilitar la opción "Rellenar en X" de la paleta Empaquetado. Las opciones Rellenar X/Y y Expandir en X/Y son similares a las encontradas en los hbox y vbox, sin emgargo, en una tabla es necesario si se desea rellenar/expandir respecto a la columna y/o fila.

  5. Insertar una etiqueta en la segunda fila y segunda columna de la tabla.

    1. Renombrar a label (en vez de label1).

    2. Definir Texto como "Ingresar texto".

    3. Habilitar la opción "Expandir en X" en la paleta Empaquetado.

  6. Redimensionar la ventana para que cuadre con los controles. Al momento de ejecutar la ventana, se ajustará automáticamente al tamaño de los controles, independientemente de la forma en que se muestra en Glade. Sin embargo, es buena práctica realizar el redimensionamiento para trabajar de la misma forma en que se verá en la aplicación. Si se desea modificar a un tamaño distinto y mayor al tamaño mínimo dado por los widgets, entonces es necesario sobrescribir los valores de los campos Ancho y Altura para el widget ventana (ver paleta "Comunes").

Ejemplo 2. Un ejemplo más elaborado con GTK

	#include <gtk/gtk.h>
	#include <glade/glade.h>

	void on_button_clicked (GtkButton *button, gpointer user_data) {
		GtkWidget *label, *entry;
		gchar *text;

		label = g_object_get_data (G_OBJECT (button), "label");
		entry = g_object_get_data (G_OBJECT (button), "entry");

		text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
		gtk_label_set_text (GTK_LABEL (label), text);
	}

	int main(int argc, char *argv[]) {
		GladeXML *xml;
		GtkWidget *label, *button, *entry;

		gtk_init(&argc, &argv);

		/* Cargar la interfaz de usuario */
		xml = glade_xml_new("hola_mundo.glade", "window1", NULL);

		button = glade_xml_get_widget (xml, "button");
		label = glade_xml_get_widget (xml, "label");
		entry = glade_xml_get_widget (xml, "entry");

		g_assert (button != NULL);
		g_assert (label != NULL);
		g_assert (entry != NULL);

		g_object_set_data (G_OBJECT (button), "label", label);
		g_object_set_data (G_OBJECT (button), "entry", entry);

		/* Conectar las señales de la interfaz */
		glade_xml_signal_autoconnect(xml);

		g_object_unref (G_OBJECT (xml));

		/* Iniciar el ciclo principal */
		gtk_main();

		return 0;
	}
		

libglade y las bibliotecas de GNOME

Para integrar los widgets que se construyen sobre GTK+, sólo es necesario realizar la inicialización a través de gnome_program_init en vez de gtk_init.

Internacionalización de las interfaces