GTK+
Por Subhasísh Ghosh
El código fuente incluido junto con el texto, ha sido probado en una computadora con la
siguiente configuración: Compaq Presario 4010 Series system, 15.5 GB de espacio en
disco duro, 96 MB RAM, procesador Intel Celeron a 400 MHz, Red Hat Linux 7.1
kernel: 2.4.2-2
Este artículo ha sido dividido en las siguientes secciones para un fácil entendimiento:
Ahora miremos a GNOME desde "el punto de vista del programador", así como desde
"el punto de vista del administrador del sistema”. La pregunta básica que viene a la
mente es: ¿piensan y sienten lo mismo cuando hablan acerca de GNOME?, esto no es
fácil de responder, la mayoría de los administradores Linux, son o han sido
programadores Linux en el pasado, lo cual, hace bastante difícil el responder a esta
pregunta. Para la mayoría de los administradores de sistemas Linux, el ambiente
GNOME provee abundantes herramientas que hacen que el trabajo de administración
sea muy simple. Por lo pronto, el programador GNOME tiene la responsabilidad de
continuar abasteciendo esas facilidades diseñando programas aún mejores. Entonces,
están en una perfecta armonía el uno con el otro al grado de que sus respectivas labores
se afectan entre sí.
2. La arquitectura GNOME.
La extremadamente poderosa, sin embargo, flexible arquitectura de GNOME, es lo que
proporciona a GNOME su estupenda funcionalidad. El conjunto de herramientas base
en GNOME es llamado GTK+(the GIMP toolkit). Fue originalmente escrito para usarse
en GIMP (GNU Image Manipulation Program). La adecuada comprensión de GTK+ es
extremadamente necesaria para la asimilación de la programación GNOME. GTK+ es
un conjunto de herramientas orientadas a objetos, de plataforma cruzada y
lenguaje neutral, que es ante todo, usada para crear aplicaciones independientes de
GNOME. Entonces la pregunta que viene es: ¿por que fue GTK+ elegido como el
conjunto de herramientas(toolkit) para GNOME?, la respuesta es simple, fue por su
soporte a muchos lenguajes de programación incluidos C, C++, PERL, Python, ADA
etc. Sin embargo, es útil siempre tener en cuenta que GNOME, al igual que GTK+, fue
escrito usando C; de tal forma que aquí estaríamos tratando con C únicamente.
Otra pregunta que debe surgir en la mente del lector es: ¿que es lo que contienen esas
cosas llamadas "Toolkits"?, los toolkits como GTK o Qt(el ambiente KDE esta basado
en Qt), son colecciones de widgets. Lo cual nos trae la pregunta ¿que son los
"Widgets"?
Los Widgets son controles GUI como botones, menús, cajas de diálogo y otros como
los objetos relacionados a funciones generales. Esto puede ser comparado con la Active
Template Library (ATL 3.0) sobre la plataforma Microsoft, la cual proporciona a los
desarrolladores COM(Component Onject Model) con un armazón listo y hecho para
crear objetos y componentes COM(ActiveX, EXE's y ActiveX DLL's).
3. GTK+ - Introducción.
Ahora demos un vistazo más de cerca a algunas de las características de GTK+:
gchar char
gshort short
glong long
gint int
gboolean boolean
gpointer void*
GtkObject --> GtkWidget --> GtkContainer --> GtkBin --> GtkWindow --> GnomeApp
Así, si miras cuidadosamente, puedes ver que el widget GnomeApp es derivado del de
mayor nivel GtkWindow, el cual en sí mismo ha sido derivado del de mayor nivel
GtkBin y así sucesivamente. Si tomamos en cuenta las características esenciales de la
programación en lenguaje C++, esto nos trae a la memoria el concepto de "Herencia".
¿no es así?, seguramente lo es. Y es en este aspecto de la "herencia de widgets" en el
que se incorpora la funcionalidad derivada en GTK+.
Demos ahora una breve mirada a las funciones de creación de widgets. Para que estas
funciones operen correctamente, primero debemos asegurarnos de tener todas las
librerías GTK+ y GNOME instaladas correctamente, otra cosa importante a tomar en
cuenta es que la ruta de las librerías debe de ser correcta, hazlo antes de intentar
compilar cualquier código fuente.
GtkWidget *ghosh;
ghosh = gnome_app_new(………);
Debemos notar que esto significa que si queremos llamar a una función especifica de
GnomeApp como gnome_app_set_menús(), entonces tenemos que usar una macro para
realizar el enlace de desde el tipo GtkWidget a el tipo GnomeApp; lo cual solo es
posible ya que GnomeApp es derivada de GtkWidget (observa la herencia mostrada
anteriormente).
4. Un programa básico.
La mejor forma de aprender la programación Linux es entender el trabajo interno del
kernel y haciendo programas por tí mismo. así que, ahora miremos un pequeño
programa para entender mejor el tema.
GtkWidget *ghosh;
gnome_init("sample", "0.1", argc, argv);
ghosh = gnome_app_new("sample", "My Window");
gtk_widget_show(ghosh);
gtk_main();
return 0;
Ahora, para compilar el programa myapp.c, asegúrate de teclear bien (toma en cuenta
las comillas simples):
# ./myapp &
y presiona enter.
Una ventana vacía aparecerá en la pantalla, la cual puedes mover, ajustar el tamaño, así
como cerrar. Ahora miremos detenidamente el código. Al principio, introducimos
algunas líneas de comentarios, describiendo el programa, su creador y la fecha de
creación, aunque no es necesario, es una buena práctica de programación incluir
comentarios a cada programa. Después, incluimos el archivo de cabecera gnome.h, que
se encarga de todas las librerías GTK+ y GNOME así como de las funciónes y
definiciones necesarias, luego viene "gosh", que es un puntero a GtkWidget, este
apuntara a nuestro nuevo objeto ventana. La función gnome_init es entonces llamada,
esta inicializa librerías y es usada para un correcto manejo de sesión. La identificación
que se le pasa a la función gnome_init es "sample", el número de versión es "0.1" y la
usual línea de argumentos de la función main, estos son necesarios para el trabajo
interno de GNOME. Luego viene la función gnome_app_new(), que cuando es
ejecutada, crea nuestra ventana, esta toma dos argumentos, como se muestra en el
código: "sample" y "My Window". "Sample" es el nombre de la aplicacion y "My
Window" es el titulo de la ventana. Pero hay que notar que: aunque el nombre de esta
función es gnome_app_new(); esta NO crea ningún tipo de nueva aplicación o algo así;
crea una ventana top-level, eso es todo. La siguiente función llamada es
gtk_widget_show(), la cual hace visible nuestra ventana. Luego viene gtk_main(), la
cual es una función muy importante, ya que asegura que funciónes GNOME como son
los eventos y pulsaciones de botones sean ejecutados mediante el paso de funcionalidad
a GNOME.
Se debe notar que distintos tipos de widgets emiten señales diferentes. Las señales de
los botones son:
Examinaremos que las Señales y Callbacks juegan un rol vital en las aplicaciones que
desarrollaremos mas tarde.
6. Contenedores.
A continuación, veremos otro componente vital de la programación GNOME:
contenedores. GTK+ utiliza una gran cantidad de contenedores, debido a que GTK+ es
realmente un conjunto de herramientas basado en contenedores, lo que significa que
tenemos un contenedor padre dentro del cual tenemos que ubicar nuestros widgets. Las
ventanas son simples contenedores de widgets. De tal manera que, el punto importante a
tomar en cuenta es que GTK+ utiliza "cajas empaquetadas" invisibles las cuales pueden
contener múltiples widgets para crear diseños de ventana. Estas "cajas empaquetadas"
son de dos tipos: horizontales y verticales, creadas usando la funcionalidad de las
funciónes gtk_hbox_new y gtk_vbox_new, respectivamente. Pronto veremos que estas
funciones en acción, en las aplicaciones que crearemos mas tarde. Por ahora,
examinemos los parámetros de estas dos funciones:
7. Botones.
Ahora viene otro componente vital: botones. GTK+ proporciona 4 diferentes tipos de
botones:
8. Widgets de entrada.
Para crear widgets de texto de una sola línea, que son comúnmente llamados "widgets
de entrada", utilizamos una función llamada gtk_entry_new(). Los widgets de entrada
son principalmente usados para introducir pequeñas cantidades de información.
Miremos ahora un programa que crea una "ventana de acceso", y despliega el campo
password, la señal activa ocurre, cuando el botón ha sido pulsado. Teclea lo siguiente y
ejecuta el programa como ha sido explicado.
#include <gnome.h>
text_entry = gtk_entry_new();
gtk_entry_set_visibility(GTK_ENTRY(text_entry), FALSE);
gtk_box_pack_start(GTK_BOX(hbox), text_entry, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(app), "delete_event",
GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
gtk_signal_connect(GTK_OBJECT(text_entry), "activate",
GTK_SIGNAL_FUNC(enter_pressed), text_entry);
gnome_app_set_contents(GNOME_APP(app), hbox);
gtk_widget_show_all(app);
gtk_main( );
return 0;
}
9. Lista y combos.
Las listas y combos juegan el mismo papel que desempeñan en la plataforma Microsoft.
Los widgets lista agrupan una lista de cadenas de caracteres que permiten a los usuarios
seleccionar una o mas entradas; involucrados en esto, los widgets son así configurados.
Las listas son widgets de entrada con un menú emergente agregado que permite a los
usuarios seleccionar las opciones disponibles.
Solo espera un segundo, alguien puede preguntar: "Hey, lo estábamos haciendo bastante
bien con código ordinario y todas esas cosas con las que tratamos anteriormente. ¿Cual
es el uso de eso llamado "librerías especificas de programación GNOME"?, ¿son de
verdad útiles? o ¿estas solo incluyéndolas aquí para hacer tu artículo mas grande?"
Los menús y barras de herramientas tienen cada uno sus propiedades definidas en
arreglos. Algunas de estas propiedades incluyen tipo, string, callback ponter, etc. La
mayor parte del tiempo las entradas a los menús son bastante simples, y podemos usar
una o un conjunto de macros suministradas por GNOME que creara la estructura por
nosotros; Revisemos algunas de las macros mas utilizadas.
NOTA: estas macros son las que crean menús de nivel superior cuando un arreglo es
transmitido conteniendo algunas o todas las siguientes estructuras GnomeUIInfo.
menú Macro
File GNOMEUIINFO_menú_FILE_TREE(tree)
Edit GNOMEUIINFO_menú_EDIT_TREE(tree)
View GNOMEUIINFO_menú_VIEW_TREE(tree)
Settings GNOMEUIINFO_menú_SETTINGS_TREE(tree)
Windows GNOMEUIINFO_menú_WINDOWS_TREE(tree)
Help GNOMEUIINFO_menú_HELP_TREE(tree)
Game GNOMEUIINFO_menú_GAME_TREE(tree)
Dentro de los menús de nivel superior existen más de treinta macros para crear menús
comunes. Las macros asocian pequeñas imágenes (pixmaps) y combinaciones de teclas
para cada opción del menú. Una función Callback es requerida para ser llamada cuando
la opción es seleccionada y un apuntador de datos es pasado a la función.
File -->>
New --> GNOMEUIINFO_menú_NEW_ITEM (label, hint, cb, data)
Open --> GNOMEUIINFO_menú_OPEN_ITEM (cb, data)
Save --> GNOMEUIINFO_menú_SAVE_ITEM (cb, data)
Print --> GNOMEUIINFO_menú_PRINT_ITEM (cb, data)
Exit --> GNOMEUIINFO_menú_EXIT_ITEM (cb, data)
Edit -->>
Cut --> GNOMEUIINFO_menú_CUT_ITEM (cb, data)
Copy --> GNOMEUIINFO_menú_COPY_ITEM (cb, data)
Paste --> GNOMEUIINFO_menú_PASTE_ITEM (cb, data)
Settings -->>
Preferences --> GNOMEUIINFO_menú_PREFERENCES_ITEM (cb, data)
Help -->>
About --> GNOMEUIINFO_menú_ABOUT_ITEM (cb, data)
Al igual que los menús, las barras de herramientas requieren de un arreglo usando la
macro GNOMEUIINFO_ITEM_STOCK (label, tooltip, callback, stock_id). Aquí,
"stock_id" es le identificador de un icono predefinido utilizado para esta opción.
Veamos este sencillo ejemplo, y observa como trabajan los arreglos y macros en
realidad.
#include <gnome.h>
GnomeUIInfo file_menú[ ] = {
GNOMEUIINFO_ITEM_NONE ("A menú item", "This is the Status bar info",
callback),
GNOMEUIINFO_menú_EXIT_ITEM (gtk_main_quit, NULL),
GNOMEUIINFO_END
};
GnomeUIInfo menúbar[ ] = {
GNOMEUIINFO_menú_FILE_TREE (file_menú),
GNOMEUIINFO_END
};
GnomeUIInfo toolbar[ ] = {
GNOMEUIINFO_ITEM_STOCK ("Print", "This is another tooltip", callback,
GNOME_STOCK_PIXMAP_PRINT),
GNOMEUIINFO_ ITEM_STOCK ("Exit", "Exit the application", gtk_main_quit,
GNOME_STOCK_PIXMAP_EXIT),
GNOMEUIINFO_END
};
GtkWidget *app;
gtk_widget_show_all (app);
gtk_main();
return 0;
Este programa crea una pequeña ventana con un menú empotrado y una barra de
herramientas. Puedes hacerle click, fijarlo, liberarlo y arrastrarlo por la pantalla.
Veamos este extracto de código de un programa, el cual crea una simple caja de
diálogo, agrega tres botones y responde a el código del usuario..
switch (button)
{
case 1: /* user pressed apply */
return;
GtkWidget *dlg;
gtk_widget_show (dlg);
NOTA: la programación GNOME no es en absoluto difícil. Una vez que tienes un poco
de conocimiento, es realmente sencilla de comprender. Aun hay mucho más por
aprender después de este artículo, pero terminado diligentemente, puede ser
definitivamente dominado.
Para más información y cobertura detallada de este tópico, revisa las siguientes
direcciones:
http://www.linuxheadquarters.com/howto/programming/gtk_examples/index.shtml
http://www.ibiblio.org/pub/Linux/docs/HOWTO/mini/other-
formats/html_single/Programming-Languages.html
http://linuxheadquarters.com/howto/programming/gtk_examples/window/window.shtml
http://developer.gnome.org/doc/GGAD/ggad.html
http://wolfpack.twu.net/docs/gtkdnd/index.html
Subhasísh Ghosh