Criado em 26/09/2010 às 17:44
Esta página tratá mais informações sobre parentesco e como utilizar SIGNALs e SLOTs. Como já foi dito anteriormente,
o conhecimento das classes do Qt é extremamente importante e, por esse motivo, a partir de agora sempre que eu chamar alguma
diretiva #include colocarei um comentário ao lado mostrando todo o caminho de herança da classe,
por exemplo: "#include <QApplication> //QObject-QCoreApplication-QApplication".
Vamos começar exemplificando o parentesco com a criação de um botão QPushButton dentro (filho) da nossa QLabel do exemplo anterior.
Mas o botão será criado na heap, seguindo a recomendação da página anterior. O botão também é uma widget. Todas as widgets tem uma construtora com um parâmetro "(QWidget * parent = 0)". Este parâmetro serve para dizer "sua mãe/pai será..". Observe no Código 3 como o
botão é criado:
Código 3. Criação de um botão, filho da label (main.cpp).
#include <QApplication> //QObject-QCoreApplication-QApplication
#include <QLabel> //QObject-QWidget-QFrame-QLabel
#include <QPushButton> //QObject-QWidget-QAbstractButton-QPushButton
int main(int argc, char * argv[])
{
QApplication app(argc, argv);
QLabel textinho("Que mané Hello World oq!? Meu nome é Zé Pequeno!");
textinho.resize(400,80);
textinho.setAlignment(Qt::AlignCenter);
QPushButton *botao = new QPushButton("Botão inutil", &textinho);
textinho.show();
app.exec();
}
É, um botão filho de uma label não é lá uma coisa muito útil, mas para exemplificar é o suficiente. Perceba as diretivas #include
tanto para a QLabel quanto para o QPushButton, ambas vem das classes QObject-QWidget.
Observe também que "textinho" é passado como parente do botão pelo endereço (&textinho), já que o parametro "QWidget * parent = 0" da construtora do botão é um ponteiro. Vamos dar uma olhadinha no resultado para este código:
Nossa label funciona, neste caso, como um container armazenando o botão. Note que o botão foi colocado no "local padrão" já que não especificamos nenhuma geometria para ele (canto superior esquerdo), e ao redimensionar a janela como mostrado na figura acima, o botão "tampa" um pedaço do texto da label. Essa é
a forma que, geralmente, iremos dizer quem é mãe de quem. Vamos dar uma olhada nos passos envolvidos na execução do programa:
- O programa inicia;
- a label "textinho" é criada no Stack e é configurada;
- o botão "botao" é criado na Heap, e sua mãe é "textinho";
- a widget "textinho" é exibida e, junto com ela, seu filho botao;
- o programa entra no loop de eventos;
- ao fechar o programa, todas as variáveis declaradas na Stack serão deletadas;
- no caso da variável "textinho", ela procura pelos filhos e os deleta automáticamente (botao);
- "textinho" é deletada;
- fim!
Já que estamos com um botão inútil, vamos fazer com que seja fechado ao clicar.
O Uso de Signals e Slots
Modifique o código 3 de acordo com o código abaixo adicionando uma conexão para o botão:
Código 4. "Conectando" o botão à alguma ação(main.cpp).
#include <QApplication> //QObject-QCoreApplication-QApplication
#include <QLabel> //QObject-QWidget-QFrame-QLabel
#include <QPushButton> //QObject-QWidget-QAbstractButton-QPushButton
int main(int argc, char * argv[])
{
QApplication app(argc, argv);
QLabel textinho("Que mané Hello World oq!? Meu nome é Zé Pequeno!");
textinho.resize(400,80);
textinho.setAlignment(Qt::AlignCenter);
QPushButton *botao = new QPushButton("Botão inutil", &textinho);
QObject::connect(botao, SIGNAL(clicked()), botao, SLOT(close()));
textinho.show();
app.exec();
}
A função utilizada para conectar o botão a alguma ação (ou um widget a uma ação) está declarada dentro da classe QObject (a função pública e estática connect) por isso precisamos
utilizar o operador de resolução de escopo "::". Poderiamos traduzir a linha "QObject::connect(botao, SIGNAL(clicked()), botao, SLOT(close()));"
como: Ao clicar no widget sender "botão", feche o widget receiver "botão". Existem algumas propriedades importantes de SIGNALS/SLOTS, como por exemplo, parâmetros de cada um passados para o outro. Essas propriedades serão abordadas mais futuramente.
|
Mas então você pergunta:
E como vou saber quais funções podem "entrar" ali no slot? Eu posso criar uma??
|
Ao pesquisar sobre a classe QPushButton no Qt Assistant você encontra o seguinte:
Então estes são os "slots padrões" que podemos chamar quando o widget receiver for um botão. Você também pode criar um Slot,
para isso basta você declará-lo como uma função dentro da sessão "public slots" de sua classe. A partir de agora além de declarar sessões
public:, private:, protected:, você também declarará public slots:, por exemplo.
Com todos os conceitos mostrados até agora já podemos criar uma aplicação menos inútil! uma aplicação que realmente faça alguma coisa.
|
2012-01-31 16:22:39, disse:
Tudo bem Danilo.
Muito legal o site.
Mas estou com algumas dúvidas:
Como eu chamo um SLOT de uma classe diferente da qual eu estou trabalhando?
Por exemplo, no meu caso: Seja a classe ButtonMine, derivada de QPushButton, e eu queira acessar o SLOT buttonMineClicked() desta classe a partir da class MainWindow, como será a sintaxe do connect? Eu tentei assim:
ButtonMine *buttons [10][10];
...
connect(
buttons [i][j],
SIGNAL(clicked()),
this,
SLOT(buttons [i][j]->ButtonMineClicked()));
Mas não funciona.
Toda a parte de inicialização e "sets" está funcionando.
Outra coisa, é possível conectar SIGNAL e SLOT com assinaturas diferentes?
Desde já agradeço.
|
2012-05-02 13:28:06, disse:
Olá André,
Você já tentou utilizar o connect dessa forma?:
connect(buttons[i][j], SIGNAL(clicked()), buttons[i][j], SLOT(ButtonMineClicked()));
Por assinatura você quer dizer o parâmetro do SIGNAL() e do SLOT()? Se sim, você não pode conectar SIGNALs e SLOTs com assinaturas diferentes. Se vc tem SIGNAL(int,int) então seu SLOT deverá ser SLOT(int,int).
Hoje quando eu chegar em casa vou fazer um exemplo e pensar melhor na sua primeira dúvida.
|