ProgramacionGTKenC/CapituloII

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

Contenido

Empaquetamiento Basico

Algunos widgets son capaces de contener a otro widget. Esto se conoce como empaquetamiento. Por lo general, los widgets solo pueden contener a un hijo (pero veremos mas adelante que pueden contener mas). En el caso del widget boton, se puede empaquetar un widget de tipo etiqueta. En el caso del widget ventana, se puede empaquetar cualquier otro widget.

Por lo general, el empaquetamiento se realiza haciendo un cast desde GtkWidget * a GtkContainer * (en el caso que el widget lo permita).

Por ejemplo

GtkWidget * boton;
GtkWidget * etiqueta;
etiqueta = gtk_label_new("Mi nombre es Juan");
boton = gtk_button_new();
gtk_container_add ((GtkContainer *) boton, etiqueta);

Widgets de Empaquetamiento

Algunos de estos widgets "invisibles" son usados para empaquetamiento. Es decir, pueden contener dos o mas widgets hijos dentro de el.

El widget mas conocido para empaquetamiento es el GtkBox (o caja de empaquetamiento). Lo hay en dos versiones, horizontal (GtkHBox) y vertical (GtkVBox).

GtkWidget * hbox;
GtkWidget * vbox;

Estos widgets, a su vez, son hijos del widget GtkBox, el cual permite el empaquetamiento basico. Es decir, para empaquetar los widgets de forma horizontal y vertical se usan las mismas primitivas para ambos, siempre y cuando se haga un cast a GtkBox *.

hbox = gtk_hbox_new(homogeneidad, distancia);
La funcion gtk_hbox_new() crea un widget de tipo HBox. Los parametros que recibe esta funcion son
  • homogeneidad : (gboolean) si es verdadero, todos los widgets hijos ocuparan el mismo espacio
  • distancia : (gint) numero de pixeles de espacio entre widgets.

Para empaquetar los controles a una caja, se usan las funciones gtk_box_pack_start(que inserta los controles hacia la derecha (horizontal) o hacia abajo (vertical)) y gtk_box_pack_end(que inserta los controles hacia la izquierda (horizontal) o hacia arriba (vertical)).
gtk_box_pack_start((GtkBox *) hbox, widget, expandir, llenar, margen);
Los valores de esta funcion son

  • hbox : (GtkBox *) el widget empaquetador de tipo GtkBox
  • widget : (GtkWidget *) el widget a insertar
  • expandir : (gboolean) si es verdadero, se le da espacio extra al siguiente hijo. Este espacio se reparte equitativamente entre los widgets ya insertados
  • llenar : (gboolean) si es verdadero, el widget hijo se expandira.
  • margen : (gint) espacios extras en pixeles entre el widget insertado y sus vecinos.

Veamos un ejemplo

#include <gtk/gtk.h>
int main (int argc, char * argv[])
{
	GtkWidget * ventana;
	GtkWidget * hbox;
	GtkWidget * boton1;
	GtkWidget * boton2;
	GtkWidget * boton3;

	gtk_init(&argc, &argv);

	ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	hbox = gtk_hbox_new(TRUE, 5);
	boton1 = gtk_button_new_with_label("Soy el boton 1");
	boton2 = gtk_button_new_with_label("Soy el boton 2");
	boton3 = gtk_button_new_with_label("Boton 3");

	// empaquetar los botones en el hbox

	gtk_box_pack_start((GtkBox *) hbox, boton1, TRUE, TRUE, 0);
	gtk_box_pack_start((GtkBox *) hbox, boton2, TRUE, TRUE, 0);
	gtk_box_pack_start((GtkBox *) hbox, boton3, TRUE, TRUE, 0);

	// insertamos la caja en la ventana

	gtk_container_add((GtkContainer *) ventana, hbox);

	gtk_widget_show_all(ventana);
	gtk_main();
	return 0;
}

El resultado seria http://cursos.gnome.cl/file.php/16/Screenshot-1.png

A ejercicio del lector queda
  • cambiar las funciones gtk_box_pack_start a gtk_box_pack_end a voluntad
  • cambiar los valores de las funciones de empaquetado para ver su resultado
  • cambiar la funcion gtk_hbox_new() por gtk_vbox_new()

