ProgramacionGTKenC/CapituloIII

De Wiki GNOME Chile
(Diferencias entre revisiones)
Saltar a: navegación, buscar
(Funciones de recepcion de señales)
 
(No se muestran 3 ediciones intermedias realizadas por 3 usuarios)
Línea 1: Línea 1:
 +
__FORCETOC__
 +
 
= Señales =
 
= Señales =
  
Línea 9: Línea 11:
 
Revisando el codigo de gtkbutton.h, vemos que la clase posee una señal, clicked
 
Revisando el codigo de gtkbutton.h, vemos que la clase posee una señal, clicked
  
struct _GtkButtonClass
+
<pre>struct _GtkButtonClass
 
{
 
{
 
...
 
...
 
void (* clicked) (GtkButton * button);
 
void (* clicked) (GtkButton * button);
 
...
 
...
}
+
}</pre>
  
 
En la documentacion de GTK+, los argumentos de la funcion de callback son
 
En la documentacion de GTK+, los argumentos de la funcion de callback son
  
"clicked" void user_function (GtkButton * button, gpointer user_data);
+
<pre>"clicked" void user_function (GtkButton * button, gpointer user_data);</pre>
  
 
En el caso generico de cualquier widget, una señal se enlaza a una funcion arbitraria de la siguiente manera
 
En el caso generico de cualquier widget, una señal se enlaza a una funcion arbitraria de la siguiente manera
  
g_signal_connect((GObject *) widget,  
+
<pre>g_signal_connect((GObject *) widget,  
 
const gchar signal,  
 
const gchar signal,  
 
(GCallback *) function,  
 
(GCallback *) function,  
gpointer data);
+
gpointer data);</pre>
  
  
 
donde
 
donde
  
    * widget : es el widget que origina la señal
+
* widget : es el widget que origina la señal
    * const gchar signal : es el nombre de la señal a recibir
+
* const gchar signal : es el nombre de la señal a recibir
    * function : la funcion que se va a conectar a la señal
+
* function : la funcion que se va a conectar a la señal
    * data : puntero arbitrario de envio de datos de la funcion.
+
* data : puntero arbitrario de envio de datos de la funcion.
 
+
  
 
Mientras que la declaracion de la funcion depende de la señal. En el caso de la señal "clicked" en el widget GtkButton es:
 
Mientras que la declaracion de la funcion depende de la señal. En el caso de la señal "clicked" en el widget GtkButton es:
  
"clicked" void user_function (GtkButton * button, gpointer user_data);
+
<pre>"clicked" void user_function (GtkButton * button, gpointer user_data);</pre>
  
  
 
Veamos un ejemplo
 
Veamos un ejemplo
  
#include <gtk/gtk.h>
+
<pre>#include <gtk/gtk.h>
  
 
void funcion (GtkButton * button, gpointer data)
 
void funcion (GtkButton * button, gpointer data)
Línea 67: Línea 68:
 
gtk_container_add ((GtkContainer *) boton, etiqueta);
 
gtk_container_add ((GtkContainer *) boton, etiqueta);
  
g_signal_connect ((GObject *) boton, "clicked", (GCallback * ) funcion, NULL);
+
g_signal_connect ((GObject *) boton, "clicked", (GCallback) funcion, NULL);
  
 
gtk_widget_show(ventana);
 
gtk_widget_show(ventana);
Línea 75: Línea 76:
 
gtk_main();
 
gtk_main();
  
}
+
}</pre>
 
+
(Descargar codigo)
+
 
+
La salida seria algo similar a esta:
+
 
+
signal
+
  
Funciones de recepcion de señales
+
== Funciones de recepcion de señales ==
 
Se fijaron que cuando compilaron los ejemplos anteriores y cerraron la ventana, la aplicacion "siguio corriendo"?. Eso es debido a que al momento de cerrar la ventana principal de una aplicacion, se emite una señal "delete-event" que no es recibida por ninguna funcion.
 
Se fijaron que cuando compilaron los ejemplos anteriores y cerraron la ventana, la aplicacion "siguio corriendo"?. Eso es debido a que al momento de cerrar la ventana principal de una aplicacion, se emite una señal "delete-event" que no es recibida por ninguna funcion.
  
Línea 89: Línea 84:
 
El primero, es similar al anterior. Esta vez, se imprime "Apretamos el boton..." y la aplicacion se cerrara.
 
El primero, es similar al anterior. Esta vez, se imprime "Apretamos el boton..." y la aplicacion se cerrara.
  
#include <gtk/gtk.h>
+
<pre>#include <gtk/gtk.h>
  
 
void funcion (GtkButton * button, gpointer data)
 
void funcion (GtkButton * button, gpointer data)
Línea 114: Línea 109:
 
