Signals y Slots. Implementando la Funcionalidad de una Aplicación Qt
En la parte anterior de este tutorial vimos como utilizar layouts para diseñar la interfaz gráfica de nuestras aplicaciones y para ejemplificarlo diseñamos un diálogo de inicio de sesión.
En esta parte del tutorial aprenderemos a implementar la funcionalidad de nuestras aplicaciones utilizando Señales y Slots, los cuales forman el mecanismo a través del cual los objetos de una aplicación de Qt (incluyendo widgets) se comunican. Este mecanismo es una de la características distintivas de Qt, ya que otros frameworks suelen utilizar un enfoque basado en callbacks.
Una señal es una notificación que un objeto emite cuándo cambia su estado de manera que podría interesarle a otros objetos. Un slot es una función que se ejecuta cuándo una señal se emite.
Cualquier objeto en el que deseemos implementar señales y slots debe de heredar de la clase QObject, los widgets que utilizaremos normalmente cumplen con esto ya que heredan de QWidget que a su vez hereda de QObject. Los widgets que nos proporciona Qt poseen señales y slots predefinidos, pero también es posible crear un widget personalizado con el fin de añadir nuestras propias señales y slots.
A continuación mostramos el código de nuestra aplicación de inicio de sesión, en el cuál utilizamos señales y slots para implementar su funcionalidad, esto es que al capturar un nombre de usuario registrado y su contraseña correspondiente se nos permita el acceso a una sección restringida de una aplicación y que al capturar un nombre de usuario no registrado o una contraseña no coincidente se niegue el acceso.
En este ejemplo utilizaremos dos señales y dos slots, recordemos que las señales se emiten cuándo un objeto cambia de estado de manera interesante para otros objetos, en este caso serán emitidas cuando se presione alguno de los botones; Cada una de estas señales está conectada a un slot diferente, el cual se ejecuta cuando el botón respectivo es presionado. Más adelante veremos el código de estos slots.
En esta ocasión nuestra aplicación se compone de tres archivos, un archivo de definición de la clase, uno de implementación y un archivo main, definimos una nueva clase debido a que necesitamos un diálogo personalizado para implementar el slot que se ejecutará cuándo se presione el botón Aceptar en nuestra ventana de login, el slot que se ejecuta cuando se presiona el botón cancelar (close() el cual cierra la ventana) ya está predefinido.
NOTA: Sólo revisaremos a detalle las secciones que no hayan sido explicadas en partes anteriores del tutorial o que sean relevantes para esta explicación
El contenido de login.h, el archivo de definición de clase, es el siguiente:
#ifndef LOGIN_H #define LOGIN_H #include <QDialog> class QPushButton; class QLineEdit; { Q_OBJECT public: private slots: void verificarDatos(); private: }; #endif // LOGIN_H
#include <QDialog>En la línea 4 incluimos el archivo de cabecera de QDialog el cuál necesitamos debido a que nos basaremos en él para construir nuestro diálogo.
class QPushButton; class QLineEdit;
En las líneas 6 y 7 indicamos al compilador que utilizaremos las clases QPushButton y QLineEdit, pero no especificamos sus detalles, los cuales se encuentran en sus archivos .h propios, es posible hacer esto debido a que declaramos las variables como tipo apuntador y a que en este archivo sólo las definimos pero no las utilizamos. También hubiera sido posible incluir los archivos de cabecera pero el sólo indicar el nombre de las clases permite reducir el tiempo de compilación.
class Login : public QDialog
En la línea 9 definimos nuestra nueva clase, la cual tendrá el nombre de Login y heredará de QDialog.
Q_OBJECTEn la línea 11 utilizamos una macro llamada Q_OBJECT la cual es necesaria en cada clase que utilice señales y slots. Esta macro define algunas funciones de instrospección utilizadas por otras funciones como connect() y es necesaria para que el código de Qt sea traducido por el compilador meta objeto (moc, por sus siglas en inglés) a código C++ estándar.
public: Login();
A partir de la línea 13 declalramos las funciones y los miembros de nuestra clase. En la línea 14 declaramos el constructor de nuestra clase.
void verificar();
En la línea 17 definimos nuestro slot personalizado, el cual lleva por nombre verificarDatos(), se ejecuta cuándo se presione el botón Aceptar y como su nombre lo indica se encarga de verificar que los datos ingresados sean correctos.
QPushButton *botonAceptar, *botonCancelar; QLineEdit *campoUsuario, *campoPassword;
En las líneas 20 y 21 declaramos los widgets que utilizaremos en nuestra aplicación, dos campos de texto, uno para el nombre de usuario y otro para la contraseña y dos botones, uno para solicitar la verificación de los datos capturados y otro para salir, que sólo se provee por comodidad.
El contenido del archivo login.cpp es el siguiente:
#include "login.h" #include <QApplication> #include <QPushButton> #include <QLineEdit> #include <QFormLayout> #include <QHBoxLayout> #include <QMessageBox> { layoutBotones->addStretch(); layoutBotones->addWidget(botonAceptar); layoutBotones->addWidget(botonCancelar); layoutPrincipal->addRow(trUtf8("Usuario"), campoUsuario); layoutPrincipal->addRow(trUtf8("Contraseña"), campoPassword); layoutPrincipal->addRow(layoutBotones); setLayout(layoutPrincipal); connect(botonAceptar, SIGNAL(clicked()), this, SLOT(verificarDatos())); connect(botonCancelar, SIGNAL(clicked()), this, SLOT(close())); } void Login::verificarDatos() { if(campoUsuario->text() == "zonaqt" && campoPassword->text() == "zonaqt"){ } else }
#include "login.h"En la línea 1 incluimos el archivo de definición de nuestra clase.
Login::Login() { QFormLayout *layoutPrincipal = new QFormLayout; QHBoxLayout *layoutBotones = new QHBoxLayout; ...
En la línea 10 comienza la implementación del constructor de nuestra clase, en él inicializamos los widgets y layouts necesario para la aplicación y definimos la apariencia de nuestro widget de la misma forma que hicimos en la sección anterior del tutorial.
connect(botonAceptar, SIGNAL(clicked()), this, SLOT(verificar())); connect(botonCancelar, SIGNAL(clicked()), this, SLOT(close()));
Las líneas 30 y 31 son las que presentan novedades. En ellas utilizamos la función:
connect(QObject *emisor, const char *signal, QObject *receptor, const char *slot, Qt::ConnectionType type=Qt::AutoConnection);
La función connect es la encargada de conectar o enlazar dos QObjects, recibe como parámetros un apuntador al QObject emisor de la señal de interés, un apuntador a un arreglo de caracteres que indica la firma de función de la señal que nos interesa monitorear, un apuntador al QObject receptor de la señal y otro apuntador a un arreglo de caracteres, esta vez con la firma de función del slot que se ejecutará cuándo se emita la señal indicada.
Las macros SIGNAL() y SLOT() son requeridas por el moc al indicar el segundo y cuarto parámetro, respectivamente. Es necesario que las firmas de las funciones indicadas en estas macros coincidan en sus parámetros. Con la excepción de que la señal indicada puede tener más parámetros que los requeridos por el slot, en este caso los parámetros adicionales son ignorados.
Al utilizar la función connect() se pueden presentar los siguientes casos:
- Cada señal está conectada a un slot distinto. Este es el caso más simple y es el que mostramos en este ejemplo, en él el slot que se ejecuta depende de la señal que se emite.
- Más de una señal puede estar conectada a un slot. En este caso el slot se ejecutará cuándo se emita cualquiera de las señales conectadas a él.
- Una señal puede estar conectada a más de un slot. En este caso todos los slots conectados a la señal en cuestión se ejecutarán cuándo dicha señal se emita, uno tras otro en un orden indeterminado.
- Una señal puede estar conectada a otra señal. En este caso la señal indicada en el cuarto parámetro se emitirá al emitirse la indicada en el segundo parámetro.
- #include <QApplication>
- #include "login.h"
- int main(int argc, char *argv[])
- {
- Login *login = new Login();
- login->show();
- return app.exec();
- }
void Login::verificar()
En la línea 34 comienza la implementación de nuestro slot personalizado, indicamos el tipo de dato de retorno, después la clase a la que pertenece seguido del nombre del slot y su lista de parámetros, en este caso no ningún parámetro es requerido.
if(campoUsuario->text() == "zonaqt.com" && campoPassword->text() == "zonaqt.com"){ QMessageBox::information(this, "", trUtf8("Bienvenido a la aplicación")); emit exit(0); } else QMessageBox::warning(this, "", trUtf8("La combinación usuario/contraseña no es válida"));
En la línea 36 verificamos que la información capturada en los campos de texto coincida con la información de algún usuario registrado, en este caso y para mantener la simpleza indicamos en el código un único usuario: programacion, y su contraseña correspondiente: linux. La función QLineEdit::text() devuelve una QString con el contenido del QLineEdit en cuestión, en este caso el nombre de usuario para campoUsuario y la contraseña para campo Password.
QString es una clase de Qt que representa una cadena de caracteres unicode y que nos proporciona funciones bastante útiles como concatenación, traducción o búsqueda y reemplazo de caracteres, entre otras.
En caso de que la información capturada sea correcta mostramos un mensaje de bienvenida o confirmación y cerramos esta ventana para mostrar la ventana principal, debido a que en este momento sólo tenemos una ventana entonces salimos de la aplicación. En caso de que la información capturada sea incorrecta mostramos un mensaje de aviso informando que hubo un error.
Los mensajes de bienvenida o error, son mostrados al usuario utilizando las funciones estáticas de la clase QMessageBox
StandarButton QMessageBox::information(QWidget *padre, const QString &titulo, const QString &mensaje, StandarButtons boton=Ok, StandarButton botonPredeterminado=NoButton)
Esta función la utilizamos para mostrar un diálogo como el siguiente:
StandarButton QMessageBox::warning(QWidget *padre, const QString &titulo, const QString &mensaje, StandarButtons botones=Ok, StandarButton botonPredeterminado=NoButton)
Esta función la utilizamos para mostrar un diálogo como el siguiente:
Estas funciones permiten mostrar un diálogo para mostrar información relevante o hacer una pregunta al usuario y recibir una respuesta.
Estas funciones reciben como parámetros obligatorios: Un apuntador al QWidget padre, que en este caso es nuestra ventana de login lo cual indicamos con la instrucción this; Una cadena de texto que será el título del mensaje; Y una cadena de texto que aparecerá en el contenido del QMessageBox.
Y como parámetros opcionales: Un conjunto de valores de la enumeración StandarButtons, que representan los botones que la QMessageBox incluirá y un elemento de la enumeración StandarButtons el cual representa al botón por default de la QMessageBox, es decir, el cual cambiará su estado a presionado (emitirá la señal clicked()) al presionar la tecla enter, en caso de no especificar estos parámetros se seleccionará por defecto el botón Ok.
El contenido del archivo main.cpp es el siguiente
#include "login.h"En la línea 2 incluimos el archivo de definición de nuestra clase Login.
Login login;login.show();
Y finalmente en la línea 8 creamos e inicializamos un objeto de nuestra clase login, el cual mostramos en la línea 10.




Comentarios recientes
hace 1 día 4 horas
hace 2 días 18 horas
hace 2 días 23 horas
hace 3 días 16 horas
hace 3 días 21 horas
hace 3 días 21 horas
hace 5 días 15 horas
hace 6 días 2 horas
hace 1 semana 1 día
hace 1 semana 2 días