[Taller] Signals y Slots en Qt.

Iniciado por [L]ord [R]NA, 15 Julio 2010, 03:12 AM

0 Miembros y 2 Visitantes están viendo este tema.

[L]ord [R]NA

Los Signals y Slots son los mecanismos de comunicación utilizados para comunicar objetos que heredan de Q_OBJECT. Q_OBJECT es la base de todos los objetos de Qt.

Los Slot son simplemente funciones, que se quiere decir con esto, que pueden ser llamadas por el objeto según el estandar de C++ precediendo el nombre del metodo del nombre de la funcion seguida de un punto(.) o precediendola de una  flecha(->).

Las señales podrian interpretarse como los valores de retorno que se enviaran al metodo que esta conectado a esta señal. Se declaran como si fueran metodos pero sin procedimientos. Se envian colocando primero la macro "emit" posteriormente la señal rellenando sus argumentos con los valores que se desean emitir.

Los Signals y Slots se conectan utilizando la API de Qt llamada connect(), la cual lleva la siguiente forma: connect(const Qobject* sender, const char* signal, const Qobject* reciever, const char*  slot);

Hay ciertas caracteristicas con las que cuenta la comunicación entre los signals y los slots, entre estas estan:


  • Son type-safe, esto quiere decir que la signal debe encajar con el slot.
  • Los objetos emiten señales, pero no se preocupan de que estos sean recibidos por un slot.
  • Se pueden conectar multiples signals a un solo slot.
  • Se pueden conectar un signal a multiples slots.
  • Se puede conectar un signal con otro signal.
  • Para conectarse un signal con un slot estos deben tener el mismo numero de parametros y el mismo tipo de parametros en el orden correcto.
  • Existe una simple excepcion, si un signal contiene mas parametros que un slot y ambos se conectan, se obviaran los parametros sobrantes en el signal.


No existe mejor forma para hechar un vistazo que viendo un codigo de ejemplo que demuestre lo antes explicado.

Código (cpp) [Seleccionar]

//Ejemplo.h
#ifndef EJEMPLO_H
#define EJEMPLO_H

#include <QtGui>

class QSpinBox;
class QSlider;
class QLabel;
class QVBoxLayout;
class QHBoxLayout;

class Ejemplo : public QWidget
{
   Q_OBJECT

signals:
   void setRGB(int,int,int);

private slots:
   void getRGB(int,int,int);
   void setRed(int);
   void setGreen(int);
   void setBlue(int);
   void setAlpha(int);

private:
   short int red, green, blue, alpha;
   QSpinBox *SpinRed, *SpinGreen, *SpinBlue;
   QSlider *SliderRed, *SliderGreen, *SliderBlue;
   QLabel *LabelRed, *LabelBlue, *LabelGreen;
   QVBoxLayout *LeftVertical, *MiddleRightVertical, *MiddleLeftVertical;
   QHBoxLayout *MainHorizontal;


public:
   Ejemplo(QWidget *parent = 0);


};

#endif // EJEMPLO_H



Código (cpp) [Seleccionar]

//Ejemplo.cpp
#include "ejemplo.h"