gtk_container_add ((GtkContainer *) boton, etiqueta);
 
gtk_container_add ((GtkContainer *) boton, etiqueta);
  
g_signal_connect ((GObject *) boton, "clicked", (GCallback * ) funcion, NULL);
+
g_signal_connect ((GObject *) boton, "clicked", (GCallback) funcion, NULL);
  
 
gtk_widget_show(ventana);
 
gtk_widget_show(ventana);
Línea 122: Línea 117:
 
gtk_main();
 
gtk_main();
  
}
+
}</pre>
 
+
  
(Descargar codigo)
 
  
 
La funcion gtk_main_quit() efectivamente finaliza la aplicacion, entre otras cosas (limpiar buffers, sacar la asignacion de memoria de los widgets, etc).
 
La funcion gtk_main_quit() efectivamente finaliza la aplicacion, entre otras cosas (limpiar buffers, sacar la asignacion de memoria de los widgets, etc).
Línea 131: Línea 124:
 
Ahora, el mismo programa, pero en vez de imprimir un mensaje, automaticamente se cerrara la aplicacion.
 
Ahora, el mismo programa, pero en vez de imprimir un mensaje, automaticamente se cerrara la aplicacion.
  
#include <gtk/gtk.h>
+
<pre>#include <gtk/gtk.h>
  
 
int main (int argc, char * argv[])
 
int main (int argc, char * argv[])
Línea 152: Línea 145:
 
g_signal_connect ((GObject *) boton,  
 
g_signal_connect ((GObject *) boton,  
 
  "clicked",  
 
  "clicked",  
  (GCallback * )  
+
  (GCallback)  
 
  gtk_main_quit, NULL);
 
  gtk_main_quit, NULL);
  
Línea 161: Línea 154:
 
gtk_main();
 
gtk_main();
  
}
+
}</pre>
 
+
 
+
(Descargar codigo)
+
  
 
La diferencia entre estas dos es al conectar la señal "clicked".
 
La diferencia entre estas dos es al conectar la señal "clicked".
Línea 174: Línea 164:
 
Entonces, podemos resolver el problema conectando "delete-event" con gtk_main_quit():
 
Entonces, podemos resolver el problema conectando "delete-event" con gtk_main_quit():
  
 +
<pre>
 
g_signal_connect((GObject *) ventana,
 
g_signal_connect((GObject *) ventana,
 
"delete-event",
 
"delete-event",
 
(GCallback ) gtk_main_quit,
 
(GCallback ) gtk_main_quit,
NULL);
+
NULL);</pre>
  
  

Última revisión de 18:12 8 jun 2008


Contenido

[editar] Señales

Como vimos anteriormente, es posible definir funciones arbitrarias al momento de recibir algunos eventos. Como la programacion grafica requiere de interaccion con el usuario, GTK+ recibe y emite señales al momento de comunicarse con la capa grafica (X11). Por ejemplo, al hacer click a un boton, mover una ventana, entre otros.

En el caso del boton, al momento de hacer click en el se genera la señal "clicked", que no esta definida a ninguna funcion.

Revisando el codigo de gtkbutton.h, vemos que la clase posee una señal, clicked

struct _GtkButtonClass
{
	...
	void (* clicked) (GtkButton * button);
	...
}

En la documentacion de GTK+, los argumentos de la funcion de callback son

"clicked" void user_function (GtkButton * button, gpointer user_data);

En el caso generico de cualquier widget, una señal se enlaza a una funcion arbitraria de la siguiente manera

g_signal_connect((GObject *) widget, 
		const gchar signal, 
		(GCallback *) function, 
		gpointer data);


donde

  • widget : es el widget que origina la señal
  • const gchar signal : es el nombre de la señal a recibir
  • function : la funcion que se va a conectar a la señal
  • data : puntero arbitrario de envio de datos de la funcion.

Mientras que la declaracion de la funcion depende de la señal. En el caso de la señal "clicked" en el widget GtkButton es:

"clicked" void user_function (GtkButton * button, gpointer user_data);


Veamos un ejemplo

#include <gtk/gtk.h>

void funcion (GtkButton * button, gpointer data)
{
	g_print("Apretamos el boton y aparece este texto\n");
}

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);

	g_signal_connect ((GObject *) boton, "clicked", (GCallback) funcion, NULL);

	gtk_widget_show(ventana);
	gtk_widget_show(boton);
	gtk_widget_show(etiqueta);

	gtk_main();

}

[editar] Funciones de recepcion de señales

Se fijaron que cuando compilaron los ejemplos anteriores y cerraron la ventana, la aplicacion "siguio corriendo"?. Eso es debido a que al momento de cerrar la ventana principal de una aplicacion, se emite una señal "delete-event" que no es recibida por ninguna funcion.

