Como criar um “Dialog” utilizando o Qt Designer?

Vou partir do princípio que já temos as nossas revisões de C++, Classes e o básico do Qt em dia (“Hello World!”), pois não vou dar grande ênfase ou explicação a esse tipo de detalhes, evitando desta forma correr o risco de não conseguir fazer passar a minha mensagem.

Na terminologia utilizada em QT um widget é um elemento visual que faz parte de uma interface com o utilizador.

Uma aplicação geralmente possui um menu principal a partir do qual podemos chamar vários “dialogs”, que são nada mais nada menos que formulários utilizados para interagir com o utilizador, solicitando-lhe os dados necessários ou apresentando resultados do processamento.

Cada “dialog” é construído utilizando um conjunto de “widgets” e estabelecendo ligações (SIGNALS/SLOTS) entre eles.

Geralmente só é possível garantir a funcionalidade do nosso “dialog” recorrendo a mecanismos de herança, ou seja, por  “subclassing” da classe QDialog.

Convém ter presente que é possível construir uma aplicação sem recorrer ao Qt Designer, mas a sua utilização pode tornar mais rápida a tarefa de desenvolvimento de interfaces gráficas complexas.

Todo este artigo vai girar em torno de um pequeno formulário (dialog) que serve para introduzir a matrícula de um automóvel. Além dos botões para aceitar ou cancelar, será necessária uma área para digitarmos a identificação do veículo, que naturalmente obedece a regras muito específicas.

O resultado final será algo do tipo:

matriculaConvém dar uma vista de olhos sobre a teoria, ou seja, como estão organizadas as matrículas dos automóveis em Portugal, pois de outra forma não nos será possível entender a fase de validação dos dados.

Neste exemplo concreto temos um “dialog” designado “Matrícula”, que utiliza pelo menos quatro “widgets”, isto porque podem existir alguns que não são visíveis nesta fase. Estes correspondem a botões, elementos de texto e caixas de entrada de texto que podem observar na figura.

Quando terminarmos este exemplo vamos ter os seguintes ficheiros principais:

  • main.cpp – Que nos irá permitir testar o nosso “dialog”;
  • IdDoAutomovelDialog.ui – O ficheiro gerado pelo QtDesigner;
  • IdDoAutomovelDialog.h – A definição de uma classe correspondente ao nosso “dialog”;
  • IdDoAutomovelDialog.cpp – A implementação da classe;

Após a sequência “qmake -project > make automovel.pro > make” muitos outros ficheiros serão gerados, mas os que eu indiquei são os que devemos guardar para recordar :)

Já chega de conversa e vamos começar a construir o nosso pequeno projecto.

#1 Criar directoria para armazenar o projecto

  • Crie a directoria “automovel” numa localização à sua escolha.

#2 Criar o “dialog” utilizando o Qt Designer

  • Inicie o Qt Designer.
  • Seleccione “templates/forms” > “Widget”.
  • Criar os “child widgets” e posicioná-los no formulário, sem grandes preocupações quanto ao alinhamento.

f11

  • Definir as propriedades dos “widgets” recorrendo ao “property editor”. A tabela seguinte resume estas operações.
Widget Propriedade Valor
Label objectNametext label

&Matrícula :”

Line Edit objectName lineEdit
Push Button objectNametext

enabled

okButtonOK”

False (desmarcar)

Push Button objectNametext cancelButtonCancel”
Horizontal Spacer - -
Form(background) objectNamewindowTitle IdDoAutomovelDialogMatrícula”

O nosso “Dialog” fica com este aspecto.

f2

  • Definir os Widgets amigos (Buddies)

- Edit > Edit Buddies

- Clicar em label e arrastar a seta vermelha até lineEdit

- Edit > Edit Widgets (para abandonar o modo “Edit Buddies”)

  • Dispor os Widgets no formulário (layout).

- Seleccionar: label + lineEdit

- Form > Lay Out Horizontally

- Seleccionar: spacer + okButton + cancelButton

- Form > Lay Out Horizontally

- Seleccionar: Form (background)

- Form > Lay Out Vertically

- Form > Adjust Size

f4

  • Alterar a ordem das tabulações (tab order)

- Edit  > Edit Tab Order

f51

  • Pré-Visualizar

- Form > Preview

  • Guardar o “Dialog”

- File > Save As …

- Abrir a pasta do projecto (automovel)

- Guardar com o nome “IdDoAutomovelDialog.ui

#3 Testar o nosso formulário (ainda sem vida)

Já é possível nesta fase testarmos o nosso formulário, embora os botões não funcionem e também não seja feito qualquer tipo de validação aos dados introduzidos pelo utilizador.

Para o efeito podemos fazer o seguinte.

  • Abrir uma consola
  • Entrar na directoria “automovel“  que contém o ficheiroIdDoAutomovelDialog.ui.
  • Criar o ficheiro “main.cpp” com o seguinte código

