Qt/Sinais e slots
A comunicação entre os widgets, no Qt, é feita através de sinais (signals) e slots.
O mecanismo para ligar um sinal a um slot é através da função connect:
QObject::connect( p_widget1, signal1, p_widget2, slot2);
em que p_widget1 é um pointer para o widget sobre o qual a ação ocorre, signal1 é o sinal indicativo desta ação, p_widget2 é o widget que vai responder ao sinal e slot2 é a resposta.
Introdução
[editar | editar código-fonte]O objetivo é colocar um botão e uma caixa de texto. Ao clicar o botão (que possui como texto a string "OK"), a caixa de texto deve responder assumindo o valor "OK".
O esboço de código abaixo não faz nada, apenas mostra os widgets:
int main( int argc, char *argv[])
{
QApplication app(argc, argv);
QVBox vbox;
QPushButton button1("OK", &vbox);
QLineEdit lineedit1("", &vbox);
app.setMainWidget(&vbox);
vbox.show();
return app.exec();
}
Precisamos que lineedit1 execute o seu membro setText("OK"); assim que o botão for clicado, ou seja, precisamos fazer a conexão:
QObject::connect( &button1, SIGNAL(clicked()), &lineedit1, SLOT(setText("OK")) );
O problema é que, pela documentação da função connect[1], o número de argumentos do signal deve ser o mesmo do número de argumentos do slot - e, neste caso, o signal não tem argumentos porém estamos querendo que o slot tenha um argumento.
Ou seja, o código abaixo está errado:
int main( int argc, char *argv[])
{
QApplication app(argc, argv);
QVBox vbox;
QPushButton button1("OK", &vbox);
QLineEdit lineedit1("", &vbox);
QObject::connect( &button1, SIGNAL(clicked()), &lineedit1, SLOT(setText("OK")) );
app.setMainWidget(&vbox);
vbox.show();
return app.exec();
}
Solução orientada a objetos
[editar | editar código-fonte]A solução é transformar setText("OK") em um membro do QLineEdit. Isto é feito através do mecanismo conhecido por herança, ou seja, será criada uma nova classe, NovoLineEdit, que herdará tudo da classe QLineEdit, e terá, além disso, um novo membro, escreve_ok() que fará apenas o setText("OK").
O header .h
[editar | editar código-fonte]Uma das formas de fazer isso é criar um outro arquivo, de extensão .h (no nosso exemplo, chamado de qt_button_1.h) que contém a definição da nova classe:
#include <qlineedit.h>
class NovoLineEdit : public QLineEdit
{
Q_OBJECT
public:
NovoLineEdit(const QString & contents, QWidget * parent, const char * name = 0);
private slots:
void escreve_ok();
};
Detalhando este arquivo:
Como a nova classe herda da QLineEdit, temos que incluir qlineedit.h
class NovoLineEdit : public QLineEdit
é a declaração da nova classe (NovoLineEdit), como uma classe filha da classe QLineEdit.
A linha Q_OBJECT não é uma instrução em C++. É necessária para informar ao pré-compilador moc de que é necessário habilitar os sinais e slots, ou seja, o Q_OBJECT habilata os sinais emitidos na GUI e os slots contidos na GUI.
É necessário incluir o constructor
public:
NovoLineEdit(const QString & contents, QWidget * parent, const char * name = 0);
já que este será chamado pelo programa.
Finalmente,
private slots:
void escreve_ok();
é a função (slot) que será ligada ao signal. Note-se, de novo, que a palavra slots não faz parte da linguagem C++, sendo, assim como Q_OBJECT, coisas que o moc usa para gerar informações exotéricas.
O fonte .cpp
[editar | editar código-fonte]O fonte em C++ é:
#include <qapplication.h>
#include <qvbox.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include "qt_button_1.h"
void NovoLineEdit::escreve_ok()
{
setText("OK");
}
NovoLineEdit::NovoLineEdit(const QString & contents, QWidget * parent, const char * name) :
QLineEdit(contents, parent, name)
{
}
int main( int argc, char *argv[])
{
QApplication app(argc, argv);
QVBox vbox;
QPushButton button1("OK", &vbox);
NovoLineEdit lineedit1("", &vbox);
QObject::connect( &button1, SIGNAL(clicked()), &lineedit1, SLOT(escreve_ok()) );
app.setMainWidget(&vbox);
vbox.show();
return app.exec();
}
Detalhando:
void NovoLineEdit::escreve_ok()
{
setText("OK");
}
é o slot. Como pode ser visto, este é um membro normal da classe certa.
NovoLineEdit::NovoLineEdit(const QString & contents, QWidget * parent, const char * name) :
QLineEdit(contents, parent, name)
{
}
é o constructor da nova classe. O objetivo é que NovoLineEdit seja construído exatamente da mesma forma que o QLineEdit - lembrando que a única diferença é o acréscimo do membro escreve_ok.
QObject::connect( &button1, SIGNAL(clicked()), &lineedit1, SLOT(escreve_ok()) );
finalmente, a conexão entre o ato de clicar no botão e o QLineEdit responder é feita.
Referências
- ↑ Signals and Slots - documentação oficial em inglês