Você está na página 1de 25

Qt

Qt é uma biblioteca de classes para a linguagem de programação C++,


além disso ela também pode ser definida como um conjunto de ferramentas
para escrever programas com interfaces gráficas e multiplataforma. Usando
a filosofia "Escreva uma vez, Compile em qualquer lugar" o Qt traz uma
infinidade de APIs, que podem ser usadas para diversos fins, tanto para
criação de interfaces gráficas como já comentado antes quanto para
tratamento de strings, manipulação de arquivos, criação de objetos OpenGL
e diversas outras possibilidades, isso é possivel pois o QT herda toda a
eficiência do C++ e seus recursos.

Uma curiosidade interessante é que o QT é a biblioteca base do KDE, boa


parte dos aplicativos escritos para o KDE tem o seu código fonte escrito em
QT. A União QT/KDE fez com que os dois crescessem juntos de forma
surpreendente.

Origem do Qt

O Qt começou a ser desenvolvido em 1991 quando Haavard Nord e Eirik


Chambe-Eng decidiram escrever uma "Caixa de Ferramentas" em C++ para
o desenvolvimento de interfaces gráficas de usuários. Erik teve a idéia de
usar " sinais e slots (signals and slots)", simples mas um poderoso
paradigma de programação de interfaces gráficas, Haarvard pegou a idéia e
implementou o código fonte. Em 1993, eles tinham desenvolvido o primeiro
kernel gráfico do QT e foram capazes de implementar os seus próprios
widgets*, no final do ano Haarvard sugeriu que começassem um negócio
juntos para criarem " A melhor caixa de ferramentas gráficas de C++ do
Mundo).

O nome "QT" foi escolhido porque eles acharam a letra "Q" bonita na
Haavard's Emacs font e o "t" foi adicionado para representar "toolkit"(caixa
de ferramentas) inspirado no "Xt" o X Toolkit. A companhia que Haarvard
havia sugerido foi criada primeiramente com o nome "Quasar
Technologies", depois mudou para "Troll Tech" e hoje em dia "Trolltech".
Em maio de 1995 o Qt teve a sua primeira versão publicada, o Qt 0.90, que
poderia ser usado para desenvolvimento tanto em Linux quanto em
Windows, oferecendo a mesma API para as duas plataformas. O QT opera
sob duas licenças, a licença comercial que é requerida para o
desenvolvimento de softwares comercialmente e a free software edition que
é avaliada para o desenvolvimento de software com o código aberto.

* widgets: símbolo gráfico de uma interface que possibilita a interação entre


o usuário e o computador

Instalando o QT

Temos à nossa disposição uma variedade de métodos de instalação do QT,


podendo variar dependendo da distribuição GNU/Linux que está sendo
utilizada.

Como este curso é baseado na distribuição Debian, mostraremos como


instalar o QT utilizando a ferramenta aptitude do debian.

Este curso é baseado no QT3 , portanto instalaremos o memos em 2 passos:

- Passo 1: primeiramente vamos verificar se o QT3 está disponível no


repositório do debian com o comando:

$ aptitude search qt3

Este comando listará todos os pacotes que contenham QT3 no nome,


dentre esse pacotes, os pacotes abaixo listados deverão estar presentes na
saída deste comando:

libavahi-qt3-1

libqt3-headers
libqt3-mt

qt3-apps-dev

libqt3-mt-dev

qt3-assistantq

qt3-dev-tools

qt3-doc

qt3-examples

- Passo 2 : Agora que temos certeza que os pacotes estão disponíveis para a
instalação, basta executar o seguinte comando:

$ su (para você ficar com as permições de root, pra que seja possível
instalação)

# aptitude install libqt3-mt-dev qt3-apps-dev qt3-assistant qt3-dev-tools


qt3-doc qt3-examples

Pronto , Agora o Qt3 está instaldo e poderemos a partir daqui começar a


escrever e compilar algumas linhas de código em QT. Que comece a
Diversão!!!!!!

Começando a Diversão!

Nesta lição vamos mostrar como combinar o basico de C++ com as