#include <QApplication>
#include <QDialog> 

#include "ui_IdDoAutomovelDialog.h"

int main(int argc, char *argv[]){
	QApplication app(argc, argv);

	Ui::IdDoAutomovelDialog ui;
	QDialog *dialog = new QDialog;
	ui.setupUi(dialog);
	dialog->show();
	return app.exec();
}

  • Executar a sequencia de comandos (os ls servem para visualizar os ficheiros criados em cada passo)


$ ls
IdDoAutomovelDialog.ui  main.cpp
$ qmake -project
$ ls
automovel.pro  IdDoAutomovelDialog.ui  main.cpp
$ qmake automovel.pro
$ ls
automovel.pro  IdDoAutomovelDialog.ui  main.cpp  Makefile
$ make
/usr/bin/uic-qt4 IdDoAutomovelDialog.ui -o ui_IdDoAutomovelDialog.h
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -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 main.o main.cpp
g++  -o automovel main.o    -L/usr/lib -lQtGui -lQtCore -lpthread
$ ls
automovel      IdDoAutomovelDialog.ui  main.o    ui_IdDoAutomovelDialog.h
automovel.pro  main.cpp                Makefile

#4 Implementar as funcionalidade do formulário

Vamos agora tratar dos seguintes aspectos:

  • Aceitar apenas matrículas válidas
  • Activar o botão “OK” quando a matrícula for válida
  • Definir as acções para os botões “Cancel” e “OK”

Uma das abordagens possíveis consiste em criar uma nova classe que herde as classes QDialog e Ui::IdDoAutomovelDialog.

Teremos que criar os ficheiro IdDoAutomovelDialog.h e IdDoAutomovelDialog.cpp que correspondem à nossa classe derivada, e que vai permitir implementar todas as funcionalidades pretendidas.

IdDoAutomovelDialog.h


#ifndef IDDOAUTOMOVELDIALOG_H
#define IDDOAUTOMOVELDIALOG_H

#include <QDialog>

#include "ui_IdDoAutomovelDialog.h"

class IdDoAutomovelDialog : public QDialog, Ui::IdDoAutomovelDialog{
	Q_OBJECT

public:
	IdDoAutomovelDialog(QWidget *parent = 0);

private slots:
	void on_lineEdit_textChanged();
};
#endif

IdDoAutomovelDialog.cpp


#include <QtGui>

#include "IdDoAutomovelDialog.h"

IdDoAutomovelDialog::IdDoAutomovelDialog(QWidget *parent) : QDialog(parent){
    setupUi(this);

    //Validar a matrícula introduzida ( http://pt.wikipedia.org/wiki/Matr%C3%ADculas_autom%C3%B3veis_em_Portugal )
    QStringList listaMatriculasValidas;
    listaMatriculasValidas << "[A-Za-z]{2,2}[-][0-9]{2,2}[-][0-9]{2,2}";
    listaMatriculasValidas << "[0-9]{2,2}[-][0-9]{2,2}[-][A-Za-z]{2,2}";
    listaMatriculasValidas << "[0-9]{2,2}[-][A-Za-z]{2,2}[-][0-9]{2,2}";
    QRegExp regExp(listaMatriculasValidas.join("|"));
    lineEdit->setValidator(new QRegExpValidator(regExp, this));

    //Definir acções
    connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
    connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
}

void IdDoAutomovelDialog::on_lineEdit_textChanged(){
    okButton->setEnabled(lineEdit->hasAcceptableInput());
}

Vai ser necessário simplificar o código do nosso main.cpp, uma vez que a única classe que é necessário utilizar é a nossa, ou seja, a classe IdDoAutomovel.

main.cpp

#include <QApplication>

#include "IdDoAutomovelDialog.h"

int main(int argc, char *argv[]){
	QApplication app(argc, argv);

	IdDoAutomovelDialog *dialog = new IdDoAutomovelDialog;
	dialog->show();
	return app.exec();
}

#5 Testar o resultado

Vamos repetir o processo apresentado no #3.

  • Abrir uma consola
  • Entrar na directoria “automovel“  que contém agora so ficheiros “IdDoAutomovelDialog.h“, IdDoAutomovelDialog.cpp“,   “IdDoAutomovelDialog.ui” e “main.cpp.
  • Criar o ficheiro “main.cpp” com o seguinte código
  • Executar a sequencia de comandos
