Nesse post vou falar um pouco sobre o básico do QT, de forma que depois de ler você já saia programando interfaces relativamente complexas. Por essa razão, esse tutorial não vai explicar muitos detalhes. O QT possui algumas coisas estranhas para quem não está acostumado, simplesmente aceite-as :P. Se você nunca viu QT, este tutorial aqui é um bom começo :)

Pré-requisitos: saber C e pelo menos o básico de orientação a objetos em C++ (como criar classes, subclasses), saber o que é um makefile
Pós-requisitos: saber criar uma interface em QT e interagir com esta interface

QT é um framework multi-plataforma (entre eles windows e linux) para desenvolvimento de aplicações. Seu sucesso está no desenvolvimento de interfaces gráficas, porém também podemos usá-la para outros fins. O QT já está na versão 4 e tudo o que você precisará saber está nessa página (no caso da versão 4.2):

http://doc.trolltech.com/4.2/index.html

Parte 1: Instalação

No link anterior há instruções de instalação, mas se sua distro também tem apt-get e não quer perder tempo já pode instalar os seguintes pacotes: libqt4-dev, qt4-designer, qt4-dev-tools e qt4-qtconfig.

Parte 2: Overview das Classes

O QT é baseado em classes. A nomenclatura é bem direta: um label (texto na janela) é um objeto da classe QLabel, um botão é um objeto da classe QPushButton. Obviamente, há também classes não relacionadas a interface gráfica, como QString para representar uma string, QImage para representar uma imagem. Os widgets (widget denota qualquer componente de interação com usuário numa interface gráfica) são subclasses de QWidget e portanto herdam alguns métodos de QWidget como setVisible, setSize, etc. A maioria desses widgets possuem como parâmetro do construtor o widget a qual ele está conectado.

Ok Rafael, mas onde o aplicativo começa para que eu possa ir adicionando os widgets? Como interagir com esses widgets? Bem, chegaremos lá.

Parte 3: Rodando um aplicativo em QT

Onde começar a interface gráfica? Obviamente do main :) mas para iniciar a interface gráfica é suficiente (mas não necessariamente :)) que você deixe seu main mais ou menos assim:
#include <QApplication>
#include <QtGui>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QPushButton *pb = new QPushButton(”clica em mim”);
pb->show();
return app.exec();
}

qt0.png

Quando executar esse programa, uma janela é aberta com um botão com o texto “clica em mim”. Também nada acontece quando você clica. Mas como compilar esse código?

Parte 3.1: Compilando

Essa é a parte estranha :) você poderia pensar que para compilar seria: g++ teste.cpp -lQT… bem, não é assim. É necessário incluir várias opções na compilação e para facilitar eles fornecem uma ferramenta chamada qmake. O qmake vai gerar um makefile automaticamente para você e quando você fizer make, o seu programa é compilado e seu executável terá o mesmo nome do diretório. Um detalhe é que o qmake vai ler todo o diretório atual e subdiretórios, então o ideal é que quando você criar esses testes, coloque-os em uma pasta especial.

Parte 3.2: qmake

Com o intuito de facilitar a explicação, suponha que o diretório atual se chama “teste”. Para gerar o produto final que queremos (o makefile) é necessário 2 etapas:
1) gerar um arquivo de projeto
2) gerar o arquivo makefile

Para gerar o arquivo de projeto, você deve fazer: qmake -project
Isso criará um teste.pro (lembre-se que teste é o nome do diretório). Esse arquivo contém uma lista de arquivos e opções que fazem parte do seu projeto, mas em geral você não precisa alterá-lo.

Para gerar o makefile, você deve fazer: qmake -makefile. Com isso, será gerado um makefile baseado no arquivo teste.pro.

Resumindo para compilar e executar o programa:
qmake -project
qmake -makefile
make
./teste

Parte 4: Elaborando interfaces maiores

Tudo o que fizemos no aplicativo anterior foi criar uma aplicação QApplication, criar um QPushButton, chamar o seu método show para exibi-lo na tela e mandar executar o aplicativo. Obviamente, queremos uma interface gráfica mais complexa. Como dito anteriormente, os widgets em sua maioria possuem como parâmetro do construtor um widget ‘pai’. Então uma janela com dois botões pode ser criado instanciando um objeto da class QWidget e mais dois objeto QPushButton:

