Programando el Demo1 con Glade, GTK y C++

Nuestro primer programa Demo1 será una ventana que contendrá 2 botones y una etiqueta, cuando el usuario presione el botón 1 aparecerá en la etiqueta el texto “Botón1 – Clicked” y cuando el usuario presione el botón 2 aparecerá en la etiqueta el texto “Botón2 – Clicked”, en la Imagen 1 podemos ver el resultado que obtendremos.

Imagen 1

Iniciaremos nuestro Demo1 creando la interfaz de usuario con la ayuda de Glade, al iniciar Glade nos mostrara una ventana de preferencias como la que vemos en la Imagen 2.

Imagen 2

Si queremos que nuestro programa sea mas compatible con la mayoría de los sistemas operativos anteriores podemos seleccionar la versión 2.14 de GTK+ aunque desde Ubuntu 10.04 seguramente ya se cuenta con la versión 2.16, otra cosa que debemos notar es que debe estar seleccionada la opción GtkBuilder que será la forma en que crearemos las referencias a los objetos desde nuestro código.


Una vez que se cierre esa ventana podremos iniciar nuestro programa y agregaremos nuestro primer Widget al editor visual y será una ventana de nivel superior (Imagen 3), como se observa en la parte derecha aparecerá el nombre del Widget “window1”.

Imagen 3


Luego agregaremos el GtkVBox (caja vertical) a “window1”, ese Widget nos servirá para organizar la forma en que podremos agregar mas componentes a nuestra ventana (Imagen 4), escribiremos que dividiremos en 2 la ventana principal, en la parte de arriba agregaremos un Label.

Imagen 4

En la parte de abajo agregaremos un Widget “GtkHButtonBox” y pondremos que vamos a trabajar con 2 elementos (Imagen 5). 
Imagen 5


Una vez hecho el paso anterior podremos modificar algunas propiedades de la caja de botones horizontal como se muestra en la Imagen 6.

Imagen 6




Y después agregaremos los dos botones correspondientes a la caja hbuttonbox1 y después cambiaremos el nombre a mostrar en cada botón como se muestra en la Imagen 7.


Imagen 7


Como se puede observar, la etiqueta a mostrar tiene el texto “_Boton1” y en la parte de abajo se cambio la opción: Utilizar subrayado a “Si”, lo anterior, con la finalidad de que al momento de presionar la tecla ALT se resalte la letra B para simular la acción click del ratón sobre el botón 1. De la misma forma, se cambiará la propiedad del botón 2 cambiándole el nombre a “B_otón2” y poniendo la opción de Utilizar subrayado a “Si”.

Por último, vamos a mencionar lo que son las señales, las señales son las funciones que se lanzan cuando se hace alguna acción sobre un Widget, como queremos que cuando se presione la X de la ventana principal se termine el programa, entonces tenemos que seleccionar el Widget “window1” y nos vamos a la pestaña de señales y seleccionamos “GtkObject” y después “destroy” para que seleccionemos de la columna “Manipulador” la opción “on_window1_destroy”. (Imagen 8)

Imagen 8

De la misma forma vamos a crear una señal para el botón 1 como se muestra en la Imagen 9.

Imagen 9

Guardamos nuestro archivo Glade como “demo1.glade” en el directorio donde vamos a trabajar con nuestro archivo de código C++.

Para editar el código C++ estoy utilizando Geany (Imagen 10) ya que me pareció un editor liviano que no consume muchos recursos y funcional, además de que tiene soporte para otros lenguajes de programación.

Imagen 10

Iniciaremos nuestro código "main.c" mencionando que tenemos que incluir la biblioteca "gtk.h" y para manipular los Widgets diseñados en Glade utilizaremos un tipo de dato estructurado llamado Demo1, para ello utilizaré la palabra reservada struct, veamos el inicio de nuestro programa:


/* Se importa la biblioteca gtk.h */
#include 

/* Definimos la constante con el nombre del archivo creado en Glade */
#define FILEGLADE "demo1.glade"

/* Estructura para almacenar los widgets las cual se necesita para manipularlos */
typedef struct
{
GtkWidget       *window;
GtkWidget       *boton1;
GtkWidget       *boton2;
GtkWidget       *label1;
} Demo1;

/* Declaración de las cabeceras de las funciones necesarias */

/* Función que se ejecuta cuando se lanza la señal 'click' del boton2 */
void on_click_boton2(GtkWidget *widget, Demo1 *demo);

/* El nombre de esta función se puso en la pestaña de Señales en Glade
* y se enlaza automáticamente a nuestro código */
void on_button1_clicked(GtkWidget *widget, Demo1 *demo);

/* Función que se ejecuta cuando se cierra la ventana principal */
void on_window1_destroy (GtkObject *object, gpointer user_data);

void error_message (const gchar *message); 