Mejor aun, es posible empaquetar cajas horizontales en cajas verticales, y viceversa (piensen en las alternativas posibles :) ).

#include <gtk/gtk.h>
int main (int argc, char * argv[])
{
	GtkWidget * ventana;
	GtkWidget * hbox;
	GtkWidget * vbox;
	GtkWidget * boton1;
	GtkWidget * boton2;
	GtkWidget * boton3;
	GtkWidget * boton4;
	GtkWidget * boton5;
	GtkWidget * boton6;

	gtk_init(&argc, &argv);

	ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	hbox = gtk_hbox_new(TRUE, 5);
	vbox = gtk_vbox_new(TRUE, 5);

	boton1 = gtk_button_new_with_label("Hola");
	boton2 = gtk_button_new_with_label("Mundo");
	boton3 = gtk_button_new_with_label("Foo");
	boton4 = gtk_button_new_with_label("Bar");
	boton5 = gtk_button_new_with_label("Baz");
	boton6 = gtk_button_new_with_label("Fu");


	gtk_box_pack_start((GtkBox *) hbox, boton1, TRUE, TRUE, 1);
	gtk_box_pack_start((GtkBox *) hbox, boton2, TRUE, TRUE, 1);
	gtk_box_pack_start((GtkBox *) hbox, boton3, TRUE, TRUE, 1);

	gtk_box_pack_start((GtkBox *) vbox, boton4, TRUE, TRUE, 1);
	gtk_box_pack_start((GtkBox *) vbox, boton5, TRUE, TRUE, 1);

        // ahora, empaquetar el hbox en vbox

	gtk_box_pack_start((GtkBox *) vbox, hbox, TRUE, TRUE,1);

        // y empaquetar otro boton para ver el efecto final

	gtk_box_pack_start((GtkBox *) vbox, boton6, TRUE, TRUE,1);

	gtk_container_add((GtkContainer *) ventana, vbox);

	gtk_widget_show_all(ventana);

	gtk_main();
	return 0;

}

El resultado seria algo como esto:

http://cursos.gnome.cl/file.php/16/4-vhbox.jpg

Mas Widgets

Toggles (Boton de dos estados)

En la entrega anterior vimos los GtkButtons, botones (de 1 estado) que emiten la señal "clicked" una vez que son presionados. Pero ademas existen los botones de tipo "toggle" o de dos estados : presionado y no-presionado.

#include <gtk/gtk.h>

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

	gtk_init(&argc, &argv);

	ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	toggle = gtk_toggle_button_new();
	etiqueta = gtk_label_new("Soy un boton de toggle");
	caja = gtk_vbox_new(TRUE, 5);
	boton = gtk_button_new_with_label("Soy un boton");

	gtk_container_add((GtkContainer *) toggle, etiqueta);

	gtk_box_pack_start((GtkBox *) caja, 
			   toggle,
			   TRUE,
			   TRUE,
			   3);

	gtk_box_pack_start((GtkBox *) caja,
			   boton,
			   TRUE,
			   TRUE,
			   3);

	gtk_container_add((GtkContainer *) ventana, caja);

	gtk_widget_show_all(ventana);
	gtk_main();
	return 0;
}

Veamos un ejemplo con un boton toggle y un boton simple.
La salida seria algo como esto:

http://cursos.gnome.cl/file.php/16/5-toggle.jpg"

Cual es la diferencia? El boton superior se mantiene en estado de presionado.

http://cursos.gnome.cl/file.php/16/5-toggle-1.jpg

Nota al margen: http://cursos.gnome.cl/pix/s/thoughtful.gif"

Quizas se preguntaran por que un ejemplo esta con

	gtk_box_pack_start((GtkBox *) vbox, boton6, TRUE, TRUE,1);

y otro esta con

	gtk_box_pack_start((GtkBox *) caja,
			   boton,
			   TRUE,
			   TRUE,
			   3);
La razon es la siguiente : al momento de escribir codigo, este debe ser lo mas legible posible. Por lo general, ante funciones que poseen varias opciones, se van a encontrar con varios programas que separan los argumentos de la segunda manera.

Herramientas personales
Espacios de nombres

Variantes
Acciones
Navegación
Herramientas