Você está na página 1de 62

Revista QT

Edio 2 Novembro/Dezembro - 2010

Agora com 62 Pginas!

Opera House- Oslo

Aplicaes Hbridas

Instalao do QT para Mac

Tutorial QML

Distribuindo apliaes em Qt para Linux

revistaqt.com

ndice
5 Qt + PHP parte 2
Continuao do tutorial sobre desenvolvimento de aplicaes hbridas (Desktop + Web) usando Qt e PHP.

58 Distribuindo suas aplicaes Qt para Linux 23 Geek & Poke


Charges do Oliver Widder

Dica para distribuir suas aplicaes desenvolvidas em Qt para Linux

24 Criando aplicaes com QT 4.7 no Mac OS X


Tutorial para instalao do Qt SDK no Mac

35 Estilo de codificao Qt

O estilo de codificao adotado pela equipe de desenvolvimento do Qt

41 Tutorial Qml

Traduo do Tutorial de Qml disponvel na documentao do Qt

57 Caixa de Entrada
Respostas a e-mails de leitores.

Carssimosleitores,
Hunstrsmeses,quandoresolvicriarumarevistasobreoQt eujsabiaqueserianoserianadafcil. Pra comear esta seria a minha primeira experincia como editoreprapiorareuestavasozinhonessaempreitada. Com o tempo que sobrava de um emprego em tempo integral e uma famlia numerosa, eu ia escrevendo e como tambm era a minha primeira experincia como diagramador, ia apanhando do BrOffice Draw (programa queusoparaeditararevista).DomeuentusiasmocomoQt vinhaaestmulodequeeuprecisavaparacontinuar. Comapenas24pginas,aprimeiraediodaRevistaQtfoi publicada no dia 8 de setembro deste ano. Eram poucos e umtantoinseguros,maseramosmeusprimeirospassosno sentidodaminhaideia. Dois meses e muito trabalho depois, aqui estou eu de novo, destavezescrevendooeditorialdasegundaediodaRevista Qt, que passa a ter editorias definidas, uma diagramao ligeiramente melhorada continua sendo feita por mim :) e comomesmoobjetivo:compartilharconhecimentosobreQt. Seguindo orientaes do meu amigo Pierre Freire, criei editorias, de acordo com a naturezadecadaartigoaserpublicado. EstasseroasprimeiraseditoriasdaRevistaQt: Iniciar EstaeditoriaserdedicadaaartigosparainiciantesemQt.Sej existisse na primeira edio, os artigos: Apresentando o Qt, Instalao do Qt SDK e Al Qt Creator estariam nesta editoria,porrequereremumconhecimentomuitobsicodoQt.

RevistaQt Novembro/Dezembro-2010 [3]

Laboratrio Artigoscomumnvelmaisaltodecomplexidadeouqueexijam maiores conhecimentos dos leitores sero publicados nesta editoria.OartigoQt+PHPparte1daprimeiraedioum exemplodeartigodestaeditoria.

VersoBrasileira fato: existe pouca documentao sobre Qt em portugus disponvel. No entanto,existe um bom material disponvelem ingls. Nesta editoria sero publicadas tradues da documentaodoQt.

CaixadeEntrada Nesta editoria sero publicados os emails dos leitores, enviados para revistaqt@gmail.com, com as respectivas respostasdadaspeloeditor. Notcias Sendo uma publicao bimestral, se fosse publicar tudo o que acontece precisaramos de uma centena de pginas para notcias. Ento, apenas notcias relevantes para estudantes ou profissionaisdeQtseroconsideradasparaestaeditoria Geek&Poke As charges de Oliver Widder ganham umaseoespecficanarevista. Alm destas, existem planos para outras editorias, como uma que apresente cases de aplicaodoQt. Encerrando este tutorial, agradeo pelas crticas e mensagens de apoio que tenho recebidodesdeolanamentodaprimeiraediodarevista. Umgrandeabrao. AndrLuizdeOliveiraVasconcelos editor

[4] RevistaQt Novembro/Dezembro-2010

Qt + PHP parte 2
Por: Andr Vasconcelos alovasconcelos@gmail.com

Continuaodotutorialsobredesenvolvimentodeaplicaeshbridas Desktop+PHP

Na primeira parte deste tutorial, vimos um pequeno exemplo de aplicao hbrida Desktop + PHP. A partir de agora passamos a ver um exemplo mais complexo, utilizando o Zend Framework no servidor. Como os tutoriais publicados nesta seo da revista Laboratrio sero voltados aos programadores mais experientes no vamos nos deter em aspectos bsicos de programao Qt ou PHP. Para esta segunda parte, precisaremos do Zend Framework, que pode ser obtido no endereo: http://framework.zend.com/download/latest O motivo de adotar o Zend Framework neste projeto apenas um: simplificar o desenvolvimento do lado servidor da nossa aplicao. Isto porque o ZF (vamos cham-lo assim daqui pra frente) possui uma srie de classes prontas para usar . Como usaremos apenas alguns componentes bsicos do ZF, podemos utilizar a verso minimal. Alm do ZF, vamos precisar do MySQL instalado na mquina que vamos usar como servidor. O MySQL pode ser obtido no endereo: http://dev.mysql.com/downloads/ Obviamente, como a parte servidora de nossa aplicao ser desenvolvida em PHP, precisamos tambm do Apache e do PHP 5 instalados no servidor. A minha plataforma de desenvolvimento a seguinte:

Ubuntu 10.10 Apache2 PHP5 MySQL 5.1.49-1 Zend Framework 1.10.8-minimal

RevistaQt Novembro/Dezembro-2010 [5]

phpapp
ZF Aplicao PHP com ZF

Servidor WEB Apache

HTTP

Interface em Qt
A aplicao desenvolvida nesta parte do tutorial carrega dados a partir de um servidor e mostra em um Grid. Os dados ficam em um banco MySQL e so lidos por uma aplicao em PHP disponvel no servidor. A interface da nossa aplicao feita em Qt faz uma requisio aplicao em PHP no servidor, e apresenta o resultado. Teremos um boto para fazer nova requisio ao servidor e atualizar as informaes no Grid. Do lado servidor temos um programa em PHP com ZF que recebe o nome de uma classe e o nome de um mtodo, executa o mtodo e retorna o resultado como um XML.

Participe deste projeto. Envie um e-mail para revistaqt@gmail.com.


[6] RevistaQt Novembro/Dezembro-2010

Como diria Jack, o Estripador: vamos por partes. Comecemos pela criao do banco de dados da aplicao:
CREATEDATABASE`teste`DEFAULTCHARACTERSETlatin1COLLATElatin1_swedish_ci; CREATEDATABASE`teste`DEFAULTCHARACTERSETlatin1COLLATElatin1_swedish_ci;

Com o banco de dados criado vamos criao da tabela estado:


