|-----------------------------------------------------------------------------| [ 7a69#14 ] [ 21-10-2002 ] \ / \-------------------------------------------------------------------------/ { 12 - Programando con GLADE y LibGlade. }{ Fkt } |-----------------------------------------------------------------------| Hola, lo que me ha llevado a escribir este documento es que en español hay m cha teoría sobre el tema pero he visto pocos ejemplos explicado en nuestro idioma, por no decir ninguno, con lo cual me centraré mas en la parte prácti- ca que en la teoría. 1. Requerimientos 2. GLADE 2.1 ¿Qué es? 2.2 Haciendo Una Interfaz Gráfica 2.3 Modificando Una Interfaz Gráfica Ya Existente 3. LibGlade 3.1 Introducción 3.2 Dando forma 3.3 Como Compilar Nuestro Programa 3.4 Soportes 3.4.1 GNOME 3.5 Recuperando Widgets 3.6 Definiendo y Manejando Signals 4. Ejemplos De Widgets GTK+ 1.2 4.1 GtkLabel 4.2 GtkButton 4.3 GtkToggleButton 4.4 GtkEntry 4.5 GtkSpinButton 4.6 GtkCombo 4.7 GtkText 5. Ejemplos Widgets De GNOME 5.1 GnomeAppBar 5.2 GnomeDateEdit 6. Conclusión 7. Bibliografía Bueno pues empecemos... 1. Requerimientos Doy por hecho que el lector tiene, por lo menos, conocimientos básicos de C. Para seguir el documento se necesitará una maquina con X-Windows donde correr GLADE obviamente y si se quiere probar los Widgets de GNOME pues tener GNOME. 2. GLADE 2.1 ¿Qué Es? Bueno como dije antes no me extenderé en la parte teórica asi que lo explica- ré a mi manera sin caer en definiciones técnicas. GLADE es un IDE para crear el interfaz gráfico de una aplicación fácilmente usando GTK y asi permitir al programador que se centre en lo que es realmente el _core_ del programa. Lo que quiere decir que con unos pocos de clicks nuestro programa de consola tendrá una bonito aspecto en las X-Windows ;) 2.2 Haciendo una Interfaz Gráfica Ahora ejecutamos glade desde un terminal y vemos que nos salen 3 ventanas: la de Propiedades (Properties), la Paleta de Widgets (Palette) y la Principal donde podremos guardar nuestro proyecto y demás. Paso a explicar la parte que he definido como Principal: en el menú File creo que están todas las opciones claras excepto la de Build Source Code y la de Project Options, con lo que solo explicaré esas dos; la opción de Build Sour- ce code no la usaremos porque aparte de que el código que genera el GLADE es dificil de manejar, por lo que tengo entendido en GLADE 2 esta opción se qui- tará; pinchamos en Project Options y en la pestaña General vemos que le pode- mos cambiar el nombre la proyecto, cambiarlo de carpeta, etc... Lo de langua- ge nos da igual porque no vamos a usar la opción de Build Source Code. Si queremos soporte GNOME pues marcariamos la casilla de Enable Gnome Support pero como eso lo vamos a hacer luego a mano pues esa opción también es indi- ferente como la pongais. Las otras 2 opciones tampoco las usaremos porque co- mo ya he dicho varias veces no vamos a usar el Build Source Code. Bueno la ventana de Propiedades varia según el widget que estemos usando y en la Paleta pues están los widgets que tendremos a nuestra disposición. Otra vetana que nos puede ser bastante útil es la de Show Widget Tree que la po- dremos activar dandole a View, Show Widget Tree y nos muestra en estructura de árbol la jerarquia de los Widgets. Una vez puesto a punto el entorno donde trabajaremos ya podemos hacer nuestra primera aplicación gráfica para ello en la Paleta pincharemos en GTK+ Basic y pincharemos el Widget Window, ahora si colocaramos otro Windget en la vetana que acabamos de crear ocuparía toda la ventana, ésto es porque en GLADE hay que ir poniendo Containers y ahi meter los Widgets. Pues nada eso vamos a ha- cer asi que como nuestro fin es hacer una aplicación que abra un simple so- cket a un host y a un puerto determinado pues pinchamos en el container Ver- tical Box que divide la pantalla verticalmente, cuando pinchamos nos sale un cuadro de diálogo que nos pide cuantas filas (rows) queremos poner, le deci- mos que 3, en la de arriba pondremos una toolbar con 2 botones asi que pin- chamos en el widget toolbar, pinchamos en la división de arriba y cuando nos pida el número de botones le decimos que 2. Ahora pondremos los botones a la toolbar, para ello pinchamos en el widget button y a continuación en el lugar de la toolbar donde lo queramos poner, buag! pero que icono mas feo nos ha salido, para cambiarlo seleccionamos el botón y nos vamos a la ventana de propiedades, en Icon le damos a la lista desplegable donde nos saldrán varios iconos prediseñados (también podemos nosotros diseñar nuestro propio icono), pinchamos en el Close, ahora en Label pondremos "Salir", y en Name pondremos "salir_boton" para luego identificarlo mejor al manejar las signals. Ahora ha cemos lo mismo para añadir el otro botón, esta vez le pondremos de icono el prediseñado Help, en Label "Acerca De..." y en Name "about_boton". Ahora la división del medio la dividiremos en en 2 con el container Horizontal Box, pinchamos en Horizontal Box, luego en la división del medio y le decimos que lo divida en 2 columnas, ahora con esas 2 subdivisiones haremos lo mismo y dividiremos cada una en 2 de nuevo con el Horizontal Box. Bueno espero que no os hayais liado demasiado ;), la aplicación debería quedar como el Sino os te queda igual pues repasa los pasos anteriores :) Ahora en la division del medio de más a la izquierda pondremos un widget la- bel para ello pinchamos en la Paleta en el widget Label y luego en la divi- sión donde lo queremos meter, lo seleccionamos y le cambiamos el Label a "Host" y el X Pad lo ponemos a 7 para que no nos salga muy pegado al borde. Lo siguiente que haremos será meter un campo de texto al lado de "Host" asi que pinchamos en el widget Text Entry y luego en la división que hay al lado del Label "Host", al Text Entry en las Propiedades, en la pestaña Place pon- dremos de Padding 7 para que no quede pegado al siguiente widget y de Name pondremos "host_text". Bueno ahora haremos lo mismo que con el label Host y el Text Entry en las 2 otras divisiones solo que al Label le pondremos de Label "Puerto" y al Text Entry de Name "puerto_text". Bueno llegado a este punto la Aplicación tiene que estar como . Ahora en la división de abajo pondremos un botón, asi que pinchamos en el widget button y luego en la división de abajo, ahroa nos vamos a la ventana de Propiedades y en Stock Button seleccionamos OK y nos saldrá un botón ya prediseñado y le cambiaremos el Name a "aceptado". Ahora cambiaremos en nom- bre de la primera vetana que creamos para ello nos vamos al Widget Tree y seleccionamos window1 y en las Propiedades cambiamos el Tittle a "Socket". Y ya hemos terminado nuestro interfaz gráfico que nos tendría que quedar como en . Para guardarlo de le damos al icono Save de la vetana Principal del GLADE y nos guarda un archivo project1.glade en XML que luego "engancharemos" con Lib Glade. 2.3 Modificando Una Interfaz Gráfica Ya Existente Vaya! resulta que se nos ha olvidado poner algún widget para saber si el so- cket ha podido conectar o no, o simplemente si se ha podido crear o no, pues no hay problema!, abrimos con el GLADE el archivo project1.glade, hacemos do- ble click en el window1 que sale en la ventana principal del GLADE y nos sale nuestro proyecto tal y como lo dejamos. Lo que haremos será añadir una divi- sión abajo y poner una barra de status, para ello vamos al Widget Tree y bus- camos el container vbox1 (Vertical Box 1) y lo seleccionamos, ahora vamos a las Propiedades y en Size le ponemos un 4 e voila! ya hay una división mas abajo ;), ahora en la Paleta pinchamos en Gnome ya que vamos a poner una Gno- me Application Bar que queda mas bonita que una StatusBar de GTK Basic ;), y luego pinchamos en la división que hemos hecho abajo. En las Propiedades de la GnomeAppBar le pondremos de Name "status_bar" para identificarla mejor y le quitamos el Progress porque no lo vamos a utilizar ya que nuestra aplica- ción es demasiado sencilla, en los ejemplos de los widgets explicaré como usar todo de la GnomeAppBar. Joder!! se nos ha olvidado también hacer una ventanita de "Acerca de..." para cuando pinchen en el botón asi que vamos a hacerla, nos vamos a la paleta a Gnome porque ya trae una prediseñada y nos quita trabajo ;), pinchamos en el widget Gnome About Dialog y nos sale una bonita ventana de about ;=), la se- leccionamos y en las Propiedades, en Author pondreis vuestro nombre y en co- mments pondremos "Mi primer programa en GTK+". Ahora si tenemos la interfaz terminada asi que la guardamos y nos tiene que haber quedado como . Como habeis podido comprobar es sumamente fácil agregar cosas a un programa que se ha quedado obsoleto o que simplemente queremos que haga mas cosas. 3. LibGlade 3.1 Introducción LibGlade nos permitirá "enganchar" el XML que crea el GLADE para luego hacer lo que queramos con él en muchos lenguajes de programación aunque en este do- cumento solo trataremos como se hace en C. 3.2 Dando Forma Bueno ahora entraremos en a verdadera "chicha" de la aplicación que estamos creando, vamos a escribir el código que nos permitirá manejar nuestra aplica- ción gráfica desde C, el código es el siguiente: #include #include #define FICH_GLADE "project2.glade" GladeXML *prog; int main(int argc, char *argv[]) { gtk_init(&argc, &argv); glade_init(); prog=glade_xml_new(FICH_GLADE, NULL); glade_xml_signal_autoconnect(prog); gtk_main(); return 0; } NOTA: No voy a explicar ningún código entero solo lo que hacen las funciones a las que hace referencia el título de este documento, ya se dijo al principio que se requerian unos básicos conocimientos en C. En el #define de FICH_GLADE pondremos en archivo XML que generó el GLADE, en mi caso project2.glade, definimos un puntero a la estructura GladeXML que usaremos para "enganchar" el XML y luego usarla desde otros archivos del pro- yecto para manejar los widgets (de ahí que la definamos como variable global) La función glade_xml_new crea un nuevo objeto GladeXML con sus correspondien- tes widgets a partir de FICH_GLADE. glade_xml_signal_autoconnect conecta las signals que hayamos puesto con sus correspondientes widgets. gtk_main entra en un loop esperando a que suceda algún evento en las X-Windows como que ha- gan click en un boton del programa. 3.3 Como Compilar Nuestro Programa Una vez tenemos ya hecho el main.c vamos a compilarlo: gcc -o socket main.c `libglade-config --cflags --libs` lo que hace el comando libglade-config --cflags --libs es imprimir por panta- lla donde están las librerias necesarias y las librerias que tiene que linkar para que compile el programa. Una vez lo tenemos compilado lo ejecutamos.... y.... oohhh!! que le ha pasado a mi programa!!! no salen los dibujitos y ademas cuando lo ejecuta me da 2 warnings: ** WARNING **: unknown widget class 'GnomeAppBar' ** WARNING **: unknown widget class 'GnomeAbout' Bien, ésto pasa porque los widgets GnomeAppBar y GnomeAbout son de Gnome y nuestro programa no tiene soporte para Gnome. El main.c que hemos hecho ser- viría si solo usasemos widgets de GTK+ Basic y sin usar botones e iconos pre- definidos. Para cerra nuestro programa hacemos un Control+C en la consola donde lo hayamos ejecutado ya que aún no le hemos puesto signals para que se cierre pinchando en un botón. 3.4 Soportes 3.4.1 GNOME Como hemos comprobado nuestro programa necesita que le pongamos soporte para Gnome asi que eso es lo que haremos y el código quedaría así: #include #include #include #define FICH_GLADE "project2.glade" #define VERSION "0.1" GladeXML *prog; int main(int argc, char *argv[]) { gnome_init ("Socket", VERSION, argc, argv); glade_gnome_init(); prog=glade_xml_new(FICH_GLADE, NULL); glade_xml_signal_autoconnect(prog); gtk_main(); return 0; } Vemos que hemos añadido un #include que creo que es obvio y un #define más pa ra indicar la versión de nuestro programa, hemos cambiado gtk_init por gnome_init para que en el diálogo de about nos diga el nombre de nuestro pro- grama y la versión, y por último hemos cambiado glade_init por glade_gnome_init. Ahora lo compilamos... gcc -o socket main.c `libglade-config --cflags --libs gnome` Ahora ejecutamos el programa y ya si sale como nosotros queriamos pero nos sale la ventana de "Acerca De..." al iniciar el programa, esto tenemos que arreglarlo. Para arreglarlo se me ocurre que para practicar algo de código y tal, lo bo- rraremos del GLADE asi que abrimos nuestro proyecto con el GLADE y en el Wid- get Tree le damos con el botón derecho del ratón a about1 y pinchamos en Dele lete y guardamos nuestro proyecto. Ahora haremos una función que genere el diálogo de about cuando nosotros queramos: GtkWidget* crear_about(void) { const gchar *authors[]={ "fkt", NULL }; GtkWidget *about; about=gnome_about_new("Socket", VERSION, "", authors, _(""), NULL); return about; } Es una función que devuelve un widget, authors es un registro que hay que re- llenar para luego al crear la ventana de about, gnome_about_new devuelve un widget, Socket es el nombre del programa, VERSION la versión, authors la es- tructura que hemos rellenado antes y lo otro mi mail. 3.5 Recuperando Widgets Supongamos que queremos recuperar el Widget button que le llamamos salir_bo- ton pues se haría de la siguiente manera: GtkWidget *salir_boton; salir_boton=glade_xml_get_widget(prog, "salir_boton"); Hemos definido un widget salir_boton donde almacenaremos lo que nos devuelva la función glade_xml_get_widget que, en este caso, lo que hace es devolver el widget que le corresponda a salir_boton en el GladeXML prog y ya podemos ha- cer lo que queramos con él. Como habeis podido comprobar es bastante fácil recuperar los widgets que he- mos definido en el GLADE y jugar con ellos. 3.6 Definiendo y Manejando Signals Todo esto esta muy bien pero... para que sirve si luego no podemos hacer que si clickeas en un widget botón nos salga la ventana de about por ejemplo? Bien, pues para ésto están las signals, para definirlas lo haremos en el GLA- DE ya que luego el LibGlade con glade_xml_signal_autoconnect se encargará de conectarlas a sus respectivos widgets. Así que abrimos el GLADE con nuestro proyecto, hacemos doble click en window1 y seleccionamos el boton de acerca de..., nos vamos a la ventana de Propiedades a la pestaña de Signals y en el campo Signal le damos a los puntos suspensivos para que nos salga la lista de signals de ese widget, vemos que tenemos el signal clicked, enter, leave, pre ssed y released, a nostros el que nos viene mejor es el clicked asi que lo seleccionamos y le damos a añadir (add), hacemos lo mismo con el boton de Sa- lir y con el de OK. Ya tenemos las signals que necesitamos definidas, ahora guardamos el proyecto y haremos un main.h donde pondremos los widgets que recuperaremos en main.c y luego usaremos en otros .c, pero antes modificaremos el main.c para recupe- rar los widgets que vamos a usar y ademas añadiremos una llamada a la función gnome_appbar_status para poner en la barra de status "Listo." cuando ejecute- mos el programa, con lo que el main.c quedaría: #include #include #include #define FICH_GLADE "project2.glade" #define VERSION "0.1" GladeXML *prog; GtkWidget *about, *salir_boton, *about_boton, *aceptado, *puerto_text, *host_text, *status_bar, *window1; int main(int argc, char *argv[]) { gnome_init ("Socket", VERSION, argc, argv); glade_gnome_init(); prog=glade_xml_new(FICH_GLADE, NULL); glade_xml_signal_autoconnect(prog); salir_boton=glade_xml_get_widget(prog, "salir_boton"); about_boton=glade_xml_get_widget(prog, "about_boton"); aceptado=glade_xml_get_widget(prog, "aceptado"); puerto_text=glade_xml_get_widget(prog, "puerto_text"); host_text=glade_xml_get_widget(prog, "host_text"); status_bar=glade_xml_get_widget(prog, "status_bar"); window1=glade_xml_get_widget(prog, "window1"); about=glade_xml_get_widget(prog, "about1"); gtk_widget_destroy(about); gnome_appbar_set_status(GNOME_APPBAR(status_bar),"Listo."); gtk_main(); return 0; } GtkWidget* crear_about(void) { const gchar *authors[]={ "fkt", NULL }; GtkWidget *about; about=gnome_about_new("Socket", VERSION, "", authors, _(""), NULL); return about; } Y el main.h será el siguiente: #include #include #include GtkWidget* crear_about(void); GtkWidget *about, *salir_boton, *about_boton, *aceptado, *puerto_text, *host_text, *status_bar, *window1; NOTA: Esto se podría haber hecho poniendo en el .h el GladeXML y luego desde los otros .c recuperar los widgets o también se podría hacer hasta sin tener un .h, pero creo que así esta mejor estructurado con lo cual en nuestro ejemplo se hará así. Ahora crearemos un fichero principal.c donde controlaremos las signals y crea remos el socket. Las funciones que controlarán las signals se llamarán como hemos definido en el GLADE, por ejemplo para cuando se haga click en el boton de salir de la ToolBar se ejecutará la siguiente función: void on_salir_boton_clicked (GtkButton *button, gpointer user_data) { ; } Los prototipos de las signals asi como las propiedades de cada widget las po- deis ver en las Referencias que pondré al final, aunque en los ejemplos de widgets trataré de explicar la gran mayoría (todas no porque sino este docu- mento sería interminable ;)). Bueno ahi va el fichero principal.c: /* Includes para el socket y atoi() */ #include #include #include #include #include #include #include "main.h" /* Función para resolver un host que me prestó Ripe */ unsigned long resolv(char *name); // Thx A Ripe /* Función que se encarga de conectar el socket */ unsigned int conecta(struct sockaddr_in addr); /* Función que se ejecutará cuando se haga click en salir_boton */ void on_salir_boton_clicked (GtkButton *button, gpointer user_data) { gtk_exit(0); // Termina el programa } /* Función que se ejecutará cuando se haga click en about_boton */ void on_about_boton_clicked (GtkButton *button, gpointer user_data) { about=crear_about(); // Creamos el diálogo de about gtk_widget_show(about); // Y lo mostramos } /* Función que se ejecutará cuando se haga click en aceptado */ void on_aceptado_clicked (GtkButton *button, gpointer user_data) { struct sockaddr_in addr; unsigned int ret; // control de errores char tmp[1024]; /* gtk_entry_get_text devuelve un gchar* que se corresponde con con lo */ /* que el usuario ha escrito en el widget que se le pasa como parámetro */ /* lo de GTK_ENTRY es para conersión de tipos y que el compilador no de */ /* warning, lo vereis en muchas funciones */ addr.sin_addr.s_addr=resolv(gtk_entry_get_text(GTK_ENTRY(host_text))); addr.sin_port=htons(atoi(gtk_entry_get_text(GTK_ENTRY(puerto_text)))); addr.sin_family=AF_INET; if (addr.sin_addr.s_addr==INADDR_NONE) { ret=1; } else { ret=conecta(addr); } if (ret) { snprintf(tmp,1024,"NO Se Ha Podido Conectar a %s", inet_ntoa(addr.sin_addr)); /* gnome_appbar_set_status pone el gchar *tmp en el widget status_bar */ gnome_appbar_set_status(GNOME_APPBAR(status_bar),tmp); } else { snprintf(tmp,1024,"Se Ha Conseguido Conectar a %s", inet_ntoa(addr.sin_addr)); gnome_appbar_set_status(GNOME_APPBAR(status_bar),tmp); } } unsigned long resolv(char *name) { unsigned long ip; struct hostent *he=NULL; ip=INADDR_NONE; if (!inet_aton(name, (struct in_addr *)&ip)) { he=gethostbyname (name); if (he != NULL) memcpy (&ip, he->h_addr, sizeof (ip)); } return ip; } unsigned int conecta(struct sockaddr_in addr) { int sockfd; if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) return 1; if (connect(sockfd,(struct sockaddr *)&addr, sizeof(struct sockaddr))==-1) return 1; close(sockfd); return 0; } Bueno creo que el código es bastante simple y esta bien comentado asi que no creo que haya dudas, para compilar nuestro flamante programa haremos: gcc `libglade-config --cflags gnome` -g -O2 -Wall -c main.c gcc `libglade-config --cflags gnome` -g -O2 -Wall -c principal.c gcc `libglade-config --libs --cflags gnome` -g -O2 -Wall -o socket main.o principal.o Ha costado pero por fin tenemos nuestra primera aplicación gráfica ;) 4. Ejemplos De Widgets GTK+ 1.2 En este apartado pondré algunos ejemplos de como usar las funciones y signals de _algunos_ widgets, porque como dije antes... si pusiese todos este documen to se haría interminable, aun así animo a cualquier persona que tenga conoci- mientos sobre el tema a que escriba sobre los widgets que me deje yo en el tintero. Tampoco explicaré funciones que se derivan de propiedades, por ejem- plo para el widget Label para justificar el texto a la derecha en realidad se hace llamando a la función gtk_label_set_justify pero eso se puede hacer fa- cilmente con el GLADE en la ventana de Propiedades; ni tampoco funciones que hace el GLADE automáticamente al poner le widget como la de crearlo. 4.1 GtkLabel -¿Qué es?: Etiqueta. -Funciones: De aquí la única función que explicaré es gtk_label_get que lo que hace es po ner en un gchar que nosotros le demos el texto del label del widget. Por ejem plo si la propiedad label del widget tiene de contenido "OK" y el nombre (na- me) es "label1" pues haciendo gtk_label_get(GTK_LABEL(label1), buf); tendría- mos en buf "OK". El prototipo de esta función es: void gtk_label_get(GtkLabel *label, gchar **buf); -Propiedades: + justify: Justifica el texto, las macros que permiten hacer esto son: GTK_JUSTIFY_LEFT, GTK_JUSTIFY_RIGHT, GTK_JUSTIFY_CENTER y GTK_JUSTIFY_FILL. Se puede hacer facilmente desde la ventana de propiedades del GLADE. + label: Contiene el texto que tendrá la etiqueta. También se cambia facilmen con el GLADE. + pattern: Se usa mucho en los menús, es subrayar la letra que al darle hará la misma función que si dieramos un click con el ratón. Es facilmente modi- ficable en el GLADE. 4.2 GtkButton -¿Qué es?: Botón Simple. -Funciones: + gtk_button_presed: · Prototipo void gtk_button_pressed(GtkButton *button); Esta función manda el signal pressed al widget button. + gtk_button_released: · Prototipo void gtk_button_released(GtkButton *button); Manda el signal released al widget button. + gtk_button_clicked: · Prototipo void gtk_button_clicked(GtkButton *button); Manda el signal clicked al widget button. + gtk_button_enter: · Prototipo void gtk_button_enter(GtkButton *button); Manda el signal enter al widget button. + gtk_button_leave: · Prototipo void gtk_button_leave(GtkButton *button); Manda el signal leave al widget button. Un ejemplo de estas funciones anteriores podría ser: gtk_button_clicked(GTK_BUTTON(boton_salida)); Siendo GtkWidget *boton_salida; después de ejecutar esta función el progra- ma ejecutaría la función que hubiera asociada a este signal (si es que la hubiese), las demás funciones anteriores son análogas a ésta. + gtk_button_set_relief: Facilmente configurable desde GLADE, pone un estilo de relieve al botón de tipo GtkReliefStyle que puede ser: GTK_RELIEF_NORMAL, GTK_RELIEF_HALF o GTK_RELIEF_NONE. + gtk_button_get_relief: · Prototipo GtkReliefStyle gtk_button_get_relief(GtkButton *button); Dice el estilo de relieve que tiene el widget button. · Ejemplo estilo gtk_button_get_relief(GTK_BUTTON(boton1)); Siendo: GtkStyleRef estilo; GtkWidget *boton1; -Propiedades: + label: El texto que tendrá el botón. + relief: Relieve del botón. -Signals: + pressed: Cuando el botón se encuentra pulsado inicialmente. + released: Cuando el botón que estaba pulsado se "suelta". + clicked: Cuando se hace click en el botón con el ratón, si el puntero del ratón no está en el botón el signal no se emite. + enter: Cuando el puntero del ratón entra en el botón. + leave: Cuando el puntero del ratón sale del botón. Para todas estas signals el prototipo es el mismo: void funcion_predefinida_en_el_glade(GtkButton *boton, gpointer user_data); En el ejemplo del programa que hemos hecho en este documento se ve claramente 4.3 GtkToggleButton -¿Qué es?: Botón que si lo pulsas se queda "toggled" (pulsado) hasta que lo vuelvas a pulsar. -Funciones: + gtk_toggle_button_toggled: · Prototipo: void gtk_toggle_button_toggled(GtkToggleButton *boton); Cambia el estado del botón, si el botón estaba activado lo desactiva. + gtk_toggle_button_get_active: · Prototipo: gboolean gtk_toggle_button_get_active(GtkToggleButton *boton); Nos dice si el botón esta o no activado, si está activado devuelve TRUE y sino devuelve FALSE. + gtk_toggle_button_set_active: · Prototipo: void gtk_toggle_button_set_active(GtkToggleButton *boton, gboolean estado); Pone el botón en el estado que le digamos, activado o desactivado. Ejemplo: (Esto se suponiendo que ya se ha puesto el toggle button con el GLADE y se ha enganchado el XML) GtkWidget *bool_proxy; int usar_proxy=0; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(bool_proxy))) { usar_proxy=1; gtk_toggle_button_toggled(GTK_TOGGLE_BUTTON(bool_proxy)); } if (!usar_proxy) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bool_proxy),TRUE); } -Propiedades: + active: Estado del botón, si esta presionado o no. Es un gboolean (TRUE o FALSE). -Signals: + toggled: Cuando el estado del botón cambia, ya sea de TRUE a FALSE o viceversa. · Prototipo: void funcion_predef(GtkToggleButton *boton, gpointer user_data); 4.4 GtkEntry -¿Qué es?: Es una caja de texto. -Funciones: + gtk_entry_set_text: · Prototipo: void gtk_entry_set_text(GtkEntry *entry, const gchar *text); Pone un texto en la caja reemplazando el existente (si es que lo habia). + gtk_entry_append_text: · Prototipo: void gtk_entry_append_text(GtkEntry *entry, const gchar *text); Concatena el texto que habia en la caja (si es que lo habia) con el nuevo. + gtk_entry_prepend_text: · Prototipo: void gtk_entry_prepend_text(GtkEntry *entry, const gchar *text); Antepone el texto nuevo al que habia (si lo hubiese). + gtk_entry_get_text: · Prototipo: gchar* gtk_entry_get_text(GtkEntry *entry); Devuelve un puntero a gchar donde estará el contenido de la caja de texto. + gtk_entry_set_visibility: · Prototipo: void gtk_entry_set_visibility(GtkEntry *entry, gboolean visible); Si visible es FALSE lo que se escriba o haya en la caja aparecerá con aste- riscos (*), y si es TRUE aparecerá texto plano normal. + gtk_entry_set_editable: · Prototipo: void gtk_entry_set_editable(GtkEntry *entry, gboolean editable); Determina si esa caja de texto puede ser editada o no por el usuario, si editable es FALSE el usuario no podrá editarla. + gtk_entry_set_max_length: · Prototipo: void gtk_entry_set_max_length(GtkEntry *entry, guint16 max); Pone un máximo de caractéres a escribir en la caja de texto. Si el usuario se pasa de ese máximo los caractéres se truncarán hasta el máximo definido. NOTA: Muchas de estas funciones están obsoletas y serán reemplazadas por fun- ciones del widget GtkEditable. Ejemplo: GtkWidget *pass_text, *user_text; gchar *pass, *user; gtk_entry_set_text(GTK_ENTRY(user_text),"Pon Aquí Tu Usuario"); gtk_entry_set_visibility(GTK_ENTRY(pass_text),FALSE); /* Poner los caracteres visibles o no asi como ponerla editable o no */ /* es mas sencillo hacerlo desde GLADE */ gtk_entry_set_max_length(GTK_ENTRY(user_text),8); pass=gtk_entry_get_text(GTK_ENTRY(pass_text)); user=gtk_entry_get_text(GTK_ENTRY(user_text)); if (!strncmp(pass,user,8)) { /* g_print() es equivalente a printf(), imprime por la consola */ g_print("Usuario Válido\n"); } else { g_print("ERROR: Usuario NO Válido\n"); } -Propiedades: + max_length: es un guint (unsigned int) que indica el máximo de caracteres. + visibility: gboolean que indica si el texto saldrá en asteriscos o en texto plano. 4.5 GtkSpinButton -¿Qué es?: Es ideal cuando queremos que el usuario meta un valor y lo pueda incrementar en lo que nosotros queramos y tiene multiples propiedades para hacerlo más o menos estricto. -Funciones: Muchas las voy a omitir ya que es mucho mas sencillo ajustar las propiedades con el GLADE. En la vetana de Propiedades de un SpinButton tendremos lo si- guiente: Climb Rate es lo que escalará para ajustarlo. Digits serán los números decimales que habrá en el SpinButton. Numeric, si ponemos esto a Yes y el usuario mete un carácter será ignorado, excepto el '-' y el '.' Snap, si ponemos Snap a Yes cuando el usuario ponga un número que no esté en los incrementos definidos automáticamente se ajustará. Wrap, si la ponemos a Yes y el usuario se pasa de nuestro máximo, que suponga mos que es 5 automáticamente se pondrá un 5, lo mismo pasaría con el mínimo. Step Inc que será lo que subamos cada vez que el usuario pinche en la flecha del botón para incrementar, o igualmente pero decrementando. Las funciones más interesantes son: + gtk_spin_button_get_value_as_float: · Prototipo: gfloat gtk_spin_button_get_value_as_float(GtkSpinButton *spin_button); Almacena en un gfloat el valor que contenga el spin button. + gtk_spin_button_get_value_as_int: · Prototipo: gint gtk_spin_button_get_value_as_int(GtkSpinButton *spin_button); Almacena en un entero el contenido del spin button. Ejemplo: GtkWidget *spin; gint num; gfloat nfloat; nfloat=gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(spin)); num=gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(spin)); g_print("Valor del Spin: entero-> %d - float-> %f\n", num, nfloat); -Propiedades: Mirar en las funciones de este widget :). 4.6 GtkCombo -¿Qué es?: Es una caja que te da a elegir entre varias opciones. -Funciones: Antes de nada decir que el GtkCombo se compone de un GtkEntry que contendrá la opción que se haya seleccionado, asi que será lo que tendremos que leer a la hora de querer saber la opción elegida por el usuario. Una vez más se puede hacer todo mucho mas sencillo con el glade sin tener que llamar a funciones, en el GLADE seleccionamos el GtkCombo entero (no solo el GtkEntry que tiene), y en la ventana de propiedades vemos Items ahi es donde tendremos que meter los elementos entre los que podrá elegir el usuario. Tam- bién podemos definir si será Case Sensitive en caso de que el usuario pueda editar la GtkEntry. 4.7 GtkText -¿Qué es?: Es como un GtkEntry gigante :), un espacio donde se podrá o no (según desee el programador) escribir/ver texto. -Funciones: Se puede poner editable o no, con el GLADE sin tener que llamar a ninguna fun ción. + gtk_text_set_point: · Prototipo: void gtk_text_set_point(GtkText *text, guint index); Pone el cursor en la posicion dada por index. + gtk_text_get_point: · Prototipo: guint gtk_text_get_point(GtkText *text); Devuelve la posición del cursor en el GtkText. + gtk_text_get_length: · Prototipo: guint gtk_text_get_length(GtkText *text); Devuelve la longitud del texto completo que haya. + gtk_text_freeze: · Prototipo: void gtk_text_freeze(GtkText *text); No deja que se escriba mas en el widget hasta que se llame a gtk_text_thaw, es útil si se hacen cambios muy rápido en el widget para que el usuario vea el resultado. + gtk_text_thaw: · Prototipo: void gtk_text_thaw(GtkText *text); Vuelve a dejar escribir en el widget despues de un freeze. + gtk_text_insert: · Prototipo: void gtk_text_insert(GtkText *text, GdkFont *font, GdkColor *fore, GdkColor *back, const char *chars, gint length); Inserta un texto chars en el widget text con la fuente font etc..., fore es el color del texto y back el color del fondo. + gtk_text_backward_delete: · Prototipo: gint gtk_text_backward_delete(GtkText *text, guint nchars); Borra un número de caractéres, a partir de la posición del cursor para atrás dado por nchars y devuelve TRUE si se ha podido realizar la operación o FALSE en caso contrario. + gtk_text_forward_delete: · Prototipo: gint gtk_text_forward_delete(GtkText *text, guint nchars); Hace y devuelve lo mismo que gtk_text_backward_delete pero borra los carac- téres a partir de la posición del cursor para adelante. Ejemplo: GtkWidget *texto; GdkColor *foreground, *background; guint tam; foreground->red=0; foreground->blue=65535; foregroung->green=0; background->red=0; background->green=0; background->blue=0; gtk_text_insert(GTK_TEXT(texto),GDK_FONT_FONT,foreground, background, "hola",4); if(gtk_text_backward_delete(GTK_TEXT(texto),2)) g_print("Borradas 2 letras\n"); tam=gtk_text_get_length(GTK_TEXT(texto)); g_print("Longitud del texto actual: %d\n", tam); 5. Ejemplos Widgets De GNOME 5.1 GnomeAppBar -¿Qué es?: Es una barra de estado + una barra de progreso. -Funciones: Desde el GLADE se puede quitar la barra de estado o la barra de progreso, o las 2, según se prefiera. + gnome_appbar_set_status: · Prototipo: void gnome_appbar_set_status(GnomeAppBar *appbar, const gchar *status); Pone en la barra de estado el mensaje status. + gnome_appbar_push: · Prototipo: void gnome_appbar_push(GnomeAppBar *appbar, const gchar *status); Pone en la pila de mensajes de la barra de estado el mensaje status y ade- más sale en la barra de estado. + gnome_appbar_pop: · Prototipo: void gnome_appbar_push(GnomeAppBar *appbar); Saca de la pila el último mensaje metido y pone el siguiente en la barra de estado. + gnome_appbar_clear_stack: · Prototipo: void gnome_appbar_clear_stack(GnomeAppBar *appbar); Borra la pila de mensajes de la barra de estado y pone el default message, si lo hubiese, en la barra de estado. El default message se pone con la función gnome_appbar_set_default que recibe un widget appbar y un gchar. + gnome_appbar_set_progress: · Prototipo: void gnome_appbar_set_progress(GnomeAppBar *appbar, gfloat percentage); Rellena la barra de progreso con el porcentaje dado en percentage en float. Ejemplo: Hay ejemplos sobre este widget en el programa que hemos hecho al principio del documento. 5.2 GnomeDateEdit -¿Qué es?: Es un widget en el cual el usuario puede cambiar la hora y la fecha. -Funciones: La mayoría de las funciones de este widget son para ajustar propiedades y se puede hacer con el GLADE mucho más fácilmente. + gnome_date_edit_get_date: · Prototipo: time_t gnome_date_edit_get_date(GnomeDateEdit *gde); Devuelve el la fecha y la hora que hay en ese momento en el widget. NOTA: time_t es un long int. -Signals: + date_changed: Se produce cuando el usuario cambia la fecha. · Prototipo: void funcion_predef(GnomeDateEdit *dateedit, gpointer user_data); + time_changed: Se produce cuando el usuario cambia la hora. · Prototipo: void funcion_predef(GnomeDateEdit *dateedit, gpointer user_data); 6. Conclusión Después de este artículo (si se puede llamar asi :)) espero que seais capaces de seguir aprendiendo a manejar los muy variados widgets que hay, y que encon trareis en las URL del punto siguiente (la bibliografía). Espero que os haya servido de ayuda. Un Saludo. 7. Bibliografía http://developer.gnome.org/doc/API/libglade/libglade.html - API LIBGLADE http://developer.gnome.org/doc/API/gtk/index.html - API GTK+ http://developer.gnome.org/doc/API/libgnomeui/book1.html - API GNOME UI *EOF*