Ejemplo::Ejemplo(QWidget *parent)
   : QWidget(parent)
{

   //Construimos los Slider que utilizaremos.
   this->SliderBlue = new QSlider(Qt::Vertical,0);
   this->SliderBlue->setMinimum(0);
   this->SliderBlue->setMaximum(255);
   this->SliderRed = new QSlider(Qt::Vertical,0);
   this->SliderRed->setMinimum(0);
   this->SliderRed->setMaximum(255);
   this->SliderGreen = new QSlider(Qt::Vertical,0);
   this->SliderGreen->setMinimum(0);
   this->SliderGreen->setMaximum(255);

   //Construimos los SpinBox que utilizaremos.

   this->SpinRed = new QSpinBox;
   this->SpinRed->setMinimum(0);
   this->SpinRed->setMaximum(255);
   this->SpinBlue = new QSpinBox;
   this->SpinBlue->setMinimum(0);
   this->SpinBlue->setMaximum(255);
   this->SpinGreen = new QSpinBox;
   this->SpinGreen->setMinimum(0);
   this->SpinGreen->setMaximum(255);

   //Construimos los Labels.
   this->LabelBlue = new QLabel("Azul");
   this->LabelGreen = new QLabel("Verde");
   this->LabelRed = new QLabel("Rojo");

   //Construimos los Layout para Organizar.
   this->LeftVertical = new QVBoxLayout;
   this->MiddleLeftVertical = new QVBoxLayout;
   this->MiddleRightVertical = new QVBoxLayout;
   this->MainHorizontal = new QHBoxLayout;

   //Vamos agregando los Objetos a los Layout.
   this->LeftVertical->addWidget(this->LabelRed);
   this->LeftVertical->addWidget(this->SpinRed);
   this->LeftVertical->addWidget(this->SliderRed);
   this->MiddleLeftVertical->addWidget(this->LabelGreen);
   this->MiddleLeftVertical->addWidget(this->SpinGreen);
   this->MiddleLeftVertical->addWidget(this->SliderGreen);
   this->MiddleRightVertical->addWidget(this->LabelBlue);
   this->MiddleRightVertical->addWidget(this->SpinBlue);
   this->MiddleRightVertical->addWidget(this->SliderBlue);
   this->MainHorizontal->addLayout(this->LeftVertical);
   this->MainHorizontal->addLayout(this->MiddleLeftVertical);
   this->MainHorizontal->addLayout(this->MiddleRightVertical);
   this->setLayout(this->MainHorizontal);
   this->setWindowTitle("Cambia el Fondo(Codigo de Ejemplo)");

   this->MainHorizontal->addStretch();
   this->setFixedHeight(this->sizeHint().height());

   this->red = 0;
   this->blue = 0;
   this->green = 0;
   this->alpha = 0;

   //Realizamos las conexiones que necesitaremos.
   connect(this->SpinRed,SIGNAL(valueChanged(int)),this->SliderRed,SLOT(setValue(int)));
   connect(this->SpinGreen,SIGNAL(valueChanged(int)),this->SliderGreen,SLOT(setValue(int)));
   connect(this->SpinBlue,SIGNAL(valueChanged(int)),this->SliderBlue,SLOT(setValue(int)));
   connect(this->SliderRed,SIGNAL(valueChanged(int)),this->SpinRed,SLOT(setValue(int)));
   connect(this->SliderGreen,SIGNAL(valueChanged(int)),this->SpinGreen,SLOT(setValue(int)));
   connect(this->SliderBlue,SIGNAL(valueChanged(int)),this->SpinBlue,SLOT(setValue(int)));
   connect(this->SliderRed,SIGNAL(valueChanged(int)),this,SLOT(setRed(int)));
   connect(this->SliderGreen,SIGNAL(valueChanged(int)),this,SLOT(setGreen(int)));
   connect(this->SliderBlue,SIGNAL(valueChanged(int)),this,SLOT(setBlue(int)));
   connect(this,SIGNAL(setRGB(int,int,int)),this,SLOT(getRGB(int,int,int)));



   emit setRGB(this->red,this->green,this->blue); //Enviamos una señal para cambiar el color.

   }

void Ejemplo::setAlpha(int change)
{
   this->alpha = change;
   emit setRGB(this->red,this->green,this->blue); //Enviamos una señal para cambiar el color.

   }

void Ejemplo::setRed(int change)
{
   this->red = change;
   emit setRGB(this->red,this->green,this->blue); //Enviamos una señal para cambiar el color.

   }

void Ejemplo::setGreen(int change)
{
   this->green = change;
   emit setRGB(this->red,this->green,this->blue); //Enviamos una señal para cambiar el color.

   }

void Ejemplo::setBlue(int change)

{
   this->blue = change;
   emit setRGB(this->red,this->green,this->blue); //Enviamos una señal para cambiar el color.
   }

void Ejemplo::getRGB(int red, int green, int blue)
{
QColor *Background = new QColor(red,green,blue,255);
QPalette *Paleta = new QPalette;
Paleta->setColor(QPalette::Background,Background->convertTo(QColor::Rgb));
this->setPalette(*Paleta);
}



Código (cpp) [Seleccionar]

//main.cpp
#include <QtGui/QApplication>
#include "ejemplo.h"

int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   Ejemplo w;
   w.show();
   return a.exec();
}

leogtz

Excelente, continúa con el taller, por favor, me gustaría ponerle interfaz a algunos problemas que tengo.

Ah, por cierto, deberías de especificar como compilar.

Yo hago esto:
leo@lein:~/Escritorio/c_proyect/qt_proyects/signals$ ls -1
Ejemplo.cpp
Ejemplo.h
main.cpp
leo@lein:~/Escritorio/c_proyect/qt_proyects/signals$ qmake -project
leo@lein:~/Escritorio/c_proyect/qt_proyects/signals$ qmake *.pro
leo@lein:~/Escritorio/c_proyect/qt_proyects/signals$ sudo make
g++ -c -pipe -fpermissive -g -Wall -W -D_REENTRANT -DQT_SHARED -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. -o Ejemplo.o Ejemplo.cpp
Ejemplo.cpp:3:24: error: ui_Ejemplo.h: No existe el fichero ó directorio
make: *** [Ejemplo.o] Error 1
leo@lein:~/Escritorio/c_proyect/qt_proyects/signals$