CREATE TABLE `estado` ( CREATE TABLE int(11) NOT NULL AUTO_INCREMENT, `id_estado` `estado` ( `id_estado` int(11) NOT NULL `sigla` varchar(2) NOT NULL, AUTO_INCREMENT, `sigla` varchar(2) NOT NULL, `nome` varchar(40) NOT NULL, `nome` varchar(40) NOT NULL, PRIMARY KEY (`id_estado`), PRIMARY KEY (`id_estado`), UNIQUE KEY `estado_sigla` (`sigla`), UNIQUE KEY `estado_sigla` (`sigla`), UNIQUE KEY `estado_nome` (`nome`) UNIQUE KEY `estado_nome` (`nome`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=27 ; ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=27 ;

Os comandos a seguir populam a tabela com a lista de estados e o Distrito Federal:


insert into estado (id_estado,nome,sigla) values (1, 'Amazonas', 'AM'); insert into estado (id_estado,nome,sigla) values (1, 'Amazonas', 'AM'); insert into estado (id_estado,nome,sigla) values (2, 'Acre', 'AC'); insert into estado (id_estado,nome,sigla) values (2, 'Acre', 'AC'); insert into estado (id_estado,nome,sigla) values (3, 'Rondonia', 'RO'); insert into estado (id_estado,nome,sigla) values (3, 'Rondonia', 'RO'); insert into estado (id_estado,nome,sigla) values (4, 'Roraima','RR'); insert into estado (id_estado,nome,sigla) values (4, 'Roraima','RR'); insert into estado (id_estado,nome,sigla) values (5, 'Par', 'PA'); insert into estado (id_estado,nome,sigla) values (5, 'Par', 'PA'); insert into estado (id_estado,nome,sigla) values (6, 'Maranho', 'MA'); insert into estado (id_estado,nome,sigla) values (6, 'Maranho', 'MA'); insert into estado (id_estado,nome,sigla) values (7, 'Piau', 'PI'); insert into estado (id_estado,nome,sigla) values (7, 'Piau', 'PI'); insert into estado (id_estado,nome,sigla) values (8, 'Cear', 'CE'); insert into estado (id_estado,nome,sigla) values (8, 'Cear', 'CE'); insert into estado (id_estado,nome,sigla) values (9, 'Rio Grande do Norte', 'RN'); insert into estado (id_estado,nome,sigla) values (9, 'Rio Grande do Norte', 'RN'); insert into estado (id_estado,nome,sigla) values (10, 'Paraba', 'PB'); insert into estado (id_estado,nome,sigla) values (10, 'Paraba', 'PB'); insert into estado (id_estado,nome,sigla) values (11, 'Sergipe', 'SE'); insert into estado (id_estado,nome,sigla) values (11, 'Sergipe', 'SE'); insert into estado (id_estado,nome,sigla) values (12, 'Alagoas','AL'); insert into estado (id_estado,nome,sigla) values (12, 'Alagoas','AL'); insert into estado (id_estado,nome,sigla) values (13, 'Bahia', 'BA'); insert into estado (id_estado,nome,sigla) values (13, 'Bahia', 'BA'); insert into estado (id_estado,nome,sigla) values (14, 'Tocantins', 'TO'); insert into estado (id_estado,nome,sigla) values (14, 'Tocantins', 'TO'); insert into estado (id_estado,nome,sigla) values (15, 'Gois', 'GO'); insert into estado (id_estado,nome,sigla) values (15, 'Gois', 'GO'); insert into estado (id_estado,nome,sigla) values (16, 'Distrito Federal', 'DF'); insert into estado (id_estado,nome,sigla) values (16, 'Distrito Federal', 'DF'); insert into estado (id_estado,nome,sigla) values (17, 'Esprito Santo', 'ES'); insert into estado (id_estado,nome,sigla) values (17, 'Esprito Santo', 'ES'); insert into estado (id_estado,nome,sigla) values (18, 'Minas Gerais', 'MG'); insert into estado (id_estado,nome,sigla) values (18, 'Minas Gerais', 'RJ'); insert into estado (id_estado,nome,sigla) values (19, 'Rio de Janeiro', 'MG'); insert into estado (id_estado,nome,sigla) values (19, 'Rio de Janeiro', insert into estado (id_estado,nome,sigla) values (20, 'So Paulo', 'SP'); 'RJ'); insert into estado (id_estado,nome,sigla) values (20, 'So Paulo', 'SP'); insert into estado (id_estado,nome,sigla) values (21, 'Paran', 'PR'); insert into estado (id_estado,nome,sigla) values (21, 'Paran', 'PR'); insert into estado (id_estado,nome,sigla) values (22, 'Santa Catarina', 'SC'); insert into estado (id_estado,nome,sigla) values (22, 'Santa Catarina', 'SC'); insert into estado (id_estado,nome,sigla) values (23, 'Rio Grande do Sul', 'RS'); insert into estado (id_estado,nome,sigla) values (23, 'Rio Grande do Sul', 'RS'); insert into estado (id_estado,nome,sigla) values (24, 'Mato Grosso do Sul', 'MS'); insert into estado (id_estado,nome,sigla) values (24, 'Mato Grosso 'MT'); insert into estado (id_estado,nome,sigla) values (25, 'Mato Grosso', do Sul', 'MS'); insert into estado (id_estado,nome,sigla) values (25, 'Mato Grosso', insert into estado (id_estado,nome,sigla) values (26, 'Amap', 'AP'); 'MT'); insert into estado (id_estado,nome,sigla) values (26, 'Amap', 'AP');

Agora que temos o banco de dados vamos criao do lado servidor da nossa aplicao em PHP. O documentRoot do Apache em minha mquina aponta para o diretrio /home/vasconcelos/Projetos/www. Se voc no faz ideia do que seja documentRoot, recomendo que procure na Internet por um tutorial de instalao e configurao do Apache. Estando no diretrio correspondente ao documentRoot do Apache, crie um diretrio chamado phpapp:

$ mkdir phpapp $ mkdir phpapp

RevistaQt Novembro/Dezembro-2010 [7]

A seguir vamos criar dentro do diretrio de nossa aplicao um diretrio chamado Classes, onde ficaro os arquivos com os cdigos das classes da mesma:
$ cd phpapp $ cd phpapp $ mkdir Classes $ mkdir Classes

Como esta aplicao far uso do ZF, vamos criar em seu diretrio um link simblico para o diretrio contendo as bibliotecas do cara (o ZF).
$ ln -s ../ZendFramework-1.10.8-minimal/library/Zend Zend $ ln -s ../ZendFramework-1.10.8-minimal/library/Zend Zend

No meu caso, o diretrio contendo o ZF ZendFramework-1.10.8-minimal e fica no mesmo nvel do diretrio da aplicao. Substitua a referncia na criao do link de acordo com o nome do diretrio e a localizao do ZF no seu servidor.

Agora que temos o diretrio de nossa aplicao e um link para o diretrio com as bilbiotecas do ZF criados, vamos escrever o cdigo PHP para ela, comeando pelo arquivo index.php, que dever ser criado no diretrio da aplicao phpapp.

www.revistaqt.com www.twitter.com/revistaqt
[8] RevistaQt Novembro/Dezembro-2010

<?php <?php // index.php // index.php // Include para o Servidor Rest do Zend Framework // Include para o Servidor Rest do Zend Framework require_once('Zend/Rest/Server.php'); require_once('Zend/Rest/Server.php'); // Nome da classe que est sendo requisitada // Nome da classe que est sendo requisitada $className = $_GET['class']; $className = $_GET['class']; // Include para definio da classe requisitada // Include para definio da classe requisitada require_once("Classes/{$className}.php"); require_once("Classes/{$className}.php"); // Instancia servidor Rest // Instancia servidor Rest $server = new Zend_Rest_Server(); $server = new Zend_Rest_Server(); // Seta o nome da classe // Seta o nome da classe $server->setClass($className); $server->setClass($className); // Processa a requisio // Processa a requisio $server->handle(); $server->handle();

No quadro acima temos todo o cdigo do arquivo index.php. Como mencionei no incio desta parte do tutorial, a adoo do ZF simplificou muito o trabalho. A classe Zend_Rest_Server faz toda a mgica acontecer. O Rest Server recebe uma requisio para execuo de um mtodo em uma determinada classe e retorna o resultado. Nosso prximo passo ser criar uma classe para conexo ao banco de dados. Antes de continuarmos, quero fazer algumas observaes. A finalidade deste exemplo demonstrar a abordagem de aplicaes hbridas (Qt + PHP), no servir de base para uma aplicao real. Aqui no estou preocupado com o tratamento de erros, por exemplo. Observe que no index.php no est sendo tratada a situao de inexistncia do arquivo correspondente classe que esteja sendo requisitada ao servidor. A classe de conexo que vamos criar a seguir tambm no possuir tratamento de erros e servir apenas para executar queries. Crie um arquivo chamado Conexao.php no diretrio Classes da aplicao.

RevistaQt Novembro/Dezembro-2010 [9]

<?php <?php // Classes/Conexao.php // Classes/Conexao.php require_once('Zend/Db.php'); require_once('Zend/Db.php'); // Definio da classe de conexo com o banco de dados // Definio da classe de conexo com o banco de dados class Conexao { class Conexao { private $db; // Recurso de conexo com o banco de dados private $db; // Recurso de conexo com o banco de dados static private $instancia; // Instncia esttica de Conexao static private $instancia; // Instncia esttica de Conexao // Mtodo pblico para conectar ao banco de dados // Mtodo pblico para conectar ao banco de dados public function conecta() public function conecta() { { // Conecta ao banco de dados // Conecta ao banco de dados $db = Zend_Db::factory('Pdo_Mysql', array( $db = Zend_Db::factory('Pdo_Mysql', array( 'host' => 'localhost', // servidor 'host' => 'localhost', // servidor 'username' => 'root', // usurio 'username' => 'root', // usurio 'password' => 'margrande', // senha 'password' => 'margrande', // senha 'dbname' => 'teste', // banco de dados 'dbname' => 'teste', // banco de dados 'charset' => 'utf8' // codificao 'charset' => 'utf8' // codificao )); )); $this->db = $db; $this->db = $db; } } // Mtodo esttico para retornar ou instanciar uma nova conexo // Mtodo esttico para retornar ou instanciar uma nova conexo static public function getConexao(){ static public function getConexao(){ if (!isset(self::$instancia)) { if (!isset(self::$instancia)) { $c = __CLASS__; $c = __CLASS__; self::$instancia = new $c; self::$instancia = new $c; } } return self::$instancia; return self::$instancia; } } // Mtodo para execuo de Queries SQL // Mtodo para execuo de Queries SQL public function executaQuery($sql) public function executaQuery($sql) { { if(!is_resource($this->db)){ if(!is_resource($this->db)){ $this->conecta(); $this->conecta(); } } return $this->db->fetchAll($sql); return $this->db->fetchAll($sql); } } }

Esta classe de conexo usa o Design Pattern conhecido como Singleton. Mais informaes sobre o assunto podem ser encontradas em http://pt.wikipedia.org/wiki/Singleton.

[10] RevistaQt Novembro/Dezembro-2010 10]

Para concluir a parte servidora desta aplicao falta apenas criar a classe que ser requisitada pelo programa em Qt.
<?php <?php // Classes/ListaEstado.php // Classes/ListaEstado.php class ListaEstado { class ListaEstado { public function retorna() { public function retorna() { include_once1('Classes/Conexao.php'); include_once1('Classes/Conexao.php'); $db = Conexao::getConexao(); $db = Conexao::getConexao(); return $db->executaQuery("SELECT return $db->executaQuery("SELECT id_estado, id_estado, sigla, sigla, nome nome FROM FROM estado"); estado"); } } } }

isso. Para testar acesse a aplicao pelo browser, passando na url os argumentos class e method, como mostra a figura abaixo:

O resultado apresentado depender do browser que voc estiver utilizando. O Firefox apresenta o XML retornado pela aplicao como mostra a prxima figura.

RevistaQt Novembro/Dezembro-2010 [11] 11]

O Chrome suprime a exibio das tags XML, exibindo apenas os valores retornados. Se voc selecionar a opo exibir cdigo fonte da pgina (ou View page source), ver o XML completo.

Agora que o servidor est pronto, vamos criar a parte cliente da nossa aplicao em Qt. Como j foi esclarecido tanto no Editorial, como no incio desta parte do tutorial, a editoria Laboratrio (da qual o presente artigo faz parte) dedicada queles com mais experincia em Qt. Sero abordados aqui, tpicos um pouco mais avanados e que vo portanto requerer do leitor o conhecimento bsico de Qt. Usando o Qt Creator, crie um projeto chamado QtPHP, tendo sua classe principal chamada QtPHP. Quem tiver dvidas sobre como criar uma aplicao em Qt, pode consultar o artigo Al, Qt Creator publicado na primeira edio da Revista Qt. Com um projeto com o nome de QtPHP criado, vamos crio da interface (bem simples) da aplicao. Arraste para a janela da aplicao um componente QpushButton. Troque sua propriedade objectName para btnAtualizar e sua propriedade text para Atualizar.

[12] RevistaQt Novembro/Dezembro-2010 12]

Arraste um componente QtableWidget para a janela da aplicao. Coloque um componente Spacer entre o boto Atualizar e a borda da janela, como mostrado abaixo.

Usando o menu de contexto da janela de nossa aplicao (boto direito do mouse), selecione a opo Layout Layout in a Grid.

RevistaQt Novembro/Dezembro-2010 [13] 13]

A janela da aplicao ter a seguinte aparncia, nesse ponto:

Com a interface da nossa aplicao desenhada, podemos passar ao cdigo-fonte, mas antes vamos a uma breve descrio de seu funcionamento.

enviarRequisicao
QU rl

QNetworkRequest tratarResultado

A base do nosso programa so os slots enviarRequisicao e tratarResultado. O primeiro, utiliza um objeto do tipo QNetworkRequest para enviar ao servidor uma requisio http. No caso desta aplicao, a requisio ser:
http://localhost/phpapp/?class=ListaEstado&method=retorna http://localhost/phpapp/?class=ListaEstado&method=retorna

O slot enviarRequisicao monta uma URL que submetida atravs de um objeto do tipo QNetworkRequest pelo mtodo get de um objeto QNetworkAccessManager. O signal finished do objeto QNetworkAccessManager ser conectado ao slot tratarResultado que receber um objeto do tipo QNetworkReply com o resultado da requisio feita ao servidor. O slot tratarResultado processar o XML recebido como resposta do servidor, preenchendo o grid QTableWidget que colocamos na interface do programa.

[14] RevistaQt Novembro/Dezembro-2010 14]

a ost sp Re

http QNetworkReply Signal finished QNetworkAccessManager XML

Internet

Nosso programa utilizar os mdulos QtNetwork e QtXml, portanto, edite o arquivo qtPHP.pro e altere a linha:
QT QT += core gui += core gui

para

QT QT

+= core gui network xml += core gui network xml

O cdigo da funo main, no arquivo main.cpp no apresenta qualquer alterao em relao ao criado pelo Qt Creator, como vemos a seguir:
#include <QtGui/QApplication> #include <QtGui/QApplication> #include "qtphp.h" #include "qtphp.h" int main(int argc, char *argv[]) { int main(int argc, char *argv[]) { QApplication a(argc, argv); QApplication a(argc, argv); QtPHP w; QtPHP w; w.show(); w.show(); return a.exec(); return a.exec(); } }

Agora edite o arquivo qtphp.h para que seu contedo seja igual ao mostrado na listagem abaixo:
#ifndef QTPHP_H #ifndef QTPHP_H #define QTPHP_H #define QTPHP_H #include <QMainWindow> #include <QMainWindow> #include <QNetworkAccessManager> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkRequest> #include <QNetworkReply> #include <QNetworkReply> #include <QMessageBox> #include <QMessageBox> #include <QdomDocument> #include <QdomDocument> #include <QTimer> #include <QTimer> namespace Ui { namespace Ui { class QtPHP; class QtPHP; } } class QtPHP : public QMainWindow { class QtPHP : public QMainWindow { Q_OBJECT Q_OBJECT public: public: explicit QtPHP(QWidget *parent = 0); explicit ~QtPHP(); QtPHP(QWidget *parent = 0); ~QtPHP(); private slots: private slots: void enviarRequisicao(); void enviarRequisicao(); void tratarResultado(QNetworkReply * resposta); void tratarResultado(QNetworkReply * resposta); private: private: Ui::QtPHP *ui; Ui::QtPHP *ui; QNetworkAccessManager * requisicaoRede; QNetworkAccessManager * requisicaoRede; }; }; #endif // QTPHP_H #endif // QTPHP_H