funcionalidades do QT para criar pequenas e simples interfaces gráficas e
na próxima lição começaremos a falar um pouco sobre a idéia que originou
o QT, "sinais e slots".

Hello QT
Vamos começar com o Hello QT, um programa simples que irá mostra na
tela uma janela com "Hello QT - Yeah" escrito dentro dela. Primeiro irei
mostrar o código fonte, depois explicaremos linha por linha e finalmente
veremos como compilar o código.

Hello QT:

Antes de partirmos para o entendimento do código. Faremos uma


observação, no decorrer do curso você verá que os fontes dos programas
estão como imagens. Isso não é para dificultar o aprendizado, muito pelo
contrário. Estamos acostumado com o famoso "copy and paste", dessa
maneira somos forçados a escrever o código no editor de texto e assim
vamos entender e aprender melhor.

Entendendo o código

Nas linhas 1 e 2 estamos incluindo as classes QApplication e QLabel, são


classes do qt, mais abaixo falaremos sobre elas.
Na linha 5 é um objeto QApplication que gerencia os recursos do programa.

O QApplication requer os argumentos argc e argv porque o QT suporta


alguns argumentos em linha de comando, ou seja o QT aceita que sejam
passados parâmetros ao programa na sua chamada.

Na linha 6 é criado o *widget QLabel que irá mostrar "Hello QT - Yeahh!"

Na linha 7 é feito com que a (label) que foi criado na linha 6 se torne o
widget principal, para que quando o usuário fechar a janela (clicando no X
da barra de titulo da janela,por exemplo) o programa termine, casa não seja
feito essa ligação, que torna a label a widget principal (main widget) quando
o usuário fechar a janela o programa ainda continuaria rodando
ocultamente. Em qualquer programa em que se deseja que o programa seja
encerrado ao fechar uma janela, essa janela deve ser a widget principal,
caso contrario o programa continuará em execução.

Na linha 8 é feito com que a label se torne visível, pois todos os widgets que
são criados, por padrão, são ocultos, ou seja não são mostrados na tela.

Na linha 9 é passado o controle do programa, ou seja , é neste ponto que o


programa entra em stand-by esperando a ação do usuário, clicks do mouse
ou ações do teclado.

Vamos Compilar!

Agora que já escrevemos o primeiro código em QT, vamos aprender a


compilá-lo, para gerar o executável desse código, assim então poderemos
visualizar o resultado.

A primeira coisa que devemos fazer é: Criar um diretório "pasta" com o


nome "hello" no qual salvaremos o código fonte com o nome de "hello.cpp".

Agora que já criamos o diretório e salvamos o código vamos usar o qmake


em 3 etapas para compilar.
1ª etapa: Vamos criar o arquivo "hello.pro" que no caso é a plataforma
independente do projeto, para criar o "hello.pro" vamos executar o seguinte
comando:

# qmake -project

2ª etapa: Agora que criamos o arquivo "hello.pro" vamos criar o mekefile


para a plataforma específica a partir do "hello.pro" com o comando:

#qmake hello.pro

3ª etapa: Com o makefile criado vamos executar o comando make para


compilar o código.

Pronto, depois de executar todas as etapas o código foi compilado e o


arquivo hello foi gerado, esse arquivo é o executável do código fonte.

Vendo o Resultado

Com o código compilado e o executável gerado vamos ver como ficou a


cara do osso programa.

Para rodarmos o programa basta executar o arquivo executável com o


seguinte comando:

$./hello

A cara do programa será algo parecido com essa abaixo, dependendo de


qual for o tema Desktop que esta sendo utilizado.
QButton

Nesta lição iremos substituir o rótulo (label) por um botão que estará ligado
a um determinado evento, que neste caso terá a função de encerrar o
aplicativo.

Um botão é um elemento comum de interface com usuário em toda


plataforma: você clica e algum evento acontece. Em Qt, os botões são
representados pela classe QPushButton, que é uma subclasse de QButton,
que por sua vez é uma subclasse de QWidget, a classe básica de todos os
elementos GUI deQt.

Entendendo o código

#include <qfont.h>

Como este programa usa o QFont, então devemos incluí-lo no header.


QPushButton quit( "Quit", 0 );