Como ves, me da error con el ui_Ejemplo.h

Saludos.
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

[L]ord [R]NA

Lo que sucede es que siempre he compilado con el QtCreator, pero desde que termine de cenar posteo como compilar.

cbug

Muy bueno... Me quedo a la espera de como compilar  :xD

[L]ord [R]NA

#4
Cita de: Leo Gutiérrez. en 15 Julio 2010, 03:33 AM
Excelente, continúa con el taller, por favor, me gustaría ponerle interfaz a algunos problemas que tengo.

Ah, por cierto, deberías de especificar como compilar.

Yo hago esto:
leo@lein:~/Escritorio/c_proyect/qt_proyects/signals$ ls -1
Ejemplo.cpp
Ejemplo.h
main.cpp
leo@lein:~/Escritorio/c_proyect/qt_proyects/signals$ qmake -project
leo@lein:~/Escritorio/c_proyect/qt_proyects/signals$ qmake *.pro
leo@lein:~/Escritorio/c_proyect/qt_proyects/signals$ sudo make
g++ -c -pipe -fpermissive -g -Wall -W -D_REENTRANT -DQT_SHARED -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. -o Ejemplo.o Ejemplo.cpp
Ejemplo.cpp:3:24: error: ui_Ejemplo.h: No existe el fichero ó directorio
make: *** [Ejemplo.o] Error 1
leo@lein:~/Escritorio/c_proyect/qt_proyects/signals$


Como ves, me da error con el ui_Ejemplo.h

Saludos.

@LeoGutierrez: lo que sucede es que el QtCreator añade el #include "ui_ejemplo.h" por si quieres utilizar el QtDesigner pero soy un poco loco y prefiero hacer todo con codigo... solo tienes que quitar esa linea y compila correctamente. Por cierto la quite en el codigo, disculpen fue un error mio.

@cbug: Lo habia olvidado... ahora mismo pongo los pasos


1) qmake-qt4 -project
       
Esto se ejecuta dentro de la carpeta del proyecto con todos los ficheros a utilizar... esto creara un fichero *.pro.

2) qmake-qt4 *.pro

Esto creara un fichero llamado makefile.

3) make

Esto creara el programa funcional.

Debci

Muyyyyy bueno, hace ya mucho que buscaba un tutorial de este calibre y en castellano que te da menos cuelgue lerlo, pero en este caso son lecturas obligadas, no leerlo seria un delito ;)

Saludos

[Zero]

Jaja, ya aprendiste a manejar Layouts con código, yo nunca aprendí, justo ahí le cogí gusto al Designer  :xD. Muy buen texto, seguiré leyendo si decides continuar escribiendo  :P.

Saludos

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche

[L]ord [R]NA

Cita de: [Zero] en 15 Julio 2010, 14:39 PM
Jaja, ya aprendiste a manejar Layouts con código, yo nunca aprendí, justo ahí le cogí gusto al Designer  :xD. Muy buen texto, seguiré leyendo si decides continuar escribiendo  :P.

Saludos

:xD tenemos una pequeña diferencia... yo no se usar el Designer, me vuelvo un disparate.

sizeofc

Hola necesito ayuda, tengo una aplicacion en la cual consiste en un formprincipal.cpp en el cual tiene un boton editar actionEditar que sirve para editar la fila seleccionada en un qtablewidget que se encuentra dentro del mismo formulario y al precionar dicho boton se abre un formulario llamado actualizaborrar en el cual tendria que cargar los datos de la fila seleccionada. y no se como hacerlo
lo que hago al precionar el boton editar es:

void formprincipal::on_actionEditar_triggered()
{

    actualizaBorrar formActualBorrar(this);//creao una instancia del la clase actualizaBorrar
    int resp;
    qDebug()<<"Item seleccionado: "<<getSelectItem();//esta funcion devuelve el item seleccionado

    formActualBorrar.setSelectItem(getSelectItem());//en esta linea intento setear el id a buscar en la base de datos con un metodo setselectItem

    resp= formActualBorrar.exec(); //muestro el formulario
 
    if(resp==QDialog::Rejected)
        return;                             //si en el formulario no presiono cancel seguiria actualizar los datos de la base de datos con los campos del formulario