As linhas em destaque (cor vermelha) no cdigo acima referem-se quelas que devem ser includas em relao ao arquivo originalmente criado pelo Qt Creator. Temos a incluso das definies das classes que usaremos no programa, dos prottipos dos slots enviarRequisicao e tratarResultado e do atributo requisicaoRede.
RevistaQt Novembro/Dezembro-2010 [15] 15]

Bom, agora vamos parte mais importante deste programa. A implementao, propriamente dita, da classe QtPHP, no arquivo qtphp.cpp. Como o cdigo um mais extenso (pouco mais de cem linhas), vamos ver cada parte dele separadamente. Comeando pelos includes feitos para o header da classe e para o header da classe correspondente interface grfica.
#include "qtphp.h" #include "qtphp.h" #include "ui_qtphp.h" #include "ui_qtphp.h"

A prxima parte do cdigo da nossa classe a declarao do construtor.


QtPHP::QtPHP(QWidget *parent) : QtPHP::QtPHP(QWidget *parent) : QMainWindow(parent), QMainWindow(parent), ui(new Ui::QtPHP) ui(new Ui::QtPHP) { { ui->setupUi(this); ui->setupUi(this); requisicaoRede = new QNetworkAccessManager(this); requisicaoRede = new QNetworkAccessManager(this); connect(ui->btnAtualizar, connect(ui->btnAtualizar, SIGNAL(clicked()), SIGNAL(clicked()), this, this, SLOT(enviarRequisicao())); SLOT(enviarRequisicao())); connect(requisicaoRede, connect(requisicaoRede, SIGNAL(finished(QNetworkReply*)), SIGNAL(finished(QNetworkReply*)), this, this, SLOT(tratarResultado(QNetworkReply*))); SLOT(tratarResultado(QNetworkReply*))); // Configura o QTableWidget // Configura o QTableWidget ui->tableWidget->setColumnCount(3); ui->tableWidget->setColumnCount(3); ui->tableWidget->verticalHeader()->setVisible(false); ui->tableWidget->verticalHeader()->setVisible(false); // Monta o cabealho da tabela // Monta o cabealho QStringList cabecalho; da tabela QStringList cabecalho; cabecalho << "Id" << "Sigla" << "Nome"; cabecalho << "Id" << "Sigla" << "Nome"; ui->tableWidget->setHorizontalHeaderLabels(cabecalho); ui->tableWidget->setHorizontalHeaderLabels(cabecalho); // Chama o SLOT enviarRequisicao // Chama o SLOT enviarRequisicao QTimer::singleShot(0, this, SLOT(enviarRequisicao())); QTimer::singleShot(0, this, SLOT(enviarRequisicao())); } }

As linhas em destaque (cor vermelha) foram includas no mtodo construtor originalmente criado pelo Qt Creator. Primeiro temos a instanciao de um objeto do QNetworkAccessManager que o responsvel neste caso pela comunicao entre nosso programa em Qt e a aplicao Web. Este objeto um atributo da classe QtPHP, de modo que esteja acessvel em todos os mtodos da mesma. Se no fosse um atributo da classe, precisaramos passar por referncia a todos os mtodos que precisam utiliz-lo. Como temos um boto, chamado btnAtualizar que dever executar uma requisio ao servidor, conectamos o signal clicked do mesmo ao slot enviarRequisicao da nossa classe. Quando ocorrer uma requisio, o objeto QNetworkAccessManager aguarda pela resposta do servidor e emite um signal finished quando isto ocorrer. Para que nosso programa saiba que a requisio foi atendida e reaja resposta, conectamos o signal finished do objeto QNetworkAccessManager ao slot tratarResultado, passando ao mesmo um ponteiro para um objeto do tipo QNetworkReply. [16] RevistaQt Novembro/Dezembro-2010 16]

A seguir temos a configurao do objeto QTableWidget que exibir a lista de estados obtida do servidor. Estamos setando o nmero de colunas para trs (3) e ocultando o header vertical, ou seja, a coluna mostrada esquerda da tabela com a numerao das linhas. Continuando, setamos o cabealho (header) do objeto QTableWidget, com Id para a primeira coluna, Sigla para a segunda coluna e Nome para a terceira. Agora vem um macete publicado por Mark Summerfield em seu livro Advanced Qt Programming da Prentice Hall. Observe a utilizao de uma chamada ao mtodo esttico singleShot da classe QTimer para chamar o mtodo enviarRequisicao. A ideia de colocar a chamada ao mtodo enviarRequisicao no mtodo construtor era de que, ao executar o programa, a lista de estados seja automaticamente carregada e exibida, sem que o usurio tenha que clicar no boto Atualizar. At a tudo bem, mas porque no coloquei no final do mtodo construtor simplesmente uma chamada ao mtodo enviarRequisicao? De acordo com Mark, deve-se limitar ao construtor, chamadas a mtodos que estejam relacionados criao do objeto. A chamada ao mtodo de carga da lista de estados pressupe que a janela de nossa aplicao esteja pronta. Chamadas diretas a mtodos do objeto que est sendo construdo so consideradas inseguras, porque no existe a garantia de que o objeto esteja pronto durante a execuo do construtor. Assim, Mark recomenda o uso de uma chamada ao mtodo esttico singleShot de QTimer com zero como argumento correspondente ao intervalo, como foi feito aqui:
QTimer::singleShot(0, this, SLOT(enviarRequisicao()));} QTimer::singleShot(0, this, SLOT(enviarRequisicao()));}

Com esta instruo estamos executando em zero milissegundos (imediatamente, portanto), no objeto this o slot enviarRequisicao. Esta prtica garante que a execuo ocorrer apenas quando o objeto correspondente a nossa aplicao esteja pronta. Nenhuma alterao foi implementada no mtodo destrutor da classe criado pelo Qt Creator, como visto a seguir:
/** /** * @brief Destrutor * */ @brief Destrutor */ QtPHP::~QtPHP() { QtPHP::~QtPHP() { delete ui; delete ui; } }

O prximo mtodo da nossa classe o enviarRequisicao, que um slot privado da classe QtPHP, para que possa ser conectado ao signal clicked do boto Atualizar.
void QtPHP::enviarRequisicao() { void QtPHP::enviarRequisicao() { ui->tableWidget->setRowCount(0); ui->tableWidget->setRowCount(0); ui->tableWidget->clearContents(); ui->tableWidget->clearContents(); // Monta a URL para requisio dos dados ao servidor // Monta a URL para requisio dos dados ao servidor QString url = "http://localhost/phpapp/?class=ListaEstado&method=retorna"; QString url = "http://localhost/phpapp/?class=ListaEstado&method=retorna"; // Executa a requisio ao servidor // Executa a requisio ao servidor requisicaoRede->get(QNetworkRequest(QUrl(url))); requisicaoRede->get(QNetworkRequest(QUrl(url))); } }

RevistaQt Novembro/Dezembro-2010 [17] 17]

As duas primeiras linhas do slot enviarRequisicao, servem para apagar o contedo do objeto tableWidget, que exibir a lista de estados carregada do servidor. Desta forma, quando o usurio clicar no boto Atualizar, a nova lista carregada substituir a anterior. A prxima instruo no mtodo a montagem da URL que ser submetida ao servidor. Aqui foi utilizado um objeto do tipo QString para armazenar o endereo. A ltima instruo do mtodo usa o mtodo get do atributo requisicaoRede que um QNetworkAccessManager. O mtodo get de QNetworkAccessManager recebe um objeto QNetworkRequest, o qual como o prprio nome indica, uma requisio de rede. A requisio retornar ao QNetworkAccessManager um ponteiro para um objeto QNetworkReply, que receber o resultado de tal requisio. Quando a resposta for recebida pelo objeto QNetworkAccessManager, este emitir um signal finished. que foi conectado l no construtor com o prximo e ltimo mtodo de nossa classe: o slot tratarResultado. Como o cdigo de tratarResultado maior e o responsvel pela apresentao do resultado de nosso programa, vamos listar o seu cdigo por blocos:
void QtPHP::tratarResultado(QNetworkReply * resposta) { void QtPHP::tratarResultado(QNetworkReply * resposta) { // Verifica se houve erro na resposta // Verifica se houve erro na resposta if(resposta->error() != QNetworkReply::NoError){ if(resposta->error() != QNetworkReply::NoError){ QMessageBox::critical(this, "Erro", QMessageBox::critical(this, "Erro", "No foi possvel recuperar dados do servidor"); "No foi possvel recuperar dados do servidor"); return; return; } }

O slot tratarResultado recebe como argumento um ponteiro para um objeto do tipo QNetworkReply passado para ele pelo objeto QNetworkAccessManager no momento em que o signal finished for emitido (lembre-se de que no construtor da classe QtPHP, conectamos o signal finished do objeto requisicaoRede que um QNetworkAccessManager ao slot tratarResultado). O primeiro passo em tratarResultado verificar se ocorreu erro na requisio feita ao servidor. Para isso verificamos se o resultado da chamada ao mtodo error do objeto resposta diferente de QNetworkReply:NoError. Caso tenha ocorrido um erro, o programa emite uma mensagem informando ao usurio e retorna. A resposta recebida do servidor ser um XML com a seguinte estrutura:
<ListaEstado generator="zend" version="1.0"> <ListaEstado generator="zend" version="1.0"> <retorna> <retorna> <key_0> <key_0> <id_estado>1</id_estado> <id_estado>1</id_estado> <sigla>AM</sigla> <sigla>AM</sigla> <nome>Amazonas</nome> <nome>Amazonas</nome> </key_0> </key_0> ... ... <key_25> <key_25> <id_estado>26</id_estado> <id_estado>26</id_estado> <sigla>AP</sigla> <sigla>AP</sigla> <nome>Amap</nome> <nome>Amap</nome> </key_25> </key_25> <status>success</status> <status>success</status> </retorna> </retorna> </ListaEstado> </ListaEstado>

[18] RevistaQt Novembro/Dezembro-2010 18]

Na primeira linha temos a tag raiz do nosso XML, identificando nesse caso o nome da classe que foi executada para emisso da resposta ListaEstado. Os atributos generator e version indicam respectivamente quem gerou o XML e qual a verso. A prxima tag do XML tem o nome do mtodo executado retorna. Em seguida, temos para cada um dos registros retornados a tag key_n, onde n representa o nmero sequencial do registro, comeando por zero (0). Para cada registro, temos trs tags indicando os nomes dos campos retornados, a saber: <id_estado> <sigla> <nome> O valor contido em nas tags acima o contedo do registro propriamente dito.
// Cria objeto DOM para tratamento do XML de resposta e // Cria objeto resposta pode ser atribuda ao este objeto // verifica se a DOM para tratamento do XML de resposta e // verifica se a QDomDocument doc; resposta pode ser atribuda ao este objeto QDomDocument doc; if(!doc.setContent(resposta)){ if(!doc.setContent(resposta)){ QMessageBox::critical(this,"Erro","Erro tratando resultado"); QMessageBox::critical(this,"Erro","Erro tratando resultado"); return; return; } }

No prximo passo, caso no tenha ocorrido um erro no retorno da requisio do servidor, temos a criao de um objeto do tipo QDomDocument que ser utilizado para tratamento do XML retornado. Na atribuio do contedo ao objeto QDomDocument verificamos se ocorreu erro. Se a resposta do servidor no puder ser atribuda ao objeto QDomDocument, o programa emite uma mensagem ao usurio e retorna. Com o XML da resposta carregado no objeto QDomDocument podemos usar suas facilidades para navegar pelas tags do documento.
// Verifica se o retorno foi gerado pela classe ListaEstado // Verifica se o = doc.documentElement(); QDomElement classe retorno foi gerado pela classe ListaEstado QDomElement classe = "ListaEstado"){ if(classe.tagName() != doc.documentElement(); if(classe.tagName() != "ListaEstado"){ QmessageBox::critical(this,"Erro", QmessageBox::critical(this,"Erro", no da classe ListaEstado"); "O XML recebido "O XML recebido no da classe ListaEstado"); return; return; } }

Neste trecho do cdigo, utilizamos um objeto QDomElement para armazenar o primeiro elemento do documento DOM. Se o nome da tag do primeiro elemento do XML recebido do servidor no for ListaEstado, o programa avisa ao usurio e retorna.
// N correspondente ao nome do mtodo - retorna // N correspondente ao nome do mtodo QDomNode metodo = classe.firstChild(); - retorna QDomNode metodo = classe.firstChild();

Em seguida o primeiro filho do elemento ListaEstado atribuido a um objeto QDomNode. A tag filha de ListaEstado em nosso XML retorna, que corresponde ao nome do mtodo executado pelo servidor.

RevistaQt Novembro/Dezembro-2010 [19] 19]

// N correspondente ao registro // N correspondente ao registro QDomNode registro = metodo.firstChild(); QDomNode registro = metodo.firstChild();

O primeiro filho da tag retorna, lida no passo anterior, corresponde ao primeiro registro retornado pela consulta.
// N correspondente ao status - o ltimo // N correspondente ao status - o ltimo QDomNode status = metodo.lastChild(); QDomNode status = metodo.lastChild(); if(status.toElement().text() != "success"){ if(status.toElement().text() != "success"){ QMessageBox::critical(this,"Erro","O servidor retornou erro"); QMessageBox::critical(this,"Erro","O servidor retornou erro"); return; return; } }

Antes de comear a navegar pelos registros, temos a leitura do ltimo filho da tag retorna, que corresponde ao status da execuo do comando. Caso o texto deste ltimo elemento seja diferente de success, significa que ocorreu um erro. Neste caso, o programa avisa ao usurio e retorna.
// Percorre os registros // Percorre os registros int linha = 0; int linha = 0; while(!registro.isNull() && registro != status){ while(!registro.isNull() && registro != status){ ui->tableWidget->insertRow(linha); ui->tableWidget->insertRow(linha); QDomNode campo = registro.firstChild(); QDomNode int coluna campo = registro.firstChild(); = 0; int coluna = 0; // Percorre os campos // Percorre os campos while(!campo.isNull()){ while(!campo.isNull()){ QTableWidgetItem * item = new QTableWidgetItem(campo.toElement().text()); QTableWidgetItem * item = new coluna, item); ui->tableWidget->setItem(linha, QTableWidgetItem(campo.toElement().text()); ui->tableWidget->setItem(linha, coluna, item); coluna++; coluna++; campo = campo.nextSibling(); campo = campo.nextSibling(); } } linha++; linha++; registro = registro.nextSibling(); registro = registro.nextSibling(); } } }

Se a execuo do programa chegou a este ponto, s falta percorrer a lista de registros e popular o QTableWidget da nossa aplicao com os dados. Neste trecho do cdigo, o primeiro loop while percorre registro, at que seja o final desde que no seja o registro de status. Como cada campo de um registro um filho seu, temos um segundo loop para percorrer os filhos de cada registro e setar a linha/coluna correspondente no QTableWidget com o contedo do campo. Para navegar entre os itens de um elemento do DOM, usamos o mtodo nextSibling. A seguir, a listagem completa do slot tratarResultado.

Envie suas crticas, dvidas e sugestes para revistaqt@gmail.com


[20] RevistaQt Novembro/Dezembro-2010 20]