A continuación veremos la función principal "main()" en donde crean las variables Demo1 *demo; y GtkBuilder *builder; dichas variables nos servirán para construir los objetos de la interfaz de usuario y para almacenar en la estructura las referencias a dichos objetos para poder manipularlos.

int main (int argc, char *argv[])
{
/* Declaramos las variables a utilizar */
Demo1       *demo;
GtkBuilder  *builder;
GError      *err=NULL;

/* Localidad de memoria utilizada para la estructura Tutorial */
demo = g_slice_new (Demo1);

gtk_init (&argc, &argv);

/* Creación del constructor (builder) para después crear los widgets a partir del archivo XML
* creado desde glade */
builder = gtk_builder_new ();
if ( gtk_builder_add_from_file (builder, FILEGLADE, &err) == 0 )
{
error_message (err->message);
g_error_free (err);
return (1);
}

/* Obtener las referencias a los Widgets para almacenarlos en la estructura y poder manipularlos */
/* Primero obtenemos la referencia a la ventana principal */
demo->window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
/* Primero obtenemos la referencia a los botones */
demo->boton1 = GTK_WIDGET (gtk_builder_get_object (builder, "button1"));
demo->boton2 = GTK_WIDGET (gtk_builder_get_object (builder, "button2"));
/* Obtenemos la referencia a la etiqueta */
demo->label1 = GTK_WIDGET (gtk_builder_get_object (builder, "label1"));

/* Se conectan las señales generadas por los objetos desde el builder con los widgets de la estructura */
gtk_builder_connect_signals (builder, demo);

/* Liberar memoria utilizada por el objeto GtkBuilder */
g_object_unref (G_OBJECT (builder));

gtk_widget_show (demo->window);

/* La otra forma de conectar a las señales directamente desde el código sin utilizar glade */
g_signal_connect(demo->boton2, "clicked", G_CALLBACK(on_click_boton2), demo);

gtk_main ();

/* Libera la memoria reservada para la estructura Demo1 */
g_slice_free (Demo1, demo);

return 0;
} 

El desarrollo de las funciones esta documentado sobre el mismo código que se pega a continuación:

/*
* Cuando el usuario presiona la X se ejecuta la opción gtk_main_quit()
* para salir de la función principal y terminar la aplicación.
*/ 
void on_window1_destroy (GtkObject *object, gpointer user_data)
{
/* Termina el ciclo gtk_main() */
gtk_main_quit ();
}

/*
* Señal que se ejecuta cuando el usuario dá click sobre el boton1
*/
void on_button1_clicked (GtkWidget *widget, Demo1 *demo)
{
/* función que agrega un texto a una etiqueta */
gtk_label_set_text(GTK_LABEL(demo->label1), "Botón 1 - Clicked");
}

/*
* Señal que se ejecuta cuando el usuario dá click sobre el boton2
*/ 
void on_click_boton2(GtkWidget *widget, Demo1 *demo)
{
/* función que agrega un texto a una etiqueta */
gtk_label_set_text(GTK_LABEL(demo->label1), "Botón 2 - Clicked");
}

/*
* Se llama error_message() cada vez que queremos mostrar un mensaje de error al usuario.
* Esto mostrará el mensaje de error en una ventana modal y también en la ventana de la terminal.
*/
void error_message (const gchar *message)
{
GtkWidget               *dialog;

/* Muestra el mensaje en la ventana (terminal) de comandos */
g_warning ("%s",message);

/* Crea un dialogo de mensaje de error y lo despliega de forma modal */
dialog = gtk_message_dialog_new (NULL, 
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",message);

gtk_window_set_title (GTK_WINDOW (dialog), "Error!");
gtk_dialog_run (GTK_DIALOG (dialog));      
gtk_widget_destroy (dialog);         
} 

Para finalizar les dejo la liga para descargar el código completo de la aplicación, recuerden compilarlo con la siguiente instrucción:


Compilar "main.c" usando el siguiente comando (Imagen 11):
  gcc -Wall -g -o demo1 main.c `pkg-config --cflags --libs gtk+-2.0` -export-dynamic

Imagen 11


Después ejecutar (Imagen 12):
  ./demo1


2 comentarios:

  1. Qué tal!
    ¿Tendrás el código de todo el proyecto?
    Ya no sirve la liga de descarga.

    ResponderEliminar
    Respuestas
    1. Luis ya no cuento con el código, se me perdió en un respaldo y desgraciadamente veo que el link ya está roto, voy a tratar de volver a hacer el proyecto y lo publicaré nuevamente. Gracias por el interés.

      Eliminar

Error al compilar en Android Studio 4.0: CIRCULAR REFERENCE:com.android.tools.r8.a: Invoke-customs are only supported starting with Android O

Resulta que estuviste construyendo tu APP desde Android Studio 4.0 y no te marcó ningún tipo de error de codificación pero al querer compila...