$ ls
IdDoAutomovelDialog.cpp  IdDoAutomovelDialog.ui
IdDoAutomovelDialog.h    main.cpp
$ qmake -project
$ ls
automovel.pro            IdDoAutomovelDialog.h   main.cpp
IdDoAutomovelDialog.cpp  IdDoAutomovelDialog.ui
$ qmake automovel.pro
$ ls
automovel.pro            IdDoAutomovelDialog.h   main.cpp
IdDoAutomovelDialog.cpp  IdDoAutomovelDialog.ui  Makefile
torrao@debian:~/Desktop/automovel/v2/automovel$ make
/usr/bin/uic-qt4 IdDoAutomovelDialog.ui -o ui_IdDoAutomovelDialog.h
g++ -c -pipe -O2 -Wall -W -D_REENTRANT ...
...
...
...
... moc_IdDoAutomovelDialog.o    -L/usr/lib -lQtGui -lQtCore -lpthread
$ ls
automovel                IdDoAutomovelDialog.o   Makefile
automovel.pro            IdDoAutomovelDialog.ui  moc_IdDoAutomovelDialog.cpp<a href="http://gracianotorrao.wordpress.com/2009/01/14/qt-creator/" target="_blank">
IdDoAutomovelDialog.cpp  main.cpp                moc_IdDoAutomovelDialog.o
IdDoAutomovelDialog.h    main.o                  ui_IdDoAutomovelDialog.h<span style="color:#000000;">
<pre>

Conclusão

É relativamente simples o processo de criação de uma pequeno formulário, podendo agora este ser facilmente adaptado a outras situações específicas, bastando adicionar novos widgets, validações e acções.

O código fonte fica disponibilizado neste link.

Agradeço o feedback daqueles que seguirem este pequeno tutorial.

Uma alternativa à utilização da linha de comandos poderá ser o Qt Creator ( ver artigo anterior ), tal como mostrado na imagem.

qtcreatorscreeshot

No próximo artigo vou apresentar uma forma de escrever o mesmo programa sem recorrer ao Qt Designer.

Boa sorte :)

seguinte

10 Respostas para “Como criar um “Dialog” utilizando o Qt Designer?”

  1. Rodrigo Diz:

    Parabéns cara, ótimo tutorial!

  2. Rodrigo Diz:

    Uma dúvida, ao trabalhar com slots e signals via qtcreator, ele não mostra o código que ele gerou (queria aprender visualizando o código gerado).

    • Graciano Torrão Diz:

      Seo Dialog se chamar myDialog então vias ter sempre os seguintes ficheiros (entre outros):
      - mydialog.h
      - mydialog.cpp
      - mydialog.ui

      Após a compilação este mydialog.ui é transformado pelo UIC( http://doc.trolltech.com/4.5/uic.html ) num ui_mywidget.h.
      Este último contém a classe que é utilizada para gerar a inferface com o utilizador.

      Caso tenha criado os SLOTS/SIGNALS no QtDesigner podes encontrar o código gerado neste ficheiro.

      Eu prefiro nunca fazer isto dessa forma e trato dessa parte no construtor da classe, logo a seguir a …
      ui->setupUi(this);
      connect(ui->objecto, SIGNAL(clicked()), this, SLOT(exp1()));

  3. Rodrigo Diz:

    Ex: utilizando o botão “Edit signal/slots (F4) para ao clicar em um botão ele “limpar um “lineedit”, é só clicar no botão e arrastar para o lineedit e

  4. Rodrigo Diz:

    Cara, antes de ler sua resposta, achei essa classe e vi que ele gera o código nela, mesmo assim valeu mesmo! Gerar o código via qtcreator achei bem interessante, pois desta forma ganhamos tempo para trabalhar mais com o que é mais importante.

  5. Rodrigo Diz:

    Completando: Estou me referindo a clicar os SLOTS/SIGNALS, via interface qtdesigner, pois assim temos mais tempo para lidar com as outras questões do programa.

  6. Gil Diz:

    Olá Graciano!

    Infelizmente seu exemplo não funcionou em minha máquina. Quando dou um make para testar o formulário (ainda sem vida), obtenho a seguinte resposta do console:

    /usr/bin/uic idDoAutomovelDialog.ui -o ui_idDoAutomovelDialog.h
    g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/default -I. -I/usr/include/QtCore -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtGui -I/usr/include -I. -I. -I. -o main.o main.cpp
    main.cpp:2:19: error: Qdialog: Arquivo ou diretório não encontrado
    main.cpp:4:36: error: ui_IdDoAutomovelDialog.h: Arquivo ou diretório não encontrado
    main.cpp: In function ‘int main(int, char**)’:
    main.cpp:9: error: ‘Ui’ has not been declared
    main.cpp:9: error: expected `;’ before ‘ui’
    main.cpp:10: error: invalid use of undefined type ‘struct QDialog’
    /usr/include/QtGui/qwindowdefs.h:38: error: forward declaration of ‘struct QDialog’
    main.cpp:11: error: ‘ui’ was not declared in this scope
    main.cpp:12: error: invalid use of undefined type ‘struct QDialog’
    /usr/include/QtGui/qwindowdefs.h:38: error: forward declaration of ‘struct QDialog’
    make: ** [main.o] Erro 1

    O que eu esqueci de configurar?

  7. Gil Diz:

    Era isso! Não acredito que tenha sido essa besteira… E eu imaginando mil coisas! Bom, valeu cara!


Deixar uma Resposta