void QtPHP::tratarResultado(QNetworkReply * resposta) { void QtPHP::tratarResultado(QNetworkReply * resposta) { // Verifica se houve erro na resposta // Verifica se houve erro na resposta if(resposta->error() != QNetworkReply::NoError){ if(resposta->error() != QNetworkReply::NoError){ QMessageBox::critical(this, "Erro", QMessageBox::critical(this, "Erro", "No foi possvel recuperar dados do servidor"); "No foi possvel recuperar dados do servidor"); return; return; } } // Cria objeto DOM para tratamento do XML de resposta e // Cria objeto resposta pode ser atribuda ao este objeto // verifica se a DOM para tratamento do XML de resposta e // verifica se a QDomDocument doc; resposta pode ser atribuda ao este objeto QDomDocument doc; if(!doc.setContent(resposta)){ if(!doc.setContent(resposta)){ QMessageBox::critical(this,"Erro","Erro tratando resultado"); QMessageBox::critical(this,"Erro","Erro tratando resultado"); return; return; } } // Verifica se o retorno foi gerado pela classe ListaEstado // Verifica se o = doc.documentElement(); QDomElement classe retorno foi gerado pela classe ListaEstado QDomElement classe = "ListaEstado"){ if(classe.tagName() != doc.documentElement(); if(classe.tagName() != "ListaEstado"){ QMessageBox::critical(this,"Erro", QMessageBox::critical(this,"Erro", "O XML recebido no da classe ListaEstado"); "O XML recebido no da classe ListaEstado"); return; return; } } // N correspondente ao nome do mtodo - retorna // N correspondente ao nome do mtodo QDomNode metodo = classe.firstChild(); - retorna QDomNode metodo = classe.firstChild(); // N correspondente ao registro // N correspondente ao registro QDomNode registro = metodo.firstChild(); QDomNode registro = metodo.firstChild(); // N correspondente ao status - o ltimo // N correspondente ao status - o ltimo QDomNode status = metodo.lastChild(); QDomNode status = metodo.lastChild(); if(status.toElement().text() != "success"){ if(status.toElement().text() != "success"){ QMessageBox::critical(this,"Erro","O servidor retornou erro"); QMessageBox::critical(this,"Erro","O servidor retornou erro"); return; return; } } // Percorre os registros // Percorre os registros int linha = 0; int linha = 0; while(!registro.isNull() && registro != status){ while(!registro.isNull() && registro != status){ ui->tableWidget->insertRow(linha); ui->tableWidget->insertRow(linha); QDomNode campo = registro.firstChild(); QDomNode int coluna campo = registro.firstChild(); = 0; int coluna = 0; // Percorre os campos // Percorre os campos while(!campo.isNull()){ while(!campo.isNull()){ QTableWidgetItem * item = new QTableWidgetItem(campo.toElement().text()); QTableWidgetItem * item = new coluna, item); ui->tableWidget->setItem(linha, QTableWidgetItem(campo.toElement().text()); ui->tableWidget->setItem(linha, coluna, item); coluna++; coluna++; campo = campo.nextSibling(); campo = campo.nextSibling(); } } linha++; linha++; registro = registro.nextSibling(); registro = registro.nextSibling(); } } } }

A explicao sobre o funcionamento deste programa no foi feita linha a linha, mas para aqueles com alguma experincia em Qt, os comentrios colocados no cdigo-fonte j devem ajudar bastante. A mesma observao vale para a parte PHP desta aplicao.

A figura a seguir mostra o resultado da execuo do nosso programa:

RevistaQt Novembro/Dezembro-2010 [21] 21]

Comentando um dia desses sobre aplicaes hbridas Qt + PHP com um amigo, ele questionou: no poderamos fazer a parte servidora tambm em Qt, usando CGI? Verdade poderamos. Mas fazer a parte servidora usando a dupla PHP / Zend Framework facilita muito o trabalho. No precisamos nos preocupar com detalhes da conexo com o banco de dados ou com a formatao do resultado em XML. comum encontrar programadores especialistas em uma ferramenta, querendo utiliz-la para tudo aquilo que pretendam fazer. Sempre uso o seguinte exemplo para ilustrar esta situao: Imagine um trabalhador que possui um excelente conjunto de chaves de fenda. Vrios tamanhos, torques, modelos, etc. - uma maravilha... Mas se tentar colocar um prego, um martelo seria mais til do que todo o seu conjunto de chaves. A escolha da ferramenta deve ser feita de acordo com o trabalho a ser feito. Ok, eu admito - t parecendo coisa de livro de auto-ajuda, mas se tem uma coisa que os meus vinte e poucos anos de programao me ensinaram que no existe ferramenta definitiva. Na prxima edio continuamos com mais exemplos de aplicaes hbridas, utilizando Qt e PHP. Um grande abrao.

Programadores fazem programas, analistas fazem anlise e programalistas fazem as 10 coisas.

[22] RevistaQt Novembro/Dezembro-2010 22]

Por: Oliver Widder oliver.widder@gmail.com

http://geekandpoke.typepad.com

RevistaQt Novembro/Dezembro-2010 [23] 23]

Criando aplicativos com Qt 4.7 no Mac OS X


Por: Pierre Freire blog@pierrefreire.com.br

Nestetutorialiremosaprenderacomoinstalarumambientede desenvolvimentocomQTnoMacOSX. Com o crescimento da Apple no mercado, tem se tornado muito comum o uso de notebooks e desktops da empresa de Cupertino por usurios e empresas, com isto a demanda por novos aplicativos tem crescido bastanteeestenovofiloparaosprogramadoresestaapenascomeando. OobjetivodestetutorialabordarainstalaodoSDK(KitdeDesenvolvimentodaQTparaMacOS),outras informaesoslinksabaixopoderoajudarbastante.
http://www.revistaqt.com http://qt.nokia.com

Ambientetestado: MacBookWhite SistemaoperacionalSnowLeopard10.6.4 1AcessandoositedaNokia 1.1OKitdedesenvolvimentodaQTpodeserobtidogratuitamentenositehttp://qt.nokia.com/acessando olinkdeDOWNLOADS:

[24] RevistaQt Novembro/Dezembro-2010 24]

1.2Voctemagoraaopodeusaraversocomercialoulgpl(livre),nonossotutorialestamosbaixandoa versolgpl,conformeaimagemabaixo:

1.3Casoodownloadnocomece,cliquenolink,conformeafigura:

1.4Avelocidadedodownloadvaidependerdasuabandalarga,agoraaordemesperar.

RevistaQt Novembro/Dezembro-2010 [25] 25]

2Iniciandoainstalao OdownloadfoiefetuadocomsucessoeoarquivoQtSDK.mpkgiraparecernodesktopdoseucomputador, eleirabrirautomaticamente,casoistonoaconteacliquenoicone.

[26] RevistaQt Novembro/Dezembro-2010 26]

2.1Ateladoinstaladorapareceeoprocessoseinicia.

2.2Teladeboasvindascomalgumasinformaessobreoproduto.

RevistaQt Novembro/Dezembro-2010 [27] 27]

2.3UmreadmecominformaessobreaversaodoQTeinformaesemgeral,podemosseguiremfrente.

2.4Informaessobreolicenciamentodosoftware,casotenhainteresseleiaesigaemfrente.

[28] RevistaQt Novembro/Dezembro-2010 28]

2.5 Esta janela, quer uma confirmao se voc aceita os termos da licena clique emAgreecaso voc concordeemusar.

2.6Oinstaladorirmostrarasunidadesdediscoeoespaodisponvel,eoespaoqueainstalaodoQT vaiocuparnodisco.

2.7Sequisermudarolocaldeinstalao.Notutorialdeixamosnopadro.

RevistaQt Novembro/Dezembro-2010 [29] 29]

2.8 Como esta instalando um software, por motivos de segurana o Mac Os vai solicitar o seu usurio e senhadoadministrador.

[30] RevistaQt Novembro/Dezembro-2010 30]

2.9Oprocessodeinstalaofoiiniciado,agoraesperar.

2.10Sevocchegouaesteponto,significaqueoQTfoiinstaladocomsucessonoseucomputador.

RevistaQt Novembro/Dezembro-2010 [31] 31]

3.0Testandooambienteinstalado ComoSDKdoQtinstalado,vamosagoraconheceracaradoQT. 3.1UsandooFinderouoatalhonoseudesktopacesseoseuMacintoshHD.