QWidget *widget = new QWidget();
QPushButton *b1 = new QPushButton(widget, “clica em mim aqui”);
QPushButton *b1 = new QPushButton(widget, “oba”);
widget->show();

Isso vai resultar na seguinte interface:

qt1.png

Como vocês podem ver, um botão saiu em cima do outro. Bem, ele não tem um gerenciador automático de layouts (e nem faria muito sentido ter). Mas você pode usar classes como QVBoxLayout para isso. Mas não se preocupe! Você não precisa programar a esse ponto, afinal daria muito trabalho. Para poupar trabalho da criação da interface, existe o qt-designer.

Parte 4.1: QT Designer

Você pode iniciar o qt-designer executando designer-qt4. Deve aparecer uma nova janela perguntando qual tipo de formulário você quer. Escolha Widget (como vimos antes, a janela pode ser um widget). Depois é só arrastar os componentes que quiser no widget, alterar suas propriedades, etc (bem, a interface é bem intuitiva!).

Tente criar uma interface parecida com essa:

qt2.png

Salve (digamos com o nome interface.ui). Esse arquivo .ui é um XML que contém a descrição do seu formulário. A questão é: como gerar um código a partir desse XML que crie a mesma interface correspondente? O primeiro passo é fazer qmake -project novamente. Se você abrir o teste.pro verá algo parecido com isso:

FORMS += interface.ui
SOURCES += teste.cpp

O qmake -project reconheceu que tem um arquivo de formulário no diretório e o acrescentou em FORMS. Quando você fizer qmake -makefile, o makefile terá um comando para converter esse .ui em um .h. No caso de interface.ui, após executar make, será criado um arquivo ui_interface.h (dê uma espiada nele :)).

O ui_interface.h contém uma classe Ui_Form (você pode mudar o nome pelo qt-designer, o padrão do nome do form é Form) com tudo necessário para a criação do widget que você mesmo criou no qt-designer. E o que interessa nessa classe? O método setupUi:

void setupUi(QWidget *Form)

Você passa um objeto QWidget a este método e ele trata de adicionar neste widget todos os componentes que você especificou em suas devidas posições, tamanhos, valores, etc.

Vamos agora mudar o nosso teste.cpp

#include <QApplication>
#include <QtGui>
#include “ui_interface.h”
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QWidget *widget = new QWidget();
Ui::Form form;
form.setupUi(widget);
widget->show();
return app.exec();
}

Pronto, make e já pode executar.

Parte 5: Interagindo com os widgets

O programa anterior exibiu os widgets conforme especificamos no qt-designer, mas ainda não é possível interagir com esses widgets. Como fazer? Para essa interface, vamos fazer três coisas:

1) Quando clicar em ‘here we go’, mudar o QLabel para dizer qual o melhor time do mundo.

2) Quando clicar em ‘quit’, sair do programa.

3) Quando mudar o spinbox ou a barra de rolagem mudar o valor do outro, de forma que ambos apresentem a mesma quantidade.

Parte 5.1: como os widgets interagem

Os widgets se interagem através de sinais. Quando o usuário clica na setinha do spinbox, um sinal é emitido e alguma função registrada para atender esse sinal será chamada. Vá na documentação do spinbox e vejá qual o sinal que é emitido quando o usuário clica na setinha:

http://doc.trolltech.com/4.2/qspinbox.html

Achou?

São dois tipos de sinais e mais 3 herdados de outras classes. Então para interagir com um widget você precisa saber 2 coisas:

1) Onde está o objeto que representa aquele widget
2) Qual o sinal que você quer tratar

Se você olhou o ui_interface.h pôde ver que os objetos estão na classe Ui_Form:

QPushButton *pushButton;
QLabel *label;
QPushButton *pushButton_2;
QSpinBox *spinBox;
QScrollBar *horizontalScrollBar;

Os nomes aqui estão pelo padrão do qt-designer. Mas você pode optar obviamente por nomes mais intuitivos, mudando pela interface do qt-designer :)

Parte 5.2: conectando os sinais

Para registrar uma função que deva tratar um sinal de um widget, utilize a função connect:

connect(widget,SIGNAL(sinal()),this,SLOT(funcao()));

Mas há uma forma que eu pessoalmente achei mais conveniente de usar: a conexão automática. Funciona assim: você especifica na classe que contém o objeto widget em questão um método chamado: on_<widget>_<sinal>(parametros)