Dessa vez nosso botão vai dizer "Quit", o que é exatamente a função dele:
fechar o programa quando clicado.Passamos o parâmetro 0 para dizer que o
botão é a janela primária.

quit.resize( 75, 30 );

Aqui vamos alterar o tamanho do nosso botão. Poderíamos fazer isso com o
QFontMetrics também.

quit.setFont( QFont( "Times", 18, QFont::Bold ) );

Aqui escolhemos uma nova fonte para o botão, neste caso uma fonte da
família Times com 18 pontos e em negrito.

Também podemos mudar a fonte padrão usando


"QApplication::setFont()".Teste isso depois!!

QObject::connect( &quit, SIGNAL(clicked()), &a, SLOT(quit()) );

Agora vamos ver a parte mais importante desta lição.

Vamos dar uma olhada nessa tal de SINAIS e SLOTS (Signal and Slot), que é
necessário para entender o que acontece nesse método.
Sinais e Slots são usados para a comunicação entre objetos Qt. Sempre que
o botão é clicado ele envia um sinal, neste caso um sinal clicked(). Este sinal
significa que o objeto foi clicado e o objeto fica a espera de alguma resposta
referente a essa ação.

A partir daí outros objetos que pertencem ao programa podem se conectar


com o widget para serem avisadas toda vez que o botão for clicado. Isso é
feito através de um slot que tem a função de responder a um sinal em
particular.

Sinais e Slots são conectados através do método QObject::connect(), em


que recebe como parâmetros de entrada o objeto que emite o sinal "&quit",
o sinal que é emitido "SIGNAL(clicked())", o objeto que recebe o sinal "&a" e
o slot onde este sinal é recebido "SLOT(&quit)". Um único sinal pode estar
ligado a vários slots, bem como a recíproca é verdadeira de que um único
slot pode estar escutando vários sinais.

Parent e Child Widgets

Nesta lição vamos falar um pouco sobre Parent Widgets e Child Widgets
(Widgets Pais e Widgets Filhos). Aqui vamos usar um único parent e um
único child para facilitar nosso entendimento.

Vamos dar uma olhada no código abaixo que iremos testar.


Entendendo o código

#include <qvbox.h>

Aqui nós incluimos o header vbox.h, que é a classe de layout que iremos
usar.

QVBox box;

Com esta linha criamos uma caixa (box) em que seu conteúdo será alinhado
verticalmente, ou seja, o QVBox organiza os child widgets em colunas
verticais. Separando-os de acordo com o QWidget::sizePolicy() de cada um
dos child (filhos).

box.resize( 200, 120 );


Aqui setamos o tamanho do box para 200 pixels de comprimento e 120
pixels de altura.

QPushButton quit( "Quit", &box );

Um filho acabou de nascer! (A Child is born)

Diferentemente de como usávamos o QPushButton, aqui neste exemplo o


criamos com o texto "Quit" e com o parent (box). Um child widget (widget
filho) fica sempre em cima do seu parent (pai).

Quando o child é mostrado, ele é colocado dentro dos limites do seu parent.

O parent widget, neste caso o QVBox, adiciona automaticamente o child no


centro do box. Como nada mais foi adicionado, o botão ocupa todo o espaço
que o parent possui.

box.show();

Quando o parent widget é mostrado, com a linha mostrada acima, ele irá
mostrar também todos os seus filhos (children), exceto aqueles que foram
feitos com o parâmetro QWidget::hide().

Agora que já vimos as parte do código, vamos entender o que acontece de


uma maneira mais conceitual. Como já haviamos dito, o botão não preenche
mais o widget inteiro. Isso acontece porque agora existe um widget em um
nivel mais alto, o qual é responsável por organizar o tamanho do botão e
sua posição
MyWidget

Nesta lição iremos ver como criar nosso próprio Widget, como controlar o
tamanho e dar nome a ele.

Vamos agora ver o código com o qual iremos trabalho nessa lição:
Entendendo o código

class MyWidget : public QWidget

public:

MyWidget( QWidget *parent=0, const char *name=0 );

};
Aqui nós criamos a nova classe. Como esta classe descende da classe
QWidget, a nova classe é um widget e dessa maneira, será nossa
mainwindow, ou seja, será nossa janela principal e as outras que iremos
adicinar serão seus filhos (child).

Esta classe contém apenas um membro, o construtor. Aqui ele, construtor, é


o padrão do Qt widget. Caso queria adicionar mais widgets, é necessário
sempre incluir um construtor similar.

O primeiro argumento é o parent widget (widget pai). Como aqui estamos


querendo que esse nosso widget seja o mainwindow (top-level window), o
parâmetro parent do construtor é especificado como null (0).

O segundo argumento é o nome do nosso widget. Vale lembrar que esse


nome não é aquele que aparece na barra de título do nosso widget ou o
nome do botão. Na verdade é o nome associado ao widget com o qual
poderemos referenciá-lo.

MyWidget::MyWidget( QWidget *parent, const char *name )

: QWidget( parent, name )

É aqui que começa a implementação do construtor. Aqui nós estamos


passando o parent e o nome para o construtor QWidget.

{
setMinimumSize( 200, 120 );

setMaximumSize( 200, 120 );

Como esse widget que criamos ainda não sabe lidar com alteração de
tamanho, aqui nós definimos o tamanho máximo e mínimo. Esse "problema"
nós iremos aprender a resolver na próxima lição, onde o usuário poderá
alterar o tamanho do widget.

QPushButton *quit = new QPushButton( "Quit", this, "quit" );

quit->setGeometry( 62, 40, 75, 30 );

quit->setFont( QFont( "Times", 18, QFont::Bold ) );

Aqui vamos criar e chamar o nosso widget filho (child widget) e como o
estamos criando dentro do MyWidget, ele será referenciado como this.
Antes definimos o que irá aparecer escrito no botão (Quit) e depois o nome
do botão (quit).

Note que quit é uma variável local do construtor. MyWidget não mantém
nenhum contrle sobre essa variável, mas o Qt sim e dessa forma ela será
deletada assim que o MyWidget encerrar. É dessa forma que o MyWidget
não precisa de um destrutor.
O setGeometry() faz o mesmo que o resize() da lição anterior.

connect( quit, SIGNAL(clicked()), qApp, SLOT(quit()) );

Como a classe MyWidget não conhece o objeto da aplicação, ele precisa ser
conectado o ponteiro para a aplicação, qApp.

O Widget é um componente de um software e deve saber o mínimo possível


a respeito do ambiente em que está sendo usado. Para que assim possa ser
geral e reusado o máximo possível.

E caso o Widget saiba o nome do objeto da aplicação, irá quebrar esse


princípio. Dessa forma o Qt fornece um alias para ele, qApp, para o casos
em que algum componente precise se comunicar com o objeto da aplicação.

int main( int argc, char **argv )

QApplication a( argc, argv );


MyWidget w;

w.setGeometry( 100, 100, 200, 120 );

a.setMainWidget( &w );

w.show();

return a.exec();

Aqui nós instaciamos nosso novo filho (child), o coloca para ser o main
Widget e executa a aplicação.

A diferença dessa lição para a anterior é o mode em que implementamos o


child, que nos permite ter maio flexibilidade e reusabilidade.

Tente mudar o tamanho do nosso widget e incluir mais botões para ver o
resultado.

Conectando widgets

Nesta lição vamos aprender a criar e conectar widgets usando o signal e


slots. Teremos algo como na figura abaixo:
Agora vamos ver o código que gerou esse widget:

Entendendo o código

#include <qapplication.h>

#include <qpushbutton.h>

#include <qslider.h>
#include <qlcdnumber.h>

#include <qfont.h>

#include <qvbox.h>

Aqui temos três novos includes que não tinhamos visto antes:

qslider.h : Precisamos dele pois utilizamos os Wigets que ele implementa,


QSlider;

qlcdnumber.h : Da mesma forma que o qslider, iremos utilizar o widget


QLCDNumber;

qvbox.h : Para utilizarmos o layout automatico do Qt.

class MyWidget : public QVBox

public:

MyWidget( QWidget *parent=0, const char *name=0 );

};