Temos a pasta Developer onde ficam as ferramentas de desenvolvimento.

DentrodapastaDeveloperselecioneApplications,agoraentrenapastaQT.

[32] RevistaQt Novembro/Dezembro-2010 32]

.DentrodapastaQtevriosaplicativosestarodisponveis: Assistant, QtCreator qtdemo(ExemplosfeitosemQt)

CliquenoQtCreatorparaconheceraIDEdedesenvolvimento.

3.2OQtCreatoraIDEdedesenvolvimentooficial.

Tem dvidas, crticas, sugestes? Envie um e-mail para revistaqt@gmail.com.


RevistaQt Novembro/Dezembro-2010 [33] 33]

Chegamosaofinaldestetutorial,ondeabordamosainstalaodasferramentasdedesenvolvimentoparaMac. Oprximopassoagoraoseu,estudar,pesquisareconhecerestefascinantemundodoQT.

[34] RevistaQt Novembro/Dezembro-2010 34]

EstilodecodificaoQT

Por: Andr Vasconcelos alovasconcelos@gmail.com

Esta umatraduo livredodocumento QtCodingStylecomalgumasconvenesutilizadasno desenvolvimento do Qt propriamente dito. Tratase de uma pequena lista de recomendaes queles que queiram participar ativamente do projeto, baixando os fontes do Qt e criando novas classes, novos mdulos, etc. Achei interessante reproduzir aqui como sugesto de estilo. Vamos aotexto:

EstilodeCodificaoQt EsteumresumodaconvenodecodificaoqueusamosparaescrevercdigodoQt.Estes dadosforamrecolhidospela"minerao"dosfontesdoQt,frunsdediscusso,tpicosdeemaile atravsdacolaboraodosdesenvolvedores. Indentao Quatro(4)espaossousadosparaidentao Espaos,noTabs!

Declaraodevariveis Declarecadavarivelemumalinhaseparada Eviteusarnomescurtos(porexemplo:a,rbarr,nughdeget)semprequepossvel Nomesdevariveiscomapenasumcaracteresdevemserusadasparacontadoresevariveis temporrias,quandoopropsitodavarivelsejabvio Declareumavarivelnomomentoemqueelasejanecessria


//Errado inta,b; char*c,*d; //Correto intheight; intwidth; char*nameOfThis; char*nameOfThat;

RevistaQt Novembro/Dezembro-2010 [35] 35]

Nomesdevariveisdevemcomearcomletrasminsculas.Cadapalavraseguintenonomede umavariveldevecomearcomumaletramaiscula Eviteabreviaes

//Errado shortCntr; charITEM_DELIM='\t'; //Correto shortcounter; charitemDelimiter='\t';

Classessemprecomeamcomumaletramaiscula.ClassespblicasdoQtcomeamcomuma letraQ(maiscula).Funespblicasnamaioriadasvezes,comeamcomumaletraq (minscula)

Espaosembranco Uselinhasembrancoparaagrupardeclaraesondeforadequado Sempreuseapenasumalinhaembranco Sempreuseumespaonicodepoisdeumapalavrachaveeantesdechaves.


//Errado if(foo){ } //Correto if(foo){ }

Paraponteirosoureferncias,sempreuseumnicoespaoentreotipoeocaracter'*'ou'&'*, masnenhumespaoentreo*ou&eonomedavarivel.

char*x; constQString&myString; constchar*consty="hello";

Nouseespaodepoisdeumcast. Eviteconverses(casts)noestilodeCquandopossvel.

//Errado char*blockOfMemory=(char*)malloc(data.size()); //Correto char*blockOfMemory=(char*)malloc(data.size()); char*blockOfMemory=reinterpret_cast<char*>(malloc(data.size()));

[36] RevistaQt Novembro/Dezembro-2010 36]

Chaves

Comoregrabsica,achavedaesquerdavemnamesmalinhadocomeodadeclarao:

//Errado if(codec) { } //Correto if(codec){ }

Exceo:Implementaesdefunesedeclaraesdeclassessempretmachaveesquerdano comeodeumanovalinha:

staticvoidfoo(intg) { qDebug("foo:%i",g); } classMoo { };

Usechavesquandoocorpodeumadeclaraocondicionalcontivermaisdeumalinha,ou quandocontiverapenasumalinhaquesejaumpoucomaiscomplexa

//Errado if(address.isEmpty()){ returnfalse; } for(inti=0;i<10;++i){ qDebug("%i",i); } //Correto if(address.isEmpty()) returnfalse; for(inti=0;i<10;++i) qDebug("%i",i);

RevistaQt Novembro/Dezembro-2010 [37] 37]

Exceo1:Usechavestambmseadeclaraocontivervriaslinhas

//Correto if(address.isEmpty()||!isValid() ||!codec){ returnfalse; }

Exceo2:Usechavestambmemblocosifthenelsecasooblocodecdigodoifoudoelse tenhamaisdeumalinha

//Errado if(address.isEmpty()) returnfalse; else{ qDebug("%s",qPrintable(address)); ++it; } //Correto if(address.isEmpty()){ returnfalse; }else{ qDebug("%s",qPrintable(address)); ++it; } //Errado if(a) if(b) ... else ... //Correto if(a){ if(b) ... else ... }

Usechavesquandoocorpodeumadeclaraoforvazia

//Errado while(a); //Correto while(a){} [38] RevistaQt Novembro/Dezembro-2010 38]

Parnteses

Useparntesesparaagruparexpresses:

//Errado if(a&&b||c) //Correto if((a&&b)||c) //Errado a+b&c //Correto (a+b)&c DeclaraesSwitch

Osrtulos"case"dasdeclaraesswitchestosemprenamesmacolunadadeclaraoswitch Todocasodeveterumadeclaraobreak(oureturn)nofinalouumcomentrioparaindicarque intencionalmentenofoicolocadoobreak

switch(myEnum){ caseValue1: doSomething(); break; caseValue2: doSomethingElse(); //fallthrough default: defaultHandling(); break; } Quebrasdelinhas

Mantenhaaslinhascommenosdecem(100)caracteres;utilizequebrassenecessrio. Vrgulasvonofinaldaslinhasquebradas;operadoresvonoinciodeumanovalinha.O operadorestarnofinaldeumalinhaparaevitarterquerolar(scroll)atelaseoeditorformuito estreito.

RevistaQt Novembro/Dezembro-2010 [39] 39]

//Correto if(longExpression +otherLongExpression +otherOtherLongExpression){ } //Errado if(longExpression+ otherLongExpression+ otherOtherLongExpression){ } Exceogeral

Sintaselivreparaquebrarumaregraseestafizeroseucdigoparecerruim.

No dia 18 de novembro, a Nokia ir realizar um webinar em portugus sobre o desenvolvimento de apliaes em Qt para dispositivos com Symbian. J no dia 9 de dezembro, ser a vez de um webinar sobre desenvolvimento de interfaces grficas de usurios com Qt 4.7 e Qt Quick, tambm em portugus. Para inscrever-se no webinar sobre Qt para dispositivos Symbian, acesse: http://forumnokia.emea.acrobat.com/e93667679/event/registration.html Para inscrever-se no webinar sobre desenvolvimento de interfaces grficas de usurios com QT 4.7 e Qt Quick, acesse: http://forumnokia.emea.acrobat.com/e60819127/event/registration.html

[40] RevistaQt Novembro/Dezembro-2010 40]

TutorialQML/ LayoutAnchorbased emQML/ Introduo LinguagemQML

Por: Andr Vasconcelos alovasconcelos@gmail.com

Mais uma da srie Verso Brasileira. Desta vez trago uma traduo do QML Tutorial disponvel no endereo http://doc.qt.nokia.com/4.7-snapshot/qml-tutorial.html. O Tutorial QML est dividido em trs partes. De lambuja, a traduo de mais dois tutoriais relacionados ao Tutorial QML. Um sobre layouts baseados em ncoras (Anchor-based) e outro sobre a linguagem QML. Vamos l...

Tutorial QML
Este tutorial traz uma introduo ao QML, a linguagem de marcao para o Qt Quick. Ele no cobre todos os aspectos; a nfase no ensino dos princpios fundamentais, e os recursos so apresentados medida em que sejam necessrios. Atravs dos diferentes passos deste tutorial ns aprenderemos sobre os tipos bsicos, criaremos nosso prprio componente QML com propriedades e sinais (signals), e criaremos uma animao simples com a ajuda dos estados (states) e transies (transitions). O primeiro captulo comea com um programa "Hello world!" mnimo e o captulo seguinte apresenta novos conceitos. O cdigo fonte do tutorial pode ser encontrado no diretrio: $QTDIR/examples/declarative/tutorials/helloworld onde $QTDIR corresponde ao diretrio no qual voc instalou o SDK do Qt 4.7. Captulos do tutorial: 1. Tipos bsicos 2. Componentes QML 3. Estados (States) e transies (Transitions)

RevistaQt Novembro/Dezembro-2010 [41] 41]

Tutorial QML 1 - Tipos bsicos


O primeiro programa um exemplo de "Hello world!" muito simples que apresenta alguns conceitos bsicos do QML. A figura abaixo um screenshot deste programa.

Aqui est o cdigo QML da aplicao: import QtQuick 1.0 import QtQuick 1.0 Rectangle { Rectangle { id: page id: page width: 500; height: 200 width: 500; height: 200 color: "lightgray" color: "lightgray" Text { Text { helloText id: id: "Hello world!" text: helloText text: y: 30 "Hello world!" y: 30 anchors.horizontalCenter: page.horizontalCenter anchors.horizontalCenter: page.horizontalCenter font.pointSize: 24; font.bold: true font.pointSize: 24; font.bold: true } } } }

Passo a passo Import


Primeiro ns precisamos importar os tipos necessrios a este exemplo. Na maioria dos arquivos QML importaremos os tipos QML embutidos (como Rectangle, Image, etc) que vm com o Qt usando: import QtQuick 1.0 import QtQuick 1.0

[42] RevistaQt Novembro/Dezembro-2010 42]

Elemento Rectangle

Rectangle { Rectangle { id: page id: page width: 500; height: 200 width: 500; height: 200 color: "lightgray" color: "lightgray" Declaramos um elemento raiz do tipo Rectangle. Este um dos blocos de construo bsicos que voc pode usar para criar uma aplicao em QML. Ns atribuimos um id para poder fazer referncia ao mesmo mais tarde. Neste caso, ns o chamamos de "page". Ns tambm setamos as propriedades width (tamanho), height (altura) e color (cor). O elemento Rectangle contm muitas outras propriedades (como x e y), mas estes so deixados com seus valores default.

Elemento Text
Text { Text { helloText id: id: "Hello world!" text: helloText text: y: 30 "Hello world!" y: 30 anchors.horizontalCenter: page.horizontalCenter anchors.horizontalCenter: page.horizontalCenter font.pointSize: 24; font.bold: true font.pointSize: 24; font.bold: true } }

Adicionamos um elemento Text como filho do elemento raiz Rectangle que exibe o texto "Hello world!". A propriedade y usada para posicionar o texto verticalmente a 30 pixels do topo de seu pai. A propriedade anchors.horizontalCenter refere-se centralizao horizontal de um elemento. Neste caso, especificamos que nosso elemento Text deve ser centralizado horizontalmente no elemento page (veja Layout baseado em ncora "Anchor-based Layout"). As propriedades font.pointSize e font.bold so relativas s fontes e usam a notao de ponto.

Visualizando o exemplo
Para ver o que voc criou, execute a ferramenta de visualizao QML (localizada no diretrio bin do SDK do Qt) com o nome do arquivo como primeiro argumento. Por exemplo, para executar o exemplo completo do Tutorial 1 a partir do local de instalao, voc deveria digitar:

bin/qmlviewer $QTDIR/examples/declarative/tutorials/helloworld/tutorial1.qml

RevistaQt Novembro/Dezembro-2010 [43] 43]

Tutorial QML 2 - Componentes QML


Este captulo acrescenta um seletor de cores (color picker) para alterar a cor do texto.

Nosso seletor de cores feito de seis clulas com diferentes cores. Para evitar escrever o mesmo cdigo vrias vezes para cada clula, criamos um novo componente Cell. Um componente proporciona uma forma de definir um novo tipo que podemos reutilizar em outros arquivos QML. Um componente QML como uma caixa preta e interage com o mundo exterior atravs de propriedades, sinais (signals) e funes e geralmente definido em seu prprio arquivo QML. (Para mais detalhes veja a seo "Definindo novos componentes"). O nome do arquivo do componente deve sempre comear com uma letra maiscula. Aqui est o cdigo QML do arquivo Cell.qml: import QtQuick 1.0 import QtQuick 1.0 Item { Item { container id: id: container property alias cellColor: rectangle.color property alias cellColor: rectangle.color signal clicked(color cellColor) signal clicked(color cellColor) width: 40; height: 25 width: 40; height: 25 Rectangle { Rectangle { id: rectangle id: rectangle border.color: "white" border.color: "white" anchors.fill: parent anchors.fill: parent } } MouseArea { MouseArea { anchors.fill: parent anchors.fill: parent onClicked: container.clicked(container.cellColor) onClicked: container.clicked(container.cellColor) } } } }

[44] RevistaQt Novembro/Dezembro-2010 44]