E essa função automaticamente já tratará esse sinal emitido por esse widget. Então por exemplo, queremos tratar o sinal valueChanged do objeto spinBox, criamos a função:

void on_spinBox_valueChanged(int value);

Você pode alterar o ui_interface.h para implementar esses métodos, mas NÃO FAÇA ISSO… obviamente porque se você alterar depois a interface do interface.ui, você vai perder o ui_interface.h antigo. Uma solução é criar uma subclasse de QWidget e colocar o Ui::Form form como atributo desse classe. Depois você pode implementar esses métodos nessa subclasse que o QT cuida de registrar as funções.

Parte 6: implementação final

O interface.h:

#ifndef INTERFACE_H
#define INTERFACE_H

#include “ui_interface.h”
#include <QtGui>
#include <QWidget>

class Interface : public QWidget{
Q_OBJECT

public:
Interface(QWidget *parent = 0) : QWidget(parent) {
form.setupUi(this);
}
private slots:
void on_pushButton_clicked(bool checked) {
form.label->setText(”XV de Piracicaba”);
}
private:
Ui::Form form;
};

#endif

e o teste.cpp:

#include <QApplication>
#include <QtGui>
#include “interface.h”

int main(int argc, char *argv[]) {
QApplication app(argc, argv);
Interface inter;
inter.show();
return app.exec();
}

O resto fica como exercício :) verificar os sinais do spinBox e do horizontalScrollBar para sincronizá-los.

Vou contar agora uma das coisas mais sem noção (e legais, porque saí vivo claro) que já vivenciei.

Parte 1

Bem, semana passada estive em Belo Horizonte participando da maratona. Na programação dos 2 dias de eventos, tinha um evento surpresa: um rally à pé, organizado pelo hotel fazenda em que os competidores estavam hospedados. O que era exatamente eu não sabia, mas eu fui. Tudo começou como não era para ter começado: pegamos antes um baita trânsito no caminho do hotel fazenda, por causa de um ônibus que trombou, atrasando o rally por umas 2 horas. Depois que todos se reuniram para começar o rally, a divisão dos times foi efetuada (umas 8 equipes de 15 pessoas cada). Cada equipe teria que seguir então um roteiro que consistia em passar por determinados pontos, onde uma pessoa de vermelho fazia uma pergunta de conhecimentos gerais. Nos primeiros 20 minutos esses pontos eram dentro do hotel. Nos outros 40 minutos eram fora do hotel. Depois as coisas começaram a ficar mais interessantes: tínhamos que entrar na mata, estava anoitecendo e, para piorar, nuvens pesadas cobriam todo o céu anunciando uma chuva que estava por vir. Bem, eu não desisti :)

Parte 2

Iniciando a caminhada na mata, não tínhamos grandes problemas. Tínhamos uma única lanterna, dessas de R$1,99, que só ilumina o seu próprio pé e para 15 pessoas! Mas não era muita preocupação, pois imaginava que em 10 minutos já estaria de volta ao hotel. Mero engano, a noite chegou, a tempestade começou (sem luz de lua) e não tinha mais como desistir :D

No começo era relativamente fácil, tínhamos até algumas cordas para segurar. Mas depois, todos os grupos se perderam. Chegamos a um ponto que não sabíamos se estávamos seguindo na trilha certa e um dos caminhos não tinha mais saída. Momento em que até alguns ligaram para a polícia. E se desistisse? Teria que ficar até o amanhecer para poder achar o caminho. Ninguém mais queria de fato vencer o rally, queria apenas voltar para o hotel. E a trilha naquelas condições não era nada fácil. Tínhamos que formar uma corrente para não se perder um do outro. Muitas vezes escorregando e tendo que se segurar nas árvores para não derrubar quem estava atrás. Tínhamos que passar por algumas cercas com arame farpado. A trilha também tinha alguns cipós, e era preciso praticamente arrancá-los com os pés para prosseguir, troncos de árvore. A lanterninha só servia para iluminar o script que nos deram, mas que mal dava para ler devido à chuva. Em alguns momentos, a corrente se quebrava, e o perigo era iminente. Quando dava um relâmpago, todo mundo enxergava tudo e de repente ficávamos cegos por uns 5 segundos.

