DanDomin << Tutoriais << Qt << Tipos de Janelas do Qt
Tipos de Janelas do Qt
ANTERIOR Página Inicial O Poder Gráfico do Qt Designer
Criado em 28/09/2010 às 16:40
Nesta página, falarei um pouquinho sobre os tipos de "janelas" que encontramos no Qt. Também falarei sobre "separação" do seu código para uma melhor organização. Se você abrir o Qt Creator ou o Qt Designer você terá que escolher logo de cara, qual é o template (modelo) que você usará. Tente você mesmo, você verá três opções basicamente:
Eu diria que no nível de complexidade, nós poderíamos organizá-los do mais simples para o mais complexo da seguinte forma: Widget, Dialog, MainWindow. Nada mais justo que começarmos pelo mais simples.
Você já conheçeu as Widgets das páginas anteriores, QLabel, QPushButton, QLineEdit. Você viu até um caso em que um botão estava dentro de uma label. Nesse caso, será que não poderíamos pegar a label, e seu filho botão, e chamá-los de uma unica widget? Tipo uma nova classe(widget) chamada QLabotao! Sim, nós poderíamos, e desse modo podemos criar nossas proprias widgets, compostas por outras widgets. Isso será exemplificado mais adiante.
E o Dialog? O Dialog é uma janela que tem como objetivo pegar/receber informações de escolha do usuário. Exemplos de dialogs: Janela de tipo de fonte a ser usada num editor de texto, janela de abertura de arquivo, janela de salvamento de arquivo, janela de cores. Geralmente dialogs servem como auxílio à tarefas de uma janela principal e tem dois botões, o aceitar e o cancelar.
Enfim, MainWindows são janelas principais do programa. É a janela que manda no programa, ela chama dialogs diversas vezes e quando é fechada o programa acaba. Ela tem mais algumas propriedades como statusbar, toolbars, docked windows entre outras..
Para criarmos novas Widgets, novos Dialogs ou novos MainWindows nós vamos, inicialmente, criar classes que herdam daquelas. Então é importante saber que herdaremos nossas novas classes das já existentes:
QObject-QWidget
QObject-QWidget-QDialog
QObject-QWidget-QMainWindow
Veja que o proprio caminho de heranças sugere que as classes mais diferenciadas QDialog e QMainWindow sejam mais complicadinhas que a QWidget.
Figura Esquemática 1. Classes do Qt que já vimos até agora (Heranças).
Você perceberá que ao fazer nossas próprias coisas (widgets, dialogs ou mainwindows), é sempre bom dividir nossa fonte em arquivos header e arquivos source, com isso o código fica mais organizado e entendivel. Vejamos então, um exemplo de uma Widget criada por nós, seguido do comentário do código. Mas antes, o resultado:
Código 6. Código source principal(main.cpp).
#include <QApplication> 	//QObject-QCoreApplication-QApplication
#include "nossawidget.h"	//"QObject-QWidget-"nossawidget
NossaWidget janela;
Tudo começa na função main (Código 6), onde criamos a nossa classe do tipo NossaWidget, o que acontece nesse momento? a construtora da nossa classe é chamada! Construtora essa que tem seu protótipo dentro do header "nossawidget.h"(Código 7) e sua implementação dentro do arquivo source "nossawidget.cpp"(Código 8, implementados abaixo)
Código 7. Header da nossa classe(nossawidget.h).
#ifndef NOSSAWIDGET_H
#define NOSSAWIDGET_H
#include <QWidget>			//QObject-QWidget
class NossaWidget : public QWidget
NossaWidget(QWidget *parent = 0);	//protótipo da função construtora
Perceba que nosso header está "protegido contra duplicação" nas diretivas #ifndef/#define/#endif (senão estiver definida, defina, fim do if), precisamos incluir a classe QWidget porque nossa classe vai vir dela. O parâmetro da nossa construtora é inicializado com o valor zero porque, como vamos chamá-la do main, podemos criá-la sem parâmetros e não será filha de ninguém.
Código 8. Source da nossa classe(nossawidget.cpp).
#include <QLabel>           //QObject-QWidget-QFrame-QLabel
#include <QPushButton>      //QObject-QWidget-QAbstractButton-QPushButton
#include <QVBoxLayout>      //QObject-QLayout-QBoxLayout-QVBoxLayout
#include <QHBoxLayout>      //QObject-QLayout-QBoxLayout-QHBoxLayout
#include <QLineEdit>        //QObject-QWidget-QLineEdit
#include "nossawidget.h"    //Para ele saber de quem você está falando
NossaWidget::NossaWidget(QWidget *parent) : QWidget (parent)
QLabel *label = new QLabel("Insira o seu Nome:");
QPushButton *botao = new QPushButton("Ok");
QLineEdit *linha = new QLineEdit;
QVBoxLayout *layoutV = new QVBoxLayout(this);
QHBoxLayout *layoutH = new QHBoxLayout();
layoutH->addWidget(label);
layoutH->addWidget(linha);
layoutV->addLayout(layoutH);
layoutV->addWidget(botao);
QObject::connect(botao, SIGNAL(clicked()), this, SLOT(close()));
No arquivo source da nossa widget, 3 widgets e 2 layouts são criados e o botão é conectado. Você já é capaz de entender a suruba dos layouts ali sozinho(a) mas, para judar, dê uma olhada na figura abaixo:
A linhas da figura acima representam:variável "janela" do main.cpp, Layout Vertical da nossa classe aplicado a quem o chamou (this = variável janela, do main.cpp) e Layout Horizontal da nossa clase. O "this" ali ta dizendo: O layout vertical vai ser aplicado a quem chamou a construtora (variável janela, no main), Quando for clicado, o botão vai dar um "close()" em quem o chamou (variável janela, do main.cpp).
Para fazer um dialog diferente dos padrões (como o de abertura de arquivo, ou até algumas mensagens de notificação), o processo é o mesmo mas existe uma diferença sutil nas conexões dos botões de um Dialog. Acompanhe o código do mesmo exemplo da Widget para um Dialog:
Código 9. Arquivo source principal(main.cpp).
#include "nossodialog.h"	//"QObject-QWidget-QDialog-"nossodialog
NossoDialog dialog;
Código 10. Header do nosso dialog(nossodialog.h).
#ifndef NOSSODIALOG_H
#define NOSSODIALOG_H
#include <QDialog>			//QObject-QWidget-QDialog
class NossoDialog : public QDialog
NossoDialog(QWidget *parent = 0);	//protótipo da função construtora
Já aproveitando o balanço do busão vou mostrar, na implementação do source code do nosso dialog, o uso do layout grid (QGridLayout). Você já viu que o QHBoxLayout organiza as widgets horizontalmente e que a QVBoxLayout organiza as widgets verticalmente. O layout em grid considera um esquema de linhas e colunas, como numa matriz, acompanhe abaixo:
Código 11. Arquivo source do nosso dialog(nossodialog.cpp).
#include <QGridLayout>      //QObject-QLayout-QGridLayout
#include "nossodialog.h"    //Para ele saber de quem você está falando
NossoDialog::NossoDialog(QWidget *parent) : QDialog (parent)
QPushButton *botaoOk = new QPushButton("Ok");
QPushButton *botaoCan = new QPushButton("Cancelar");
QGridLayout *layoutGrid = new QGridLayout(this);
layoutGrid->addWidget(label, 0, 0); //Linha 0, Coluna 0
layoutGrid->addWidget(linha, 0, 1); //Linha 0, Coluna 1
layoutGrid->addWidget(botaoOk, 1, 0); //Linha 1, Coluna 0
layoutGrid->addWidget(botaoCan, 1, 1); //Linha 1, Coluna 1
QObject::connect(botaoOk, SIGNAL(clicked()), this, SLOT(accept()));
QObject::connect(botaoCan, SIGNAL(clicked()), this, SLOT(reject()));
É importantíssimo frisar o modo com que um dialog é encerrado: Clicando no botão OK, ou CANCELAR. Enviando a mensagem de volta (para sua MainWindow) ACCEPTED ou REJECTED. Abaixo está uma representação do layout grid:
O uso dos layouts foi para simples demonstração, você pode usar o Layour que quiser. A criação de MainWindows vai ficar para páginas posteriores porque envolve outros conceitos. Calma que jájá faremos exemplos graficamente!, é importante saber oque acontece behind the scenes.
Crie uma classe derivada de uma QLineEdit ("MeuLineEdit"). Desenvolva uma função construtora para sua classe de forma que ela seja inicializada com um texto inicial, sem usar a construtora própria para isso ( MeuLineEdit linha("não vale")).
Que membro você escolheu para fazer essa alteração? (Use o Qt Assistant)
Comentários: Tipos de Janelas do Qt
Nome: Carlos André
2011-02-22 15:06:43, disse:
No exercício 2, para colocar o texto inicial....usei o construtor sobrecarregado (dentro da implementação do construtor da minha classe):
podia ser assim?
2011-02-23 13:59:08, disse:
Você pode usar o construtor padrão da QLineEdit (como você fez) da seguinte forma:
class MeuLineEdit : public QLineEdit
MeuLineEdit(const QString &contents);
MeuLineEdit::MeuLineEdit(const QString &contents) : QLineEdit(contents)
e no main simplesmente chamar
MeuLineEdit linha("Texto inicial");
linha.show();
Dessa forma a sua construtora só manda o argumento string para a construtora da mãe e dps disso não faz nada.
Mas também dá para fazer de um jeito que não usa a construtora padrão da QLineEdit que aceita uma string. Que seria apenas fazendo
MeuLineEdit(); //construtora que não recebe argumento
MeuLineEdit::MeuLineEdit() : QLineEdit()
this->setText("Texto inicial");
MeuLineEdit linha;
Na vedade ambos os jeitos passam pelas 2 possiveis construtoras de QLineEdit, mas o objetivo é fazer as pessoas verem que um slot (setText) pode ser chamado de qualquer lugar, não necessariamente do SIGNAL.
O exercício não tem MUITO a ver com janelas, mas é bom pra familiarizar a pessoa com QT ASSISTANT e tal
Nome: ztwdRegDdlZvPH
2012-08-25 19:09:28, disse:
Welcome to the world of Qt.I wondered why you were tirnyg such an old version of Qt (4.3.3) but I assume that's a type as you mention 4.6.0.You could have avoided all of the issues above by downloading the free MSVC integration plugin (LGLP). It allows you to set environment variables and provides wizards for creating Qt projects with all the libraries, post build steps etc setup for you. It's well worth it. There is no-need to do any of this stuff your self (although in MSVC, you still have to add libraries to the linker if you decide to use the GL or test modules later etc).The biggest problem with Qt+MSVC is that that libraries came built with the free MinGW and the symbols were not compatible (there is a GUI tool called CuteBuilder to automate this process). So the whole thing had to be rebuilt using nmake. But as of 4.6, Qt now provide an installer with MSVC 2008 binaries pre-built.
Nome: marcos souza
2012-09-02 02:43:12, disse:
meu velho, não sei nem se vc vai ler isso
mas a sua explicação foi a melhor até agora, vc tem mais tutoriais de qt pela net?
2012-12-11 17:56:45, disse:
Olá Marcos, obrigado.
Eu pretendo continuar sim, mas no momento ando ocupado. Quando tiver mais tempo vou continuar com os tutoriais.