MyWidget::MyWidget( QWidget *parent, const char *name )

: QVBox( parent, name )

MyWidget é derivado do QVBox, diferentemente dos outros exemplos que


era do QWdiget. Dessa forma, usamos o layout do QVBox que irá alinhar os
widgets filhos verticalmente. Como a alteração de tamanho é suportada
pelo QVBox, logo nosso MyWidget também terá essa característica.
QLCDNumber *lcd = new QLCDNumber( 2, this, "lcd" );

Aqui chamamos o construtor do objeto lcd, que descende da classe


QLCDNumber. Está é uma classe que mostra um display LCD com números.
Passamos como parâmetro o 2, que irá definir que iremos mostrar um
número de doi dígitos e que será filho de this, que nada mais é que nosso
MyWidget. E esse nosso objeto se chamará "lcd".

QSlider * slider = new QSlider( Horizontal, this, "slider" );

slider->setRange( 0, 99 );

slider->setValue( 0 );

A classe QSlider é simplesmente um slider que serve para ajustar algum


valor dentro de uma faixa determinada. Com essas linhas mostradas acima,
nós criamos um slider horizontal, setamos sua faixa para número entre 0-99
e colocamos como valor inicial o 0.

connect( slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)) );

Agora vamos usar o signal/slot para conectar nosso slider com o displey de
LCD. Faremos isso colocando como signal o método que altera o valor do
slider (valueChanged(int)), porque este sinal é conectado ao LCD. Como slot
colocamos o display do nosso LCD (display(int)), o qual é chamado quando o
signal é produzido.

Blocos de Widgets

Nesta lição iremos ver como encapsular dois widgets dentro de um novo
componente e pela primeira vez vamos usar um widget criados por nós
como um widget filho (child widget). Veja abaixo como vai ficar nosso
widget.

Agora vejamos o código que gerou nosso widget acima:


Entendendo o código
class LCDRange : public QVBox

public:

LCDRange( QWidget *parent=0, const char *name=0 );

};

O widget LCDRange é um widget sem aplicação (API), ele contém somente


um construtor. Um widget dessa maneira não é muito útil, mas iremos
adicionar algumas aplicações depois.

LCDRange::LCDRange( QWidget *parent, const char *name )

: QVBox( parent, name )

QLCDNumber *lcd = new QLCDNumber( 2, this, "lcd" );

QSlider * slider = new QSlider( Horizontal, this, "slider" );

slider->setRange( 0, 99 );

slider->setValue( 0 );

connect( slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)) );

Essa parte veio do nosso MyWidget da lição anterior. A única diferença é


que tiramos o botão e a classe foi renomeada.
class MyWidget : public QVBox

public:

MyWidget( QWidget *parent=0, const char *name=0 );

};

O nosso MyWidget também não contém, aplicações, a não ser seu


construtor. Podemos fazer uma analogia como se nosso MyWidget
funcionasse como uma classe abastrata, para quem já programou em java.
Ou seja, as aplicações da nossa classe serão implementadas em outras
classes.

MyWidget::MyWidget( QWidget *parent, const char *name )

: QVBox( parent, name )

QPushButton *quit = new QPushButton( "Quit", this, "quit" );

quit->setFont( QFont( "Times", 18, QFont::Bold ) );

connect( quit, SIGNAL(clicked()), qApp, SLOT(quit()) );

O nosso botão, que costumava estar onde aqui temos LCDRange, está
separado para que possamos ter um botão "Quit" e muitos objetos
LCDRange.

QGrid *grid = new QGrid( 4, this );


Aqui criamos o objeto QGrid com 4 colunas. O widget QGrid organiza
automaticamente os widgets filhos em linhas e colunas. Podemos também
especificar esses parâmetros e o QGrid vai descobrir se um novo widget
filho foi criado e irá inserí-lo na grade.

for( int r = 0 ; r < 4 ; r++ )

for( int c = 0 ; c < 4 ; c++ )

(void)new LCDRange( grid );

Aqui temos um loop para gerar as 4 linhas e 4 colunas.

Criamos um LCDRange 4X4 e todos são widget filhos do objeto QGrid.