Interactuando: Manejo de Señales.
Nuestra ventana es más o menos bonita [sobre gustos...], pero
no hace absolutamente nada. En este capítulo vamos a aprender
como interactuar con el usuario.
Básicamente, existen dos grandes sistemas de control de la
acción de un usuario:
- Una puede asemejarse a cuando queremos hablar con
determinada persona y le llamamos por teléfono. Por ejemplo,
en nuestro primer programa utilizamos std::cin>>,
para esperar que el usuario introdujera algún dato por
teclado, el
programa "llama" al teclado y solicita algún dato concreto del
usuario. Es la programación secuencial donde el programador
decide el flujo del programa.
- Y otra parecida a cuando nos llaman por teléfono,
y en función de quién sea, procedemos. Es lo habitual
en la programación gráfica. Si accedes al monitor del
sistema
[Sistema->Administración->Monitor_del_Sistema],
observarás en la pestaña de procesos que hay muchos
abiertos, la mayoría durmiendo. Cuando un usuario realiza una
"llamada" sobre un programa, éste la procesa y vuelve a
dormir, con el objeto de que varios programas puedan actuar
simultáneamente. Es la programación por eventos donde
el usuario determina el flujo del programa.
Cuando el usuario hace "click" con el ratón sobre el
botón de nuestra aplicación, este componente emite
una señal. Nosotros debemos conectar esa
señal con el código que queramos que se
ejecute, esto se hace tal que así:
boton.signal_clicked().connect(sigc::ptr_fun(&funcion));
Modificamos el archivo de main.cc para que quede tal que así:
#include <iostream>
#include <gtkmm.h>
int veces=0;
void pulsar_boton();
int main(int argc, char *argv[])
{
Gtk::Main programa(argc, argv);
Gtk::Window miventanica;
Gtk::VBox principal;
Gtk::HSeparator linea;
Gtk::Label etiqueta("Pulsa abajo");
Gtk::Button
contador("¡AQUÍ!");
contador.signal_clicked().connect(sigc::ptr_fun(&pulsar_boton));
miventanica.add(principal);
principal.pack_start(etiqueta);
principal.pack_start(linea);
principal.pack_start(contador);
principal.show();
etiqueta.show();
contador.show();
linea.show();
miventanica.set_title("maestrodenada.com");
miventanica.resize(260,110);
Gtk::Main::run(miventanica);
return 0;
}
void pulsar_boton()
{
std::cout<< "botón pulsado "
<< ++veces<< "
veces"<<std::endl;
}
Explicación:
Al código de prácticas anteriores, le hemos
añadido la conexión entre la señal de
clickar el botón con la función pulsar_botón
definida al final. Función que lo único que hace es
incrementar el valor de la variable entera veces y escribir por la
consola un mensaje sobre el número de veces pulsado el
botón...
contador.signal_clicked().connect(sigc::ptr_fun(&pulsar_boton));Realiza
la conexión entre la señal de clickar el botón y
la función pulsar_boton(). Creo que es mejor aprenderlo de
memoria, pero tratemos de explicarlo...
...En Gtk se ha creado una clase, un tipo de dato, encargado de organizar
y gestionar las señales. Si conoces algo del funcionamiento de
Internet, el concepto de proxy puede orientarte. Algunos ordenadores
tienen conexión directa con Internet, mientras que otros
utilizan un servidor proxy que hace de intermediario, permitiendo la
conexión de varios ordenadores aun cuando solo se disponga de
una salida. Esto es lo que se hace en Gtk, utilizar un
intermediario que manipula las señales: Glib::SignalProxy0.
La función
signal_clicked() de la Gtk::Button devuelve un objeto Glib::SignalProxy0, nuestro intermediario gestor de señales.
Este intermediario
tiene un método que se denomina
connect(), que establece una
relación entre una señal y un functor.
¿QUÉEEE? ciertamente, para un mayor control del
sistema, esta clase no opera con funciones directamente, sino con
funciones convertidas en objetos, también llamados functor.
Esa es la misión de
sigc::ptr_fun(), convertir la
función en functor.
Para nosotros es suficiente, saber que le indica al ordenador que
cuando alguien pulse el botón, realice el
código de la función señalada.