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


Cómo programar para GNU&Linux Gnome

Para el desarrollo de nuestro primer programa necesitaremos instalar Glade (Se encuentra en los repositorios de Ubuntu así que no tendremos problemas al querer instalarlo desde el Centro de Software. ver Imagen 1). Glade (Imagen 2) es una herramienta RAD (Desarrollo Rápido de Aplicaciones) visual para el modelado de interfases gráficas de usuario. Glade es independiente del lenguaje ya que no genera código fuente en ningún lenguaje en particular si no que se obtiene un archivo XML que puede ser importado (buscar GtkBuilder) y leído desde cualquier lenguaje compatible con GTK+ (Java, Python, C++, PHP, Ruby, por mencionar algunos).

Imagen 1

Imagen 2

Recomiendo instalar Devhelp ya que ahí encontraremos toda la información de la API (Interfase de Programación de Aplicaciones) GTK+.

También será necesario instalar “Archivos de desarrollo para libgklade2-dev” y si prefieres programar con Python también “python-gtk2-dev”.

GTK+ es una biblioteca de funciones para crear interfaces gráficas de usuario. Es funcional para muchas plataformas “UNIX-Like” y Windows. GTK+ tiene una arquitectura orientada a objetos basada en C que permite una máxima flexibilidad. GTK+ depende de las bibliotecas GLib, Pango, ATK, GdkPixbuf, GDK y GTK+.

En la siguiente entrada iniciaremos el desarrollo de nuestro primer programa Demo1.

Temas para fondos de escritorio en Ubuntu 10.04 y 10.10

Decidí iniciar un blog una vez que ya tengo un poco de material para dar a conocer y contribuir un poco con la comunidad desarrolladora de GNU&Linux, resulta que desde hace ya algunos años quería cambiarme del Sistema Operativo (SO) de las ventanas a GNU&Linux y por una u otra razón nunca hacía el cambio total, pero desde Septiembre del año pasado (2010) tomé esa decisión y no hubo vuelta atrás, me decidí por Ubuntu 10.04 y al poco tiempo cambié al 10.10 y en una siguiente entrada les comentaré más sobre la experiencia de cambio pero les puedo adelantar que no he regresado a las ventanas ni para tomar aire ni impulso ya que todo lo he encontrado en GNU&Linux.

El motivo de esta primera entrada es comentarles que encontré muy llamativa la opción que trae Ubuntu de poder seleccionar un grupo de imágenes (les llamé temas) como fondo de escritorio y que éstas se cambien automáticamente a medida que pasan algunos minutos, por default Ubuntu trae el grupo de imágenes del Cosmos (ver Captura 1) y las imágenes cambian cada 29 minutos con 5 segundos y se efectúa el cambio en los siguientes 5 segundos.

Captura 1

Debido a que me gustó esa opción de poder tener un grupo de imágenes me tomé la tarea de buscar un poco en Internet de cómo podría hacer mi propio tema de fondos de escritorio y encontré que si selecciono el tema de Cosmos y lo arrastro al escritorio (Captura 2) podría ver un archivo con formato XML (Archivo 1).

Captura 2

Información contenida en background-1.xml

  
    2009
    08
    04
    00
    00
    00
  

  
    1795.0
    /usr/share/backgrounds/cosmos/cloud.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/cloud.jpg
    /usr/share/backgrounds/cosmos/comet.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/comet.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/comet.jpg
    /usr/share/backgrounds/cosmos/earth-horizon.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/earth-horizon.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/earth-horizon.jpg
    /usr/share/backgrounds/cosmos/blue-marble-west.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/blue-marble-west.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/blue-marble-west.jpg
    /usr/share/backgrounds/cosmos/galaxy-ngc3370.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/galaxy-ngc3370.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/galaxy-ngc3370.jpg
    /usr/share/backgrounds/cosmos/helix-nebula.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/helix-nebula.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/helix-nebula.jpg
    /usr/share/backgrounds/cosmos/jupiter.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/jupiter.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/jupiter.jpg
    /usr/share/backgrounds/cosmos/sombrero.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/sombrero.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/sombrero.jpg
    /usr/share/backgrounds/cosmos/whirlpool.jpg
  
  
    1795.0
    /usr/share/backgrounds/cosmos/whirlpool.jpg
  
  
    5.0
    /usr/share/backgrounds/cosmos/whirlpool.jpg
    /usr/share/backgrounds/cosmos/cloud.jpg
  

Archivo 1

Al analizar un poco el archivo me dí cuenta que podría cambiar la ruta de las imágenes (<file>/usr/share/backgrounds/cosmos/whirlpool.jpg</file>) que yo quiero agregar al nuevo tema y también podría cambiar el tiempo en que se presentan estáticas en la pantalla (
<static>
    <duration>1795.0</duration>
) y el tiempo en que se cambian (
<transition>
    <duration>5.0</duration>
) pero ese trámite es un poco engorroso para aquellos que no queremos editar algún archivo siguiendo algún formato por lo que me decidí a desarrollar un programa gráfico (le llamo MyImageDesktop ver Captura 3) que nos ayude a seleccionar las imágenes que queremos agregar a un tema y además que me permita seleccionar el tiempo que me gustaría que permanezca en la pantalla antes de cambiarla por la siguiente y así contribuir un poco con la comunidad para enriquecer este SO.

Captura 3

MyImageDesktop está en la primera parte (v0.2) después de efectuar algunas pruebas, podemos agregar imágenes seleccionando el botón "Añadir" o bien seleccionando del menú "Editar" la opción "Agregar". Con eso nos presentará una ventana (Captura 4) donde podemos seleccionar el archivo JPG o PNG (por el momento solo JPG pero pronto agregaré los PNG) y podemos ver una vista previa en la parte de la derecha de la esa ventana. 

Captura 4

También podemos cambiar el tiempo en segundos en que la imagen permanecerá estática hasta que se cambie a la siguiente y podemos guardar nuestro archivo en cualquier lugar que queramos con el nombre que nos guste pero con terminación xml, para después arrastrar el archivo creado a las preferencias de la pantalla en la pestaña de Fondos de escritorio.

En la segunda versión de MyImageDesktop nuestro amigo Heladio nos agregó la funcionalidad de "Subir" y "Bajar" una fila de la lista de archivos con la finalidad de ordenar nuestros archivos a nuestro gusto :)

Por el momento es todo, les dejo los archivos necesarios para ejecutar MyImageDesktop. Para ejecutarlo debes descargar el archivo correspondiente a tu tipo de SO y descargar también el archivo MyImageDesktop.glade y colocarlos en el mismo directorio para después ejecutar desde una ventana (terminal) de comandos en el directorio donde se encuentran los archivos la instrucción ./MyImageDesktop

Ejecutable Ubuntu_x86 y Ubuntu_amd64
Fuente en lenguaje C

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...