Passo a passo O componente Cell


Item { Item { container id: id: container property alias cellColor: rectangle.color property alias cellColor: rectangle.color signal clicked(color cellColor) signal clicked(color cellColor) width: 40; height: 25 width: 40; height: 25

O elemento raiz do nosso componente um Item com o id container. Um Item o elemento visual mais bsico em QML e frequentemente usado com um container para outros elementos. property alias cellColor: rectangle.color property alias cellColor: rectangle.color Declaramos uma propriedade cellColor. Esta propriedade acessvel de fora do nosso componente, o que nos permite instanciar as clulas com diferentes cores. Esta propriedade apenas um apelido (alias) para uma propriedade existente - a propriedade color de um retngulo que compe a clula (veja Adicionando novas propriedades). signal clicked(color cellColor) signal clicked(color cellColor) Ns precisamos que nosso componente tenha tambm um signal que chamaremos de clicked com um parmetro do tipo color. Usaremos este signal para mudar a cor do texto no arquivo QML principal mais tarde. Rectangle { Rectangle { rectangle id: id: rectangle border.color: "white" border.color: "white" anchors.fill: parent anchors.fill: parent } } Nosso componente cell basicamente um retngulo colorido com o id rectangle. A propriedade anchors.fill uma forma conveniente de atribuir o tamanho de um elemento. Neste caso, o retngulo ter o mesmo tamanho de seu pai (veja Layout baseado em ncora "Anchor-based Layout"). MouseArea { MouseAreaanchors.fill: parent { anchors.fill: parent onClicked: container.clicked(container.cellColor) onClicked: container.clicked(container.cellColor) } }

RevistaQt Novembro/Dezembro-2010 [45] 45]

Para mudar a cor do texto quando clicar em uma clula, criamos um elemento MouseArea com o mesmo tamanho de seu pai. Um MouseArea define um signal chamado clicked. Quando o signal disparado precisamos emitir nosso prprio signal clicked com a cor como parmetro;

O arquivo QML principal


Em nosso arquivo QML principal, usamos nosso componente Cell para criar o seletor de cores:
import QtQuick 1.0 import QtQuick 1.0 Rectangle { Rectangle { id: page id: page width: 500; height: 200 width: 500; height: 200 color: "lightgray" color: "lightgray" Text { Text helloText id: { id: "Hello world!" text: helloText text: y: 30 "Hello world!" y: 30 anchors.horizontalCenter: page.horizontalCenter anchors.horizontalCenter: page.horizontalCenter font.pointSize: 24; font.bold: true } font.pointSize: 24; font.bold: true } Grid { Grid colorPicker id: { id: anchors.bottom: page.bottom; anchors.bottomMargin: 4 x: 4; colorPicker x: 4; anchors.bottom: page.bottom; anchors.bottomMargin: 4 rows: 2; columns: 3; spacing: 3 rows: 2; columns: 3; spacing: 3 Cell { cellColor: "red"; onClicked: helloText.color = cellColor } Cell cellColor: "red"; onClicked: helloText.color Cell { {cellColor: "green"; onClicked: helloText.color == cellColor }} cellColor Cell cellColor: "green"; onClicked: helloText.color = cellColor Cell { {cellColor: "blue"; onClicked: helloText.color = cellColor } } Cell cellColor: "blue"; onClicked: helloText.color Cell { {cellColor: "yellow"; onClicked: helloText.color == cellColor }} cellColor Cell{ {cellColor: "steelblue"; onClicked: helloText.color = cellColor } cellColor: "yellow"; onClicked: helloText.color = cellColor } Cell Cell cellColor: "steelblue"; onClicked: helloText.color = cellColor } Cell { {cellColor: "black"; onClicked: helloText.color = cellColor } } Cell { cellColor: "black"; onClicked: helloText.color = cellColor } } } }

Criamos o seletor de cores colocando 6 clulas com diferentes cores em uma tabela. Cell { cellColor: "red"; onClicked: helloText.color = cellColor } Cell { cellColor: "red"; onClicked: helloText.color = cellColor } Quando o signal clicked de nossa clula disparada, precisamos atribuir a cor do texto para a cellColor passada como seu parmetro. Podemos reagir a qualquer signal do componente atravs de uma propriedade de nome "onSignalName" (veja Manipuladores de sinais).

[46] RevistaQt Novembro/Dezembro-2010 46]

Tutorial QML 3 - States e Transitions


Neste captulo, ns criamos este exemplo um pouco mais dinmico pela introduo de states e transitions. Queremos que nosso texto mova-se para a base da tela, rode e fique vermelho quando clicado. Aqui est o cdigo QML:
import QtQuick 1.0 import QtQuick 1.0 Rectangle { Rectangle { id: page id: page width: 500; height: 200 width: 500; height: 200 color: "lightgray" color: "lightgray" Text { Text {helloText id: id: "Hello world!" text: helloText text: y: 30 "Hello world!" y: 30 anchors.horizontalCenter: page.horizontalCenter anchors.horizontalCenter: page.horizontalCenter font.pointSize: 24; font.bold: true font.pointSize: 24; font.bold: true MouseArea { id: mouseArea; anchors.fill: parent } MouseArea { id: mouseArea; anchors.fill: parent } states: State { states: "down"; when: mouseArea.pressed == true name: State { name: "down"; { target: helloText PropertyChanges when: mouseArea.pressed == true PropertyChanges { target: helloText y: 160; rotation: 180 y: 160; rotation: 180 color: "red" color: "red" } } } } transitions: Transition { transitions:to: "down"; reversible: true from: ""; Transition { from: ""; to: "down"; reversible: true ParallelAnimation { ParallelAnimation { properties: "y,rotation" NumberAnimation { NumberAnimation { properties: "y,rotation" duration: 500 duration: 500 easing.type: Easing.InOutQuad easing.type: Easing.InOutQuad } } ColorAnimation { duration: 500 } ColorAnimation { duration: 500 } } } } } } } Grid { Grid { colorPicker id: id: anchors.bottom: page.bottom; anchors.bottomMargin: 4 x: 4; colorPicker x: 4; anchors.bottom: page.bottom; anchors.bottomMargin: 4 rows: 2; columns: 3; spacing: 3 rows: 2; columns: 3; spacing: 3 Cell { cellColor: "red"; onClicked: helloText.color = cellColor } Cell cellColor: "red"; onClicked: helloText.color Cell { {cellColor: "green"; onClicked: helloText.color == cellColor }} cellColor Cell cellColor: "green"; onClicked: helloText.color = cellColor Cell { {cellColor: "blue"; onClicked: helloText.color = cellColor } } Cell cellColor: "blue"; onClicked: helloText.color Cell { {cellColor: "yellow"; onClicked: helloText.color == cellColor }} cellColor Cell{ {cellColor: "steelblue"; onClicked: helloText.color = cellColor } cellColor: "yellow"; onClicked: helloText.color = cellColor } Cell Cell cellColor: "steelblue"; onClicked: helloText.color = cellColor } Cell { {cellColor: "black"; onClicked: helloText.color = cellColor } Cell { cellColor: "black"; onClicked: helloText.color = cellColor } } } } }

RevistaQt Novembro/Dezembro-2010 [47] 47]

Passo a passo
states: State { states: "down"; when: mouseArea.pressed == true name: State { name: "down"; { target: helloText; y: 160; rotation: 180; color: "red" } PropertyChanges when: mouseArea.pressed == true PropertyChanges { target: helloText; y: 160; rotation: 180; color: "red" } } }

Primeiro ns criamos um novo state para nosso elemento text. Este state ser ativado quando o MouseArea for pressionado e desativado quando for solto. O state down inclui um conjunto de mudanas de propriedades em relao ao state default (os itens como so inicialmente definidos no QML). Especificamente, ns setamos a propriedade y do texto para 160, a rotao para 180 e a cor para vermelho.
transitions: Transition { transitions: Transition { reversible: true from: ""; to: "down"; from: ""; to: "down"; reversible: true ParallelAnimation { ParallelAnimation { NumberAnimation { properties: "y,rotation" NumberAnimation { properties: "y,rotation" duration: 500 duration: 500 easing.type: Easing.InOutQuad easing.type: Easing.InOutQuad } } ColorAnimation { duration: 500 } ColorAnimation { duration: 500 } } } } }

Como no queremos que o texto aparea na base da tela instantaneamente, mas ao invs disse mova-se suavemente, adicionamos uma transition entre os dois states. As propriedades from e to definem os states entre os quais a transition vai ser executada. Nesse caso, queremos uma transition do state default oara nosso state down. Como queremos que a mesma transition seja executada ao contrrio quando voltando do state down para o state default, setamos a propriedade reversible para true. Isto equivale a escrever as duas transitions separadamente. O elemento ParallelAnimation garante que os dois tipos de animao (number e color) comecem ao mesmo tempo. Podeos tambm execut-las (as animaes) uma aps a outra usando SequentialAnimation ao invs de ParallelAnimation. Para mais detalhes sobre states e transitions, veja States QML e o exemplo de states e transitions.

[48] RevistaQt Novembro/Dezembro-2010 48]

Layout Anchor-based em QML