Veamos los siguientes ejemplos. El primero, es similar al anterior. Esta vez, se imprime "Apretamos el boton..." y la aplicacion se cerrara.

#include <gtk/gtk.h>

void funcion (GtkButton * button, gpointer data)
{
	g_print("Apretamos el boton y aparece este texto\n");
	gtk_main_quit();
}

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);

	g_signal_connect ((GObject *) boton, "clicked", (GCallback) funcion, NULL);

	gtk_widget_show(ventana);
	gtk_widget_show(boton);
	gtk_widget_show(etiqueta);

	gtk_main();

}


La funcion gtk_main_quit() efectivamente finaliza la aplicacion, entre otras cosas (limpiar buffers, sacar la asignacion de memoria de los widgets, etc).

Ahora, el mismo programa, pero en vez de imprimir un mensaje, automaticamente se cerrara la aplicacion.

#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);

	g_signal_connect ((GObject *) boton, 
			  "clicked", 
			  (GCallback) 
			  gtk_main_quit, NULL);

	gtk_widget_show(ventana);
	gtk_widget_show(boton);
	gtk_widget_show(etiqueta);

	gtk_main();

}

La diferencia entre estas dos es al conectar la señal "clicked".

Pero aun no resolvemos el problema que al cerrar la ventana (hacer click en la X de la derecha sonrisa ) efectivamente se cierre.

Como dije anteriormente, la señal "delete-event" se emite cuando la ventana padre se cierra. El manejador por defecto debiera ser una funcion que destruya a esta ventana.

Entonces, podemos resolver el problema conectando "delete-event" con gtk_main_quit():

g_signal_connect((GObject *) ventana,
		"delete-event",
		(GCallback ) gtk_main_quit,
		NULL);


Este es un ejemplo bastante mas complejo que los anteriores, asi que paciencia para entenderlo:

#include <gtk/gtk.h>

// esto es de buena costumbre

void funcion1 (GtkButton * boton, gpointer data);
void funcion2 (GtkButton * boton, gpointer data);
void cerrar_ventana (GtkWidget * widget,gpointer data);


// ahora las funciones
void cerrar_ventana (GtkWidget * widget,gpointer data)
{
	gtk_widget_destroy((GtkWidget *) data);
}


void funcion1 (GtkButton * boton, gpointer data)
{
	GtkWidget * ventana1;
	GtkWidget * boton1;

	// esta funcion al apretar el boton invoca el cerrado de la ventana

	ventana1 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	boton1 = gtk_button_new_with_label("Cerrar ventana");

	gtk_window_set_title((GtkWindow *) ventana1,
			     "Nueva ventana hija");
	
	gtk_container_add((GtkContainer *) ventana1,
			  boton1);

	g_signal_connect((GObject *) boton1,
			 "clicked",
			 (GCallback) cerrar_ventana,
			 (gpointer) ventana1);
	
	gtk_widget_show_all(ventana1);
}

void funcion2 (GtkButton * boton, gpointer data)
{
	gtk_main_quit();
}

int main (int argc, char * argv[])
{
	GtkWidget * ventana;
	GtkWidget * boton1;
	GtkWidget * boton2;
	GtkWidget * vbox;
	
	
	// inicializar GTK+
	gtk_init(&argc, &argv);

	
	// crear los controles
	ventana = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	boton1 = gtk_button_new_with_label("Nueva ventana");
	boton2 = gtk_button_new_with_label("Cerrar aplicacion");
	vbox = gtk_vbox_new(TRUE,5);

	
	// modificar las propiedades
	gtk_window_set_title((GtkWindow *) ventana, 
			 "Ejemplo mas completo");       

	// empaquetamiento
	gtk_box_pack_start((GtkBox *) vbox, 
			   boton1,
			   TRUE,
			   TRUE,
			   2);

	gtk_box_pack_start((GtkBox *) vbox,
			   boton2, 
			   TRUE,
			   TRUE,
			   2);
		      
	gtk_container_add((GtkContainer *) ventana, vbox);


	// conectar las señales
	g_signal_connect((GObject *) boton1,
			 "clicked",
			 (GCallback ) funcion1,
			 NULL);


	g_signal_connect((GObject *) boton2,
			 "clicked",
			 (GCallback) funcion2,
			 NULL);

	
	// atencion aqui!

	g_signal_connect((GObject *) ventana,
			 "delete-event",
			 (GCallback) gtk_main_quit,
			 NULL);
	
	// desplegar los controles
	gtk_widget_show_all(ventana);

	// GTK+ main loop
	gtk_main();
	return 0;
}
Herramientas personales
Espacios de nombres

Variantes
Acciones
Navegación
Herramientas