Criado em 12/01/2011 às 12:00

Depois de conhecer o modo com que Qt organiza seus arquivos vamos dar continuidade ao exemplo da lanchonete. Na página "O Poder do Qt Designer" fizemos o programinha através de uma visão puramente gráfica. Agora vamos implementar um pouco de funcionalidade a ele.
Antes de partir para o código propriamente dito, vamos alterar o formulário "ui" que havíamos criado para que possamos abrir uma nova janela quando o usuário clicar em um botão "Ajuda" por exemplo.
Então, abra o projeto novamente e de duplo clique no formulário dialog.ui, sob a pasta "Forms". Para adicionar um novo botão é necessário aumentar um pouco o tamanho atual da janela, porque um novo botão não cabe ali.
Perceba que se você tentar aumentar a janela você não conseguirá. Isso acontece porque nós tinhamos definido este tamanho como "Maximum Size" e "Minimum Size". Então acesse a propriedade maximumSize (de QWIdget) do "property editor" e clique no botão que tem uma pequena seta. O tamanho será redefinido para o tamanho máximo original (16777215x16777215).
Agora você pode expandir o quanto quiser. Para que nós entremos num acordo, ajuste as propriedades "Width" e "Height" da sua janela para 350 e 150 respectivamente. Depois disso insira um novo botão entre os dois botões pré existentes, mude seu texto de exibição para "Ajuda" e seu objectName para "ajuda".
Perceba que a imagem de fundo permaneceu do mesmo tamanho e começa a se repetir no eixo horizontal. Para consertar isso, Acesse seu arquivo "Resource" sob a pasta Resources, remova a imagem anterior e adicione a nova imagem deste link:
Não esqueça de adicionar a imagem à pasta de imagens.
Ao salvar o arquivo resource, o fundo atualizará automaticamente.
Agora criaremos a janela (dialog) que será exibida quando o usuário clicar em "Ajuda".
Da mesma forma que fizemos para adicionar um arquivo resource:
- clique com o botão direito no projeto
- escolha "Add New..."
- Qt, Qt Designer Form class,
- Dialog without buttons, ok
- mude o nome para "DialogoAjuda":
Neste novo formulário adicione uma nova label, para mudar seu texto de forma que exiba mais do que uma linha de texto acesse a propriedade "text" no proprety editor. Clique no botão "..." e escreva um texto qualquer.
Clique no formulário e aplique um layout vertical (ou horizontal, já que só temos uma coisa para alinhar) e clique no botão Adjust Size.
Com isso nosso dialog adicional está pronto.
Neste momento, seus arquivos devem se apresentar da seguinte forma:
Agora que todos os forms estão desenhados, é hora de partir para o código. Você pode testar seu programa agora para ver se tudo está funcionando corretamente clicando no botão "Run" ou pressionando Ctrl+R:
Mas é claro que os botões ainda não funcionam, você ainda não os conectou.
Nada mais justo que começarmos pelo main (que já está pronto):
Código 12. main.cpp do programinha "lanchonete".
#include <QtGui/QApplication> //QObject-QCoreApplication-QApplication
#include "dialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
return a.exec();
}
No main, nada de novo certo? A classe Dialog é a classe que foi criada automaticamente pelo QtCreator quando escolhemos o nome "Dialog" la no começinho. Vamos ao código de dialog.h (header do dialogo que criamos no designer, que tem os radio buttons e botões):
Código 13. dialog.h do programinha "lanchonete".
#include <QDialog> //QObject-QWidget-QDialog
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
//adicionado
public slots:
void ok_clicado();
void cancel_clicado();
void abrir_ajuda();
};
#endif // DIALOG_H
Começamos com um include de QDialog, por que derivamos dela afinal.
O namespace Ui é obra do QtCreator, lembra? ele define esse namespace quando trabalhamos com formulários.
O macro Q_OBJECT é necessário porque neste caso implementaremos nossos próprios slots. Nós poderiamos escolher os slots padrões de fechamento de diálogos para os botões OK e cancelar (accept() ou reject()) mas nós queremos que seja exibida uma mensagem antes que o dialog feche, então vamos criar nosso proprio slot. Lembre-se de que slots podem ser chamados como funções, não necessariamente numa conexão. Vale a pena destacar que accept() e reject() são funções virtuais e nesse caso provavelmente seriam reimplementadas, mas do jeito que está é mais simples para quem está começando.
As declarações públicas compreendem as funções construtora e destrutora.
A declaração private compreende apenas o ponteiro Ui, que é elo de ligação entre nosso formulário e o código.
As declarações slot publicos são nossos 3 slots, um para cada botão clicado.
Vamos à implementação desta classe (dialog.cpp):
Código 14. dialog.cpp do programinha "lanchonete".
#include "dialog.h"
#include "ui_dialog.h"
#include "dialogoajuda.h"
#include <QMessageBox> //QObject-QWidget-QDialog-QMessageBox
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
connect(ui->ok, SIGNAL(clicked()), this, SLOT(ok_clicado()));
connect(ui->cancel, SIGNAL(clicked()), this, SLOT(cancel_clicado()));
connect(ui->ajuda, SIGNAL(clicked()), this, SLOT(abrir_ajuda()));
}
void Dialog::ok_clicado()
{
QString saindo;
saindo = "Saindo um ";
if(ui->xSalada->isChecked())
{
saindo += "X-Salada, ";
}
else
{
if(ui->xFrango->isChecked())
{
saindo += "X-Frango, ";
}
else
{
if(ui->xTudo->isChecked())
{
saindo += "X-Tudo, ";
}
else
{
saindo += "X-Nada, ";
}
}
}
saindo += "com refrigereco ";
if(ui->noCal->isChecked())
{
saindo += "light ";
}
if(ui->noGelo->isChecked())
{
saindo += "sem gelo ";
}
saindo += "!!";
QMessageBox::information(this,"Pedido Finalizado!", saindo);
this->accept();
}
void Dialog::cancel_clicado()
{
QString saindo("Saindo um cliente descontente !!");
QMessageBox::information(this,"Pedido Finalizado", saindo);
this->reject();
}
void Dialog::abrir_ajuda()
{
DialogoAjuda dialog(this);
dialog.exec();
}
Dialog::~Dialog()
{
delete ui;
}
O código pode parecer grande, mas optei por fazer um código bem simples e claro, mas não é tão grande. Começamos pelos includes das nossas classes (tanto a classe criada inicialmente quanto a adicionada posteriormente). Incluímos também a classe QMessageBox porque iremos mostrar uma mensagem quando o usuário clicar em Ok ou cancelar. Para mensagens simples, podemos usar este dialog pré-pronto QMessageBox. Veremos mais adiante.
A construtora começa já chamando a construtora de QDialog e inicializando o ponteiro ui (no cabeçalho). "setupUi" é chamada para vestir a roupa que projetamos no designer no dialog criado no main. Depois disso, os slots mostrados são conectados a cada botão através do signal "clicked()", um signal padrão de botões.
O nosso slot "ok_clicked()" nada mais faz do que criar uma string e povoá-la com um texto dependendo do que estiver selecionado na janela. Veja como acessamos os objetos do nosso formulário através do ponteiro Ui. "isChecked()" é a função que nos permite saber se aquele radio button está checado retornando true ou false.
Depois de analisar todas as possíveis escolhas, o programa exibe uma mensagem informando qual é o pedido através da função estática "information" de QMessageBox. QMessageBox é um dialogo pré-pronto de Qt que permite que nós exibamos mensagens na tela através de uma janela. Ele tem algumas funções estáticas que permitem que nós chamemos alguns tipos pré-definidos de dialogs sem termos necessariamente que instanciar uma nova classe QMessageBox. Além da função information, existem outras (que já tem o ícone bonitinho do lado esquerdo):
- QMessageBox::question(parent, título, texto)
- QMessageBox::information(parent, título, texto)
- QMessageBox::warning(parent, título, texto)
- QMessageBox::critical(parent, título, texto)
Estas são algumas funções estáticas e alguns parâmetros. A utilidade do parâmetro "parent" será discutida mais adiante. Outra forma de se fazer isso é instanciando uma classe QMessageBox e personalizando-a inteira.
O mesmo raciocínio se aplica para o botão cancelar. O botão de ajuda exibe um dialog criado por nós. O slot conectado a esse botão cria uma nova instancia para a classe "DialogoAjuda" e já manda ele entrar no loop de eventos (exec()). É isso mesmo, só de chamar a função exec() do dialog recém-criado ele já é exibido. O parâmetro this e a função exec() serão discutidos mais a frente.
Os códigos para "dialogoajuda.h" e "dialogoajuda.cpp" são criados automaticamente pelo QtCreator e nós não mudamos nadinha de nada, já que fizemos alterações apenas no formulário. Essas mudanças no formulário estarão na caixinha de supresas e como não implementamos absolutamente nada no ".cpp" então a construtora apenas chama setupUi. Mas aqui estão os códigos:
Código 15. dialogoajuda.h do programinha "lanchonete".
#ifndef DIALOGOAJUDA_H
#define DIALOGOAJUDA_H
#include <QDialog>
namespace Ui {
class DialogoAjuda;
}
class DialogoAjuda : public QDialog
{
Q_OBJECT
public:
explicit DialogoAjuda(QWidget *parent = 0);
~DialogoAjuda();
private:
Ui::DialogoAjuda *ui;
};
#endif // DIALOGOAJUDA_H
Código 16. dialogoajuda.cpp do programinha "lanchonete".
#include "dialogoajuda.h"
#include "ui_dialogoajuda.h"
DialogoAjuda::DialogoAjuda(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogoAjuda)
{
ui->setupUi(this);
}
DialogoAjuda::~DialogoAjuda()
{
delete ui;
}
Agora que todos os formulários estão criados, os botões conectados, os slots implementados, é hora de compilar. Quando se usa o QtCreator, ao clicar no botão "Run" ele executa o "make.exe" sozinho então não é necessário mais o uso do prompt de comando. TRY IT!
Responda as questões abaixo para um melhor entendimento do comportamento de dialogs abertos a partir da janela principal.
Exercício 3
i) O que acontece se passarmos "0" ao invés de "this" como parent das nossas QMessageBox::information?
ii) O que acontece se instanciarmos nossa classe Dialogoajuda sem utilizar a construtora ("DialogoAjuda dialog;" ao invés de "DialogoAjuda dialog(this)")
iii) Qual a diferença de comportamento entre "janela que mandou abrir" e a "janela aberta" quando executamos a função exec() ou show() ("dialog.exec()" e "dialog.show()").
Exemplo desta página, clique aqui
|