Trilha
Reconstituição do que eu conseguia enxergar naqueles momentos

Parte 3

Depois de cerca de 2 a 3 horas perdidos na mata, encontramos alguém para nos ajudar a pegar o caminho de volta. E em boa hora, pois as lanterninhas já haviam pifado. Ver a luz do hotel foi uma alegria tão grande, que me machuquei num galho empolgado para chegar lá :D Chegamos às 21h30 no hotel. Bem, eu não ganhei a maratona, mas ao menos meu time ganhou o rally :D

Bem, minhas férias não estão sendo muito boas. Estou com uma forte gripe/tosse desde 7 dias atrás! Mas ainda assim, faço algumas coisas no computador. Joguei um pouco de Priston Tale, estou fazendo um joguinho em flash (post futuro). Dessa vez, após notar que dava para acertar qual desenho animado estava passando somente atentando pelo estilo do desenho, desenhei hugo seguindo um estilo de 2 desenhos animados bem conhecidos. Adivinhem quais são! :) anims.jpg

Essa eu peguei daqui: freakcode que por sua vez já pegou de outro lugar =D

history|awk '{print $2}'|awk 'BEGIN {FS="|"} {print $1}'|sort|uniq -c|sort -rn|head -10

A minha lista de comandos mais usados foi:
146 cd
125 ls
32 convert
27 vim
25 grep
23 exit
19 make
17 ./portmap
16 mplayer
10 ./a.out

Acho que tem um pouco do meu perfil aí :D por exemplo, eu estive fazendo trabalho de sistemas distribuídos (portmap), toco músicas usando o mplayer pelo terminal :P usei muito o convert para converter imagens =] legal

Um dos primeiros jogos que joguei na minha vida, na época em um 286 :), foi o stunts. Era um jogo de corrida muito bom, com pistas milaborantes, com loops, pistas inclinadas, pontes, túneis, entre outros. E tem uma coisa muito legal que falta nos jogos de corrida de hoje em dia: um editor de pista.

stunts.gif

Quem jogava ou quem nunca jogou e quer jogar :) pode conferir downloads desse jogo em: http://www.kalpen.de/stunts/stunts.htm

Para minha surpresa, o track mania é um jogo muito similar ao stunts, incluindo um editor de pistas! Tem 90 pistas para correr sozinho, onde você tenta bater tempos para ganhar medalha de bronze, prata ou ouro. Só o desafio de conseguir ouro em todas elas, já é uma boa diversão. E você também pode jogar via internet ou lan.

O site oficial é este daqui: http://www.trackmania.com/
Tem essa versão gratuita TrackMania Nations que você pode baixar aqui: http://baixaki.ig.com.br/download/TrackMania-Nations-ESWC.htm

tira_duff.jpg

Isso mesmo! Se cuida! BANG! BANG! =P
Mais um desenho tosco pra minha coleção

Nos últimos dias tive que escolher um codec que tocasse tanto no windows quanto no linux. Para isso, testei em 4 windows (incluindo o meu que não tem quase nada instalado) e 2 linux. O codec mpeg4 aparentemente só toca no windows se tiver o divx ou xvid ou 3ivx instalado. O codec msmpeg4v2 (microsoft mpeg 4 parte 2) foi o que tocou tanto em todos os windows como em todos os linux e é uma das opções do mencoder na hora de criar o vídeo. Tem também o Microsoft Video 1 que está presente como codec no windows. Nesse caso, o codifiquei usando o virtual dub e tocou em todos os sistemas também.

Sabe o que eu acho legal da vida? Se você estiver seguindo um caminho na vida e se pergunta “por que estou seguindo esse caminho por tanto tempo?”. O bom é que nunca é tarde para escolher o nosso próprio melhor caminho :)

O que atrapalha são as ‘verdades absolutas’ incrustadas em nossas mentes. Fatos que se tornam verdades e continuam sendo verdades, que com o passar do tempo, continuam sendo mais verdades ainda e nunca nos questionamos sobre a veracidade dessas verdades. Talvez seja hora de pensar diferente. E isso está ficando auto-ajuda demais, então vou parar por aqui mesmo =P

Será que eu gosto de computação? O.o

projtosca.JPG

Deve fazer 1 ano que fiz esse desenho, com uma perspectiva bem maluca =P

Tentei me inspirar nos desenhos de monkey island, que lembra algo assim.