Alm dos mais tradicionais - Grid, Row e Column, QML tambm proporciona um modo de organizar itens usando o conceito de ncoras (anchors). Cada item pode ser imaginado como se tivesse um conjunto de sete linhas-ncoras invisveis: left, horizontalCenter, right, top, verticalCenter, baseline e bottom. A linha-base (no mostrada acima) corresponde linha imaginria na qual o texto estar assentado. Para itens sem texto, ela a mesma que "top". O sistema de ancoragem QML permite-lhe definir relacionamentos entre as linhas-ncoras de diferentes itens. Por exemplo, voc pode escrever:
Rectangle { id: rect1; ... } Rectangle id: rect1; ... } Rectangle { {id: rect2; anchors.left: rect1.right; ... } Rectangle { id: rect2; anchors.left: rect1.right; ... }

Neste caso, a borda esquerda de rect2 vinculada borda direita de rect1, produzindo o seguinte: O sistema de ancoragem tambm permite que voc especifique margens e deslocamentos. Margens especificam a quantidade de espao deixado para o lado de fora de um item, enquanto deslocamentos permitem que voc manipule o posicionamento usando as linhas centrais de ancoragem. Observe que margens especificadas usando o sistema de ancoragem tem significado apenas para ncoras; elas no tem qualquer efeito quando usando outros layouts ou posicionamento absoluto. O seguinte exemplo especifica uma margem esquerda:
Rectangle { id: rect1; ... } Rectangle id: rect1; ... } Rectangle { {id: rect2; anchors.left: rect1.right; anchors.leftMargin: 5; ... } Rectangle { id: rect2; anchors.left: rect1.right; anchors.leftMargin: 5; ... }

Neste caso, a margem de 5 pixels reservada para a esquerda de rect2, produzindo o seguinte: Voc pode especificar ncoras mltiplas. Por exemplo:
Rectangle { id: rect1; ... } Rectangle id: rect1; Rectangle { {id: rect2; ... } Rectangle { id: rect2; rect1.right; anchors.left: anchors.left: rect1.right; anchors.top: rect1.bottom; ... anchors.top: rect1.bottom; ... } }

Especificando mltiplas ncoras horizontais ou verticais voc pode controlar o tamanho de um item. Por exemplo:

RevistaQt Novembro/Dezembro-2010 [49] 49]

Rectangle { id: rect1; x: 0; ... } Rectangle id: rect1; x: 0; ... } Rectangle { {id: rect2 Rectangle { id: rect2 anchors.left: rect1.right anchors.left: rect1.right anchors.right: rect3.left anchors.right: rect3.left ... ... } } Rectangle { id: rect3; x: 150; ... } Rectangle { id: rect3; x: 150; ... }

Limitaes
Por razes de performance, voc s pode ancorar um item ao seus irmos e pais diretos. Por exemplo, a segunte ncora pode ser considerada invlida e produziria uma advertncia:
Item { Item group1 id: { id: group1 Rectangle { id: rect1; ... } } Rectangle { id: rect1; ... } } Item { Item group2 id: { id: group2 Rectangle { id: rect2; anchors.left: rect1.right; ... } } Rectangle { id: rect2; anchors.left: rect1.right; ... } }

// ncora invlida // ncora invlida

A sua empresa trabalha com Qt? Compartilhe sua experincia com nossos leitores. Envie um e-mail para revistaqt@gmail.com.
[50] RevistaQt Novembro/Dezembro-2010 50]

Introduo linguagem QML


QML uma linguagem declarativa projetada para descrever interfaces de usurio de um programa: sua aparncia e como ele se comporta. Em QML, uma interface de usurio especificada rvore de objetos com propriedades. Esta introduo destina-se queles com pouca ou nenhuma experincia de programao. Javascript usado como linguagem de script em QML, ento voc pode querer aprender um pouco mais sobre o assunto antes de mergulhar fundo no QML. Tambm ajuda ter um conhecimento bsico de outras tecnologias web como HTML e CSS, mas no necessrio.

Sintaxe bsica QML


QML parece com isso:
import QtQuick 1.0 import QtQuick 1.0 Rectangle { Rectangle200 width: { width: 200 height: 200 height: 200 color: "blue" color: "blue" Image { Image { source: "pics/logo.png" source: "pics/logo.png" anchors.centerIn: parent anchors.centerIn: parent } } } }

Objetos so especificados pelo seu tipo, seguido por um par de chaves. Tipos de objetos sempre comeam com uma letra maiscula. No exemplo acim, existem dois objetos, um Rectangle e um Image. Entre as chaves, podemos especificar informaes sobre o objeto, como suas propriedades. Propriedades so especificadas como propriedade: valor. No exemplo acima, podemos ver que Image possui uma propriedade chamada source, qual foi atribuido o valor "pics/logo.png". A propriedade e seus valores so separadas por uma dois pontos. Propriedades podem ser especificadas uma por linha:
Rectangle { Rectangle { 100 width: width: 100 height: 100 height: 100 } }

ou voc pode colocar mltiplas propriedades em uma nica linha:


Rectangle { width: 100; height: 100 } Rectangle { width: 100; height: 100 }

RevistaQt Novembro/Dezembro-2010 [51] 51]

Quando mltiplos pares propriedade/valor so especificados em uma nica linha, eles devem ser separados por um ponto e vrgula. A declarao import importa o mdulo Qt, que contm todos os elementos padro do QML. Sem esta declarao import, os elementos Rectangle e Image no estariam disponveis

Expresses
Alm de atribuir valores s propriedades, voc pode tambm atribuir expresses escritas em Javascript.
Rotation { Rotation {360 * 3 angle: angle: 360 * 3 } }

Estas expresses podem incluir referncias a outros objetos e propriedades, caso em que um vnculo estabelecido: quando o valor da expresso muda, a propriedade qual a expresso foi atribuda automaticamente atualizada para aquele valor.
Item { Item { { Text Text { text1 id: id: "Hello World" text: text1 text: "Hello World" } } Text { Text { text2 id: id: text1.text text: text2 text: text1.text } } } }

No exemplo acima, o objeto text2 mostrar o mesmo texto do objeto text1. Se text1 mudar, text2 automaticamente alterado para o mesmo valor. Observe que para referir-se a outros objetos, usamos os valores de seus ids (veja abaixo mais informaes sobre a propriedade id).

Comentrios QML
Comentar em QML semelhante ao JavaScript. * Comentrios de nica linha comeam com // e terminam no final da linha * Comentrios multilinhas comeam com /* e terminam com */ Comentrios so ignorados pelo engine. Eles so teis para explicar o que voc est fazendo; para referncia futura ou para outros que leiam seus arquivos QML. Comentrios tambm podem ser usados para evitar a execuo de cdigo, o que s vezes til para rastrear problemas.

[52] RevistaQt Novembro/Dezembro-2010 52]

Text { Text text: "Hello world!" { text: "Hello //opacity: 0.5 world!" //opacity: 0.5 } }

No exemplo acima, o objeto Text ser sua opacidade normal, posto que a linha opacity: 0.5 foi transformada em um comentrio.

Propriedades Nomeando propriedades


Propriedades comea com uma letra minscula (com exceo das propriedades anexadas).

Tipos de propriedades
QML suporta propriedades de muitos tipos (veja Tipos bsicos QML). Os tipos bsicos incluem int, real, bool, string, color e lists.
Item { Item {10.5 x: x: ... 10.5 ... state: "details" state: "details" focus: true focus: true } } // uma propriedade 'real' // uma propriedade 'real' // uma propriedade 'string' // uma propriedade 'string' // uma propriedade 'bool' // uma propriedade 'bool'

Propriedades QML so o que conhecido como type-safe. Isto , elas apenas permitem atribuir um valor que combine com o tipo da propriedade. Por exemplo, a propriedade x do item um real, e se voc tentar atribuir uma string a ela, voc obter um erro.
Item { Item {"hello" // ilegal! x: x: "hello" // ilegal! } }

A propriedade id
Cada objeto pode receber uma propriedade especial e nica chamada id. Nenhum outro objeto dentro do mesmo documento QML pode ter o mesmo valor de id. Atribuir um id permite que o objeto seja referido por outros objetos e scripts. O primeiro elemento Rectangle abaixo tem um id, "myRect". O segundo elemento Rectangle define seu prprio tamanho (width) por referncia a myRect.width, o que significa que ele ter o mesmo valor de width que o primeiro elemento Rectangle.

RevistaQt Novembro/Dezembro-2010 [53] 53]

Item { Item { Rectangle { Rectangle { id: myRect id: myRect width: 100 width: 100 height: 100 height: 100 } } Rectangle { Rectangle myRect.width width: { width: myRect.width height: 200 height: 200 } } } }

Observe que um id deve comear com uma letra minscula ou um underscore e no pode conter outros caracteres que no sejam letras, nmeros e underscores.

Propriedades List
Propriedades List parecem com isso:
Item { Item { children: [ children:{}, Image [ Image Text {} {}, Text {} ] ] } }

A lista encerrada entre colchetes, com uma vrgula separando os elementos da lista. Em casos onde voc esteja atribuindo um nico item lista, voc pode omitir os colchetes:
Image { Image { children: Rectangle {} children: Rectangle {} } }

Propriedades Default
Cada tipo de objeto pode especificar uma de suas listas ou propriedades de objeto como sua propriedade default. Se a propriedade foi declarada como propriedade default, a tag da propriedade pode ser omitida. Por exemplo, este cdigo:
State { State { changes: [ changes: [ PropertyChanges {}, PropertyChanges {}, PropertyChanges {} PropertyChanges {} ] ] } }

pode ser simplificado para:

[54] RevistaQt Novembro/Dezembro-2010 54]

State { State { PropertyChanges {} PropertyChanges {} PropertyChanges {} PropertyChanges {} } }

porque changes a propriedade default do tipo State.

Propriedades agrupadas
Em alguns casos, propriedades formam um grupo lgico e usam um ponto ou notao agrupada para demonstrar isso. Propriedades agrupadas pode ser escritas assim:
Text { Text { font.pixelSize: 12 font.pixelSize: font.bold: true 12 font.bold: true } }

ou assim:
Text { Text { { pixelSize: 12; bold: true } font font { pixelSize: 12; bold: true } } }

Na documentao do elemento, propriedades agrupadas so mostradas usando a notao de ponto.

Propriedades anexadas
Alguns objetos anexam propriedades a outro objeto. Propriedades anexadas so da forma Tipo.propriedade, onde Tipo o tipo de elemento que anexa a propriedade. Por exemplo:
Component { Component { id: myDelegate id: myDelegate Text { Text { text: "Hello" text: "Hello" color: ListView.isCurrentItem ? "red" : "blue" color: ListView.isCurrentItem ? "red" : "blue" } } } } ListView { ListView { delegate: myDelegate delegate: myDelegate } }

RevistaQt Novembro/Dezembro-2010 [55] 55]

O elemento ListView anexa a propriedade ListView.isCurrentItem para cada delegate que ele cria. Outro exemplo de propriedade anexada o elemento Keys que anexa propriedades para manipulao de teclas pressionadas para um item visual, por exemplo:
Item { Item focus: true { focus: true Keys.onSelectPressed: console.log("Selected") Keys.onSelectPressed: console.log("Selected") } }

Manipulao de sinais (signals)


Manipuladores de sinais permite que sejam tomadas aes em resposta a um evento. Por exemplo, o elemento MouseArea possui manipuladores de sinais para manipular o pressionamento, soltura e click dos botes do mouse:
MouseArea { MouseArea { onPressed: console.log("mouse button pressed") onPressed: console.log("mouse button pressed") } }

Todo manipulador de sinais comea com "on". Alguns manipuladores de sinais incluem um parmetro opcional, por exemplo o manipulador do sinal onPressed de MouseArea tem um parmetro mouse:
MouseArea { MouseArea { acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton onPressed: if (mouse.button == Qt.RightButton) onPressed: ifconsole.log("Boto Qt.RightButton) (mouse.button == direito do mouse pressionado") console.log("Boto direito do mouse pressionado") } }

[56] RevistaQt Novembro/Dezembro-2010 56]

O leitor Crlisson Galdino escreveu:


Primeiro, acho que houve um equvoco. Uma biblioteca GPL no permite de certa forma linkagem, sem que interfira na licena do software que est sendo desenvolvido. Para garantir espao s bibliotecas livres no mercado, concorrendo com as privativas, foi criada a Library General Public License, que depois foi rebatizada para Lesser General Public License. Posso estar enganado, mas acho difcil que uma biblioteca sob LGPL interfira na licena do software que a utiliza, caso se trate de meros includes. Seria bom voc contactar algum da FSF (o Alexandre Oliva, por exemplo) para informaes mais precisas a respeito. Gostei da iniciativa. Embora me parea algo um tanto restrito. Continue a linha "how-to simples" e v evoluindo o tipo de aplicao. Como criar uma agenda de contatos, um cliente twitter, um editor de textos... Isso muito bom pra quem est estudando! Seria bom tambm um comparativo-no-tendencioso de recursos do Qt frente aos toolkits que existem: Gtk+, Fltk, wxWindow... Outra seria uma srie apresentando, em cada edio, um how-to similar ao que voc fez, mas focando o uso do Qt em outra linguagem. Um para Python, na edio seguinte para Perl, etc... Seria uma forma de agradar tambm programadores fora do mundo C++ (ou que preferem outras linguagens). Qt e Androide tm muito ou nada a ver? Bem, era isso. Muito sucesso na iniciativa! []s,

Resposta do editor:
verdade, Crlisson, eu at publiquei um pedido pblico de desculpas com a explicao na segunda-feira (dia 20): http://revistaqt.blogspot.com/2010/09/mea-culpa.html A primeira edio foi bem limitada mesmo, porque tive que fazer tudo sozinho. At as charges liberadas pelo Oliver da Geek and Poke eu tive que editar no Gimp pra traduzir o texto... :) No tenho muita habilidade com a diagramao tambm. A idia que outros se empolguem e participem do projeto. Com relao ao Android, existe um "port" do Qt para ele (http://gitorious.org/~taipan/qt/android-lighthouse), mas no um projeto da Nokia. Um abrao e muito obrigado.

O leitor Eduardo Pereira escreveu:


Ol Andr Vasconcelos, Achei muito interessante seu trabalho com a revista porque so poucas informaes em portugus sobre Qt que acho na internet. Gostei bastante da parte QT + PHP. Seguinte, algumas imagem esto com a resoluo muito baixa e ficam com aparncia ruim. At mais!!!! Att,

Resposta do editor:
Oi Eduardo. Voc tem razo sobre a qualidade das imagens. Minha idia foi reduzir a quantidade de pginas para aqueles que (como eu) preferissem imprimir a revista, mas no final das contas, olhando a verso impressa, algumas imagens no ficaram boas mesmo. Vou melhorar isso na prxima edio, "espalhando" um pouco mais o contedo. Nesta primeira edio, acabei fazendo tudo sozinho e escaparam alguns detalhes. Preciso muito desse tipo de retorno, para ir melhorando a revista. Um grande abrao, Eduardo.

RevistaQt Novembro/Dezembro-2010 [57] 57]

Distribuindo suas aplicaes Qt para Linux

Por: Andr Vasconcelos alovasconcelos@gmail.com

Dica para montar um pacote para distribuio de suas aplicaes escritas em Qt

A histria comea com um programador e sua aplicao em Qt pronta e testada. O prximo passo distribuir a aplicao, provavelmente disponibilizando-a para download em algum servidor Web. Moleza! No dia seguinte, nosso heri recebe o e-mail de algum que fez o download do arquivo, mas ao tentar executar... nada! O usurio seguiu as instrues e deu permisso de leitura para o arquivo, mas ao tentar executar, recebeu a seguinte mensagem: error while loading shared libraries: libQtGui.so.4: cannot open shared object file: No such file or directory Estamos diante da tpica situao de na minha mquina funciona . Acontece que na mquina de desenvolvimento funciona tudo porque normalmente temos um trilho de bibliotecas instaladas nela. O Qt nos d duas opes de compilao de nossas aplicaes: esttica e dinmica. Para que possamos utilizar a compilao esttica, o prprio Qt tem que ter sido compilado estaticamente. Acreditem... esta no a mais simples das tarefas. Alm de levar muitas horas pra compilar o Qt estaticamente, existem muitas dependncias. Com a compulao esttica, temos a gerao de um executvel muito maior do que o gerado com a compilao dinmica, porm com tudo embutido nele. Se o programador da nossa historinha tivesse usado esta forma de compilao, o executvel disponibilizado para download teria funcionado. O compilao default do Qt a dinmica. Com a compilao dinmica temos executveis menores, porque as bibliotecas utilizadas no so includas. Durante a execuo dos programas, estes devem acessar arquivos externos correspondentes s bibliotecas necessrias. No caso do nosso desenvolvedor frustrado, a aplicao est reclamando que no conseguiu achar o arquivo libQtGui.so.4 que contm a biblioteca QtGui usada pelas aplicaes em Qt quando inclumos o mdulo gui no projeto, ou seja, em toda e qualquer aplicao com interface grfica desenvolvida em Qt. E tem mais... (parafraseando a Polishop) o programa interrompe a execuo na primeira biblioteca que no localiza. Ento na verdade, faltam mais arquivos do que o libQtGui.so.4. Neste artigo veremos como montar um pacote com tudo que uma aplicao nossa em Qt precisa para ser executada no Linux. Em edies futuras veremos como proceder para outras plataformas. [58] RevistaQt Novembro/Dezembro-2010 58]

Para este artigo, vamos utilizar o programa Al, Mundo! publicado na primeira edio da Revista Qt. Nosso primeiro passo ser descobrir quais so as bilbliotecas utilizadas pelo executvel de nossa aplicao, com o utilitrio ldd:

33 bibliotecas pra um Al, Mundo!? o preo que pagamos pelas facilidades que o Qt nos proporciona. Mas no se desespere (ainda...) porque muitas destas bibliotecas esto presentes na instalao de qualquer distribuio atual de Linux. O resultado do utilitrio ldd em seu computador pode ser diferente do apresentado aqui, dependendo da sua distribuio Linux e da verso de Qt que esteja utilizando. Eu uso o Ubuntu 10.10 com o Qt 4.7 instalado via Synaptic. Para testar a instalao de minhas aplicaes em Qt, instalei uma mquina virtual Ubuntu rodando no Virtual Box. Esta mquina virtual uma instalao limpa do Ubuntu sem as bibliotecas de desenvolvimento adicionais. Dessa forma, ela funciona como a mquina de um usurio que no seja programador.
RevistaQt Novembro/Dezembro-2010 [59] 59]

A princpio podemos nos preocupar apenas com as bibliotecas do Qt, ento o ldd pode ser executado em conjunto com o grep para filtrar apenas os arquivos que pertenam ao Qt:

Agora que sabemos de quais bibliotecas o programa AloMundo precisa para rodar, vamos copiar estes arquivos, juntamente com o arquivo executvel AloMundo para um diretrio chamado AloMundoLinux que usaremos para distribuir a aplicao. Para indicar a localizao das bilbiotecas, usamos devemos setar a varivel de ambiente LD_LIBRARY_PATH antes de executar o programa. Agora vem o macete retirado do diretrio do Google Earth: um script utilizado para setar a varivel de ambiente e chamar o executvel. Este script dever estar no diretrio AloMundoLinux.
#!/bin/sh # #!/bin/sh ## Agente SAA # # Agente SAA # FindPath() { FindPath() { fullpath="`echo $1 | grep /`" fullpath="`echo $1 | grep /`" if [ "$fullpath" = "" ]; then if oIFS="$IFS" [ "$fullpath" = "" ]; then oIFS="$IFS" IFS=: IFS=: for path in $PATH for [ -x "$path/$1" ]; then do if path in $PATH do if if -x "$path" = "" ]; then [ [ "$path/$1" ]; then if path="." = "" ]; then [ "$path" path="." fi fi fullpath="$path/$1" fullpath="$path/$1" break break fi done fi done IFS="$oIFS" IFS="$oIFS" fi fi if [ "$fullpath" = "" ]; then if fullpath="$1" = "" ]; then [ "$fullpath" fullpath="$1" fi fi # Is the sed/ls magic portable? # Is the sed/ls magic portable? if [ -L "$fullpath" ]; then if #fullpath="`ls -l ]; then [ -L "$fullpath" "$fullpath" | awk '{print $11}'`" #fullpath="`ls -l "$fullpath" | awk '{print $11}'`" fullpath=`ls -l "$fullpath" |sed -e 's/.* -> //' |sed -e 's/\*//'` fullpath=`ls -l "$fullpath" |sed -e 's/.* -> //' |sed -e 's/\*//'` fi fi dirname $fullpath dirname $fullpath } } CPATH="`FindPath $0`" CPATH="`FindPath $0`" LD_LIBRARY_PATH=.:${CPATH} LD_LIBRARY_PATH=.:${CPATH} export LD_LIBRARY_PATH export LD_LIBRARY_PATH cd "${CPATH}/" cd "${CPATH}/" exec "./AloMundo" "$@" exec "./AloMundo" "$@"

[60] RevistaQt Novembro/Dezembro-2010 60]

Ainda no acabou... no caso do nosso pequeno AloMundo, no utilizamos imagens, apenas um label com o texto Al, Mundo!, mas para aplicaes onde sejam utilizadas imagens, devemos incluir os plugins para tratamento dos formatos utilizados. Os plugins dos formatos de imagens ficam no diretrio qt/plugins/imageformats a partir do diretrio onde esteja instalado o Qt. Digamos que sua aplicao utilize imagens do tipo jpeg. Nesse caso voc deve criar no diretrio de sua aplicao um diretrio chamado imageformats e copie para ele o arquivo qt/plugins/imageformats/libqjpeg.so para ele. Com os arquivos da aplicao presentes no diretrio AloMundoLinux, basta gerar um pacote, compactando-o. Pode-se utilizar, por exemplo, o utilitrio tar para isso: tar cvfz AloMundoLinux.tgz AloMundoLinux Agora s baixar o arquivo na mquina cliente, descompactar e executar a aplicao atravs do script start. Caso a execuo reclame da ausncia de outra biblioteca, basta inclu-la no diretrio AloMundoLinux e gerar o pacote novamente. Uma vantagem da abordagem de compilao dinmica a possibilidade de atualizar as bibliotecas sem atualizar as aplicaes. Ok, voc pode a essa altura estar imaginando: se eu tiver 10 aplicaes em Qt terei em cada uma delas uma cpia das bibliotecas utilizadas? No necessariamente. Voc pode adotar como regra, a criao de um diretrio na mquina do cliente para armazenar as bibliotecas e utilizar este diretrio no seu script start. Alguns fabricantes de software usam a estratgia de criar um diretrio com o seu nome e dentro deste diretrio instalar seus produtos. Neste caso, o script start setar a varivel LD_LIBRARY_PATH para apontar para o diretrio compartilhado onde estaro as bibliotecas. At a prxima.

Um excelente material sobre Qt encontra-se disponvel no site de Um excelente material sobre Qt encontra-se disponvel no site de Antnio Mrcio A. Menezes. Slides de seu mini-curso e o cdigo-fonte Antnio Mrcio A. Menezes. Slides de seu mini-curso e o cdigo-fonte utilizado. Imperdvel para estudantes ou profissionais de Qt. utilizado. Imperdvel para estudantes ou profissionais de Qt. O mini-curso est disponvel em: O mini-curso est disponvel em: http://antoniomenezes.net/?tag=mini-curso-c-qt http://antoniomenezes.net/?tag=mini-curso-c-qt

RevistaQt Novembro/Dezembro-2010 [61] 61]

Edio 2 - Novembro-Dezembro-2010

Editor Andr Luiz de O. Vasconcelos Cartoons Oliver Widder (Geek & Poke) Colaboradores Pierre Andrade Freire Rogrio Etsuo Yamamaru

A revista e os aplicativos nela publicados foram criados utilizando o Linux Ubuntu, verso 10.10.

A Revista Qt foi criada e convertida para PDF no BrOffice.org Draw, verso 3.2.1.

As imagens capturadas das telas presentes na Revista Qt foram obtidas atravs do KSnaphot, verso 0.8.1.

O tratamento de imagens (como a traduo das charges do Geek & Poke) foi feito atravs do Gimp, verso 2.6.10.

Você também pode gostar