ProgramacionGTKenC/CapituloI

De Wiki GNOME Chile
Saltar a: navegación, buscar

Contenido

Programando en GTK+

Es necesario tener instalado una serie de paquetes de desarrollo. Por ejemplo:

  • GCC
  • Pkg-config, necesario para mostrar informacion de las bibliotecas de desarrollo
  • Paquetes de desarrollo de GLib
  • Paquetes de desarrollo de GTK+

En Debian y por consiguiente en Ubuntu, los paquetes son:

  • gcc
  • libc6-dev
  • pkg-config
  • libglib2.0-dev
  • libgtk2.0-dev

Compilando un programa usando GTK+

Al igual que GLib, usamos pkg-config como apoyo.

user@maquina:$ pkg-config --cflags gtk+-2.0
-I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 \
-I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 \
-I/usr/lib/glib-2.0/include

Podemos usar cualquiera de las siguientes soluciones

  • incluir la llamada completa de pkg-config usando backticks
user@maquina:$ gcc -o programa programa.c `pkg-config --cflags gtk+-2.0 --libs`
  • Usar una variable de ambiente para el resultado de pkg-config:
user@maquina:$ CFLAGS=`pkg-config --libs --cflags gtk+-2.0 `
user@maquina:$ export CFLAGS
user@maquina:$ gcc $CFLAGS -o programa programa.c

En el caso de Bourne Again Shell (Bash)

Un primer programa en GTK+

#include <gtk/gtk.h>

int main (int argc, char * argv[])
{
	GtkWidget * ventana;

	gtk_init (&argc, &argv);
	ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title((GtkWindow *) ventana, "Hola mundo");
	gtk_widget_show(ventana);

	gtk_main();
	return 0;
}

Para compilar

user@maquina: $ gcc -o programa1 programa1.c `pkg-config --cflags --libs gtk+-2.0`

Al ejecutarse, aparecera una ventana con el titulo de "Hola mundo".

Ahora veamos el codigo del programa

GtkWidget * ventana;

Se define un widget generico

gtk_init(&argc, &argv);

Con esta funcion, se inicializa el subsistema de GTK+.

ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL);

La funcion gtk_window_new() crea un Widget ventana, con un parametro, el tipo de ventana. En este caso, es una ventana de tipo "top level" o una ventana comun y corriente.

gtk_widget_show(ventana);

Esta funcion permite que el widget efectivamente se muestre.

gtk_main();

Esta funcion inicializa el loop principal de GTK+, donde se dibujarian todos los controles que hayan explicitamente pedido dibujarse (como la ventana), entre otras cosas.

Widgets Básicos

Ventana

La ventana es el mas necesario de los Widgets en GTK+. La funcion gtk_window_new() devuelve un widget de tipo ventana. El argumento de la funcion es

  • GTK_WINDOW_TOPLEVEL : generalmente usado, es para crear una ventana nueva que informe al Window Manager
  • GTK_WINDOW_POPUP : en caso de querer usar un pop-up, no manejado por el Window Manager

Un ejemplo :

GtkWidget * ventana;
....
ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);

Etiquetas

Una etiqueta es un control de texto. Es uno de los controles mas simples. No emiten señales si no estan asociados a una ventana.

La funcion gtk_label_new() crea un widget de tipo etiqueta.

GtkWidget * gtk_label_new( const char *string);

Un ejemplo,

GtkWidget * etiqueta;
...
etiqueta = gtk_label_new("Esta es una etiqueta");

Botones

Este widget es para comunicacion de usuario. Generalmente usado para confirmaciones o bien para seleccionar entre un reducido grupo de opciones (no mas que dos). En algunos casos puede tener una imagen asociada (que se va a ver en los proximos capitulos de este curso). La funcion gtk_button_new() crea un widget de tipo boton.

GtkWidget * gtk_button_new( void );

No recibe argumentos.

La funcion gtk_button_new_with_label() crea un widget de tipo boton, con una etiqueta contenida en el boton (a continuacion, contenedores)

GtkWidget * gtk_button_new_with_label ( const char * string );

Un ejemplo de estas dos funciones:

GtkWidget * boton;
GtkWidget * boton_con_etiqueta;
...
boton = gtk_button_new();
boton_con_etiqueta = gtk_button_new_with_label("Estoy dentro de un boton");

Contenedores

Como se dijo anteriormente, un widget puede contener a otro. El mas comun es la ventana, que puede encapsular a otros widgets.

Para contener un widget en otro se utiliza la funcion gtk_container_add

gtk_container((GtkContainer *) widget_contenedor, widget_a_contener);

Por ejemplo, un boton contiene internamente una etiqueta (label). En este ejemplo, se va a crear un boton que se va a insertar en una ventana, y una etiqueta en el boton.

#include <gtk/gtk.h>

int main (int argc, char * argv[])
{
	GtkWidget * ventana;
	GtkWidget * boton;
	GtkWidget * etiqueta;
	
	gtk_init(&argc, &argv);

	ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	boton = gtk_button_new();
	etiqueta = gtk_label_new("Etiqueta 1");

	gtk_window_set_title((GtkWindow *) ventana, "Ventana con boton");
	gtk_container_add ((GtkContainer *) ventana, boton);
	gtk_container_add ((GtkContainer *) boton, etiqueta);
	
	gtk_widget_show(ventana);
	gtk_widget_show(boton);
	gtk_widget_show(etiqueta);

	gtk_main();

}

Este ejemplo explica la diferencia entre crear un boton y una etiqueta por separado:

GtkWidget * boton;
GtkWidget * etiqueta;
...
boton = gtk_button_new();
etiqueta = gtk_label_new("Look ma, no hands");
...
gtk_container_add((GtkContainer *) boton, etiqueta);

y usar la funcion gtk_button_new_with_label:

GtkWidget * boton_con_etiqueta;
...
boton_con_etiqueta = gtk_button_new_with_label("Look ma, no hands");

Metodos de un Widget

GtkWidget hereda las propiedades y metodos de la clase GObject. Ademas, posee sus propios metodos y propiedades. Cualquier control que sea hijo de la clase GtkWidget hereda sus propiedades y metodos. Y asi sucesivamente.

Por ejemplo, el arbol de herencia del widget ventana es el siguiente:

GObject
+--GtkObject
	+--GtkWidget
		+--GtkContainer
			+--GtkBin
				+--GtkWindow

Esto permite que, por ejemplo, se puedan ocupar funciones que permiten modificar o consultar propiedades de widgets padres.

Lo que es necesario tener en cuenta es hacer el casting correcto al momento de usar algunas de las funciones.

En el caso de todos los widgets, el metodo show es comun. Si fuera C++, se podria ver de la siguiente manera:

objeto->show();

En GTK+:

gtk_widget_show((GtkWidget *) widget);

Propiedades de un Widget Si se han dado cuenta, C no es un lenguaje orientado a objetos. Glib y GTK+ son maneras de compatibilizar esta deficiencia en el lenguaje C (la que no tiene C++). Como vimos anteriormente, un metodo de un objeto en C++ puede ser llamado

objeto->metodo(valor1, valor2...);

mientras que en GTK+ (en C) es asi

gtk_tipocontrol_metodo((casting *) objeto, valor1, valor2,...);

En el caso de las propiedades (en C++),

objeto->propiedad=valor;

y en GTK+ (C),

gtk_tipocontrol_cambiopropiedad ((casting *) objeto, valor1, valor2,...);

o bien

g_object_set_property ((GObject *) objeto, "propiedad1", valor1);

Es confuso al principio de entender. Pero es mejor visto con un par de ejemplos. El primero podria ser:

GtkWidget * ventana;

ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_title((GtkWindow *) ventana, "Titulo de la ventana");

En este caso, la funcion gtk_window_set_title() permite cambiar la propiedad "title" del control GtkWindow.

Ahora, el mismo ejemplo, usando GObject.

GtkWidget * ventana;

ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);

g_object_set_property((GObject *) ventana,
                                  "title", "Titulo de la ventana");

La funcion g_object_set_property permite cambiar cualquier propiedad del widget, identificando el nombre de la propiedad a cambiar. En el ejemplo,

gtk_window_set_title((GtkWindow *) ventana, "ventana");

es equivalente a

g_object_set_property((GObject *) ventana, 
                                  "title", "ventana");

Tambien es posible cambiar una serie de propiedades de un objeto usando g_object_set():

g_object_set((GObject *) objeto, 
		"propiedad1", valor1,
		"propiedad2", valor2, 
		...,
		NULL);

Recordar ademas que algunas propiedades de los objetos son de solo lectura. Usando el mismo control (GtkWindow), veamos la funcion gtk_window_get_title(): const gchar * gtk_window_get_title(GtkWindow * window);

Entonces podremos tener lo siguiente:

GtkWidget * ventana;
ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title((GtkWindow *) ventana, "Look ma, no teeth");
...
g_print("Titulo de la ventana : %s\n", 
	gtk_window_get_title((GtkWindow *) ventana);

La ultima linea (g_print....) es posible de reemplazar usando g_object_get_property(que requiere uso de GValues) o bien g_object_get():

g_object_get((GObject *) objeto, 
			"propiedad1", &valor1,
			...,
			NULL);
Herramientas personales
Espacios de nombres

Variantes
Acciones
Navegación
Herramientas