C Programando GUI Com Qt4 Segunda Edicao

download C Programando GUI Com Qt4 Segunda Edicao

of 33

Transcript of C Programando GUI Com Qt4 Segunda Edicao

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    C++ Programando GUI com Qt4, Segunda Edio

    Publicado por: Prentice HallData de Publicao: 04/02/2008Traduzido por:

    Arthur DiasDanilo Domingos

    Viso GeralO nico oficialmente publicado Guia das melhores prticas para programao Qt 4.3

    Usando Trolltechs Qt possvel criar aplicaes C++ de alta performance que rodem em mquinasWindows, Linux/Unix, Mac OS X, e demais extenses Linux sem que seja necessrio fazer

    alteraes de cdigo. Agora, dois membros da TrollTech lhe oferecem este guia completo para quevoc alcance resultados surpeendentes com a mais recente verso do Qt: Qt 4.3.

    Carregado com exemplops prticos e realistas e IN-DEPH ADVICE, este o livro usado

    pela Trolltech para ensinar Qt para seus prprios novos funcionrios. Revisado e expandidoconstantemente, este livro nos revela os melhores padres atuais para se trabalhar com Qt paradiversos usos, que vo desde implementao de arquiteturas de modelagem at o uso da enginegrfica do Qt 4.3. Voc encontrar solues para diversas tarefas de desenvolvimento GUI, assimcomo tcnicas sofisticadas para sistemas com acesso a banco de dados, integrao com XML, usode subclasses, composio, e muito mais. Seja voc um novo usurio de Qt, ou um usurio antigoque est aprendendo a nova verso, este livro certamente vai lhe ajudar a tirar vantagem de tudoque o Qt 4.3 capaz de fazer.

    Eis algumas novidades que encontraro neste livro:

    Atualizado completamente, com um novssima cobertura de Databases, XML, eprogramao Qtopia

    Notificaes e cobertura de tudo que mudou do Qt 4.2 para 4.3, incluindo Integraocom Windows Vista, suporte nativo a CSS para estilizao de aplicativos, e gerao dearquivos SVG

    Captulos separados para assuntos relacionados a 2D e 3D, cobertura das novas classes

    de visualizao grfica do Qt 4.3, alm de uma cobertura total do QPainters OpenGL

    Novos captulos a respeito de otimizao look-and-feele sobre criao de scripts paraaplicaes

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Ilustra a arquitetura de visualizao e modelagem do Qt4, suporte a plugins, Manutenode Layout, processamento de eventos, classes containers, e muito mais

    Apresenta tcnicas avanadas vistas em nenhum outro livro - desde criao de plugins at

    interao com APIs nativas

    Inclui um novo apndice de Qt Jambi, a nova verso Java do Qt

    Tabela de ContedosParte 1: Qt Bsico

    Captulo 1: ComeandoOl QtFazendo conexesModelando WidgetsUsando Documentao de Referncia

    Captulo 2: Criando DialogsSubclasse QDialogSignals e SlotsDesign de um Dialog RpidoDialogs com mudana no TamanhoDialogs DinmicosClasses Dialog e Widget construdas

    Captulo 3: Criando Janelas PrincipaisSubclasse QMainWindow

    Criando Menus e Barras de FerramentasAjustando a Barra de StatusDesenvolvendo o Menu ArquivoUsando Dialogs

    Armazenando ConfiguraesDocumentos MltiplosMisturar Telas

    Captulo 4: Implementao da Funcionalidade da AplicaoO Widget CentralSubclasse QTableWidgetCarregando e SalvandoImplementao do Menu EditarImplementando os Outros MenusSubclasse QTableWidgetItem

    Captulo 5: Criando Widgets CustomizveisCustomizando Qt WidgetsSubclasse QtWidgetIntegrando Widgets Customizveis com Qt Designer

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Buffering DuploParte II: Qt Intermedirio

    Captulo 6: Manuteno de LayoutModelando Widgets em um FormLayouts Empilhados

    Splittersreas RolveisDOCK Janelas e Barras de ferramentas

    Parte I: O Bsico do Qt ( Por Danilo Domingos)

    1. Comeando Hello Qt

    Fazendo Conexes

    Alinhando Widgets

    Utilizando a Referncia

    Este captulo mostra como combinar C++ bsico com a funcionalidade disponibilizada

    porQt para criar algumas aplicaes de interface grfica pequenas. Este captulo tambmintroduz duas idias chave do Qt: signals e slots e layouts. No captulo 2, iremos mais a

    fundo, e no captulo 3, comearemos a construir aplicaes mais realsticas.Se voc j conhece Java ou C# mas tem uma experincia limitada com C++, ento recomendado que voc comece lendo o Apndice D Introduo ao C++.HELLO QT

    Vamos comear com um programa bem simples. Vamos estud-lo linha a linha e depoisver como compil-lo e rod-lo.

    1 #include 2 #include 3 int main(int argc, char *argv[])4 {5 QApplication app(argc, argv);

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    6 QLabel *label = new QLabel("Hello Qt!");7 label->show();8 return app.exec();9 }

    As linhas 1 e 2 incluem as definies das classes QApplication e QLabel. Para cadaclasse

    de Qt existe um arquivo header com o mesmo nome (e distino entre maisculas eminsculas) que contem a definio da classe.

    A linha 5 cria um objeto QApplication para gerenciar os recursos da aplicao no geral. Aconstrutora de QApplication requer os argumentos argc e argv porque Qt interpretaalguns argumentos de linha de comando prprios do Qt.

    A linha 6 cria um widget QLabel que mostra o texto Hello Qt!. No Qt e na terminologiaUnix, um widget um elemento visual numa interface grfica. O termo vem daexpresso window gadget e equivalente a tanto controle como container naterminologia do Windows. Botes, menus, barras de rolagem e frames so exemplos dewidgets. Widgets podem conter outros widgets; por exemplo, uma janela , geralmente,um widget que contem um QMenuBar, algumas QToolBars, uma QStatusBar, e algunsoutros widgets. A maioria das aplicaes usa uma QMainWindow ou um QDialog como

    janelas principais da aplicao, mas Qt to flexvel que qualquer widget pode ser umajanela. Neste exemplo, o widget QLabel a janela da aplicao.

    A linha 7 torna a label visvel. Widgets so criados, por padro, como invisveis para quepossamos customiz-los antes de serem exibidos, deste modo evitando flickering.

    A linha 8 passa o controle da aplicao para o Qt. Neste ponto, o programa entra nochamado loop de eventos. Imagine o loop de eventos como um modo de espera onde oprograma espera por aes do usurio como clicks do mouse ou ento pressionamentode teclas. Aes do usurio geram eventos (tambm chamados de mensagens) para

    osquais o programa responde, geralmente executando uma ou mais funes. Por exemplo,quando o usurio clica em um widget, os eventos pressionamento do boto do mouse eliberao do boto do mouse so gerados. Neste ponto, aplicaes grficas diferemsignificativamente de programas BAT convencionais, nos quais praticamente sprocessam uma entrada, desenvolvem algum procedimento, e terminam sem interaohumana.Por simplicidade, ns no nos preocupamos em chamar o delete para o objeto QLabel

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    aofinal da funo main(). Este vazamento de memria (memory leak) inofensivo numprograma to pequeno, j que a memria alocada ser desalocada quando o programaterminar.J possvel testar o programa na sua mquina. Ele deve se parecer com o mostrado

    naFigura 1.1. Primeiro voc ter que instalar o Qt 4.3.2 (ou uma verso mais recente), esteprocedimento explicado no Apndice A. De agora em diante, vamos assumir que voctem uma cpia corretamente instalada do Qt e que o diretrio Bin est na sua varivelPATH de ambiente. (No Windows isso feito automaticamente pelo instalador do Qt)Voc tambm precisar que o cdigo deste programa esteja num arquivo hello.cpp nundiretrio chamado hello. Voc mesmo pode escrever o arquivo hello.cpp ou copi-lo dosexemplos que acompanham este livro, que est disponvel em

    examples/chap01/hello/hello.cpp. (Todo os exemplos esto disponveis no site do livro,http://www.informit.com/title/0132354160.)

    Figura 1.1 - Hello no Linux

    Do prompt de comando, v at o diretrio hello e digite:qmake project

    Para criar um arquivo projeto que independente da plataforma, e depois digite:qmake hello.pro

    Para criar um arquivo makefile especfico para a plataforma que est usando. (Aferramenta qmake discutida em mais detalhes no apndice B.) Digite make paraconstruir o programa. Rode-o digitando hello no Windows, ./hello no Unix, e openhello.app no Mac. Para terminar o programa, clique no boto fechar na barra de ttulo da

    janela.Se voc estiver usando o Windows e tiver instalado a verso Open Source do Qt e o

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    compilador MinGW, voc ter um atalho chamado prompt de comando do Qt que temtodas as variveis de ambiente corretamente ajustadas. Se voc conseguiu visualizar a

    janela ento voc pode compilar aplicaes do Qt utilizando qmake e make comodescritos anteriormente. Os executveis so colocados na pasta debug ou release daaplicao (por exemplo, C:\examples\chap01\hello\release\hello.exe).Se voc estiver utilizando o Microsoft Visual C++ com uma vero comercial de Qt, vocutilizar o nmake ao invs de make. Alternativamente, voc pode criar um arquivoprojeto do Visual Studio a partir do arquivo hello.cpp digitando:qmake -tp vc hello.pro

    Antes de irmos para o prximo exemplo vamos nos divertir um pouco: Substitua a linha

    QLabel *label = new QLabel("Hello Qt!");

    QLabel *label = new QLabel("Hello " "Qt!");

    E recompile a aplicao. Quando rodar, ela deve parecer com a Figura 1.2. Como esteexemplo ilustra, fcil diferenciar uma aplicao de interface de usurio Qt utilizandoapenas uma formatao HTML.

    Figura 1.2: Uma label com formatao HTML bsica

    FAZENDO CONEXES

    O Segundo exemplo mostra como responder s aes do usurio. A aplicao consisteem um boto que o usurio pode clicar para sair. O cdigo muito similar ao exemploanterior, com exceo do uso de um QPushButton no lugar de uma QLabel como nossowidget principal, e ns estamos conectando a ao do usurio (clique) a um bloco decdigo.O cdigo desta aplicao est em examples/chap01/quit/quit.cpp; a aplicao emandamento mostrada na Figura 1.3. Aqui est o contedo do arquivo:1 #include

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    2 #include

    3 int main(int argc, char *argv[])

    4 {

    5 QApplication app(argc, argv);

    6 QPushButton *button = new QPushButton("Quit");

    7 QObject::connect(button, SIGNAL(clicked()),

    8 &app, SLOT(quit()));

    9 button->show();

    10 return app.exec();

    11 }

    Os widgets de Qt emitem sinais para indicar que uma ao de usurio ou uma mudanade estado ocorreu. [*] Por exemplo, QPushButtonemite um sinal clicked()quando ousurio clica no boto. Um sinal pode se conectar com uma funo (chamada de slotnesse contexto) para que quando o sinal for emitido, o slot seja executadoautomticamente. No nosso exemplo, nos conectamos o sinal clicked() do boto para oslot quit()do objeto QApplication. Os macros SIGNAL()e SLOTS()fazem parte dasintaxe.Vamos construir a aplicao. Assumimos que voc criou um diretrio chamado quitcontendo o arquivo quit.cpp. Rode o qmake no diretrio quit para gerar o arquivoprojeto, e depois rode-o denovo para gerar o makefile, como segue:qmake -project

    qmake quit.pro

    Agora construa a aplicao e rode-a. Se voc clicar em Quit, ou pressionar a barra deespao (que pressiona o boto), a aplicao terminar.

    ALINHANDO WIDGETSNesta seo, iremos criar um pequeno exemplo que demonstra como usar layouts paragerenciar a geometria dos widgets em uma janela e como usar sinais e slots para

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    sincronizar dois widgets. A aplicao (mostrada na Figura 1.4) pergunta pela idade dousurio, a qual o usurio pode informar manipulando um spin box ou um slider.

    A aplicao consiste em trs widgets: um QSpinBox, um QSlider e um QWidget. OQWidget a janela principal da aplicao. O QSpinBox e o QSlider so apresentadosdentro da QWidget; eles so filhos de QWidget. Alternativamente, podemos dizer que

    QWidget pai de QSpinBox e QSlider. QWidget no tem pais porque est sendo usadacomo uma janela top-level. As construtoras de QWidget e de todas as suas subclassestem QWidget * como parmetro que especifica quem o pai da widget em questo.Cdigo Fonte:1 #include

    2 #include

    3 #include

    4 #include

    5 int main(int argc, char *argv[])6 {

    7 QApplication app(argc, argv);

    8 QWidget *window = new QWidget;

    9 window->setWindowTitle("Enter Your Age");

    10 QSpinBox *spinBox = new QSpinBox;

    11 QSlider *slider = new QSlider(Qt::Horizontal);

    12 spinBox->setRange(0, 130);

    13 slider->setRange(0, 130);

    14 QObject::connect(spinBox, SIGNAL(valueChanged(int)),

    15 slider, SLOT(setValue(int)));

    16 QObject::connect(slider, SIGNAL(valueChanged(int)),

    17 spinBox, SLOT(setValue(int)));

    18 spinBox->setValue(35);

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    19 QHBoxLayout *layout = new QHBoxLayout;

    20 layout->addWidget(spinBox);

    21 layout->addWidget(slider);

    22 window->setLayout(layout);

    23 window->show();

    24 return app.exec();

    25 }

    As linhas 8 e 9 preparam a QWidget que servir como a janela principal da aplicao.Podemos chamar setWindowTitle() para escolher o texto que ser exibido na barra dettulo da janela.

    As linhas 10 e 11 criam um QSpinBox e um QSlider, e as linhas 12 e 13 atribuem seusintervalos validos. Podemos assumir que o usurio tem at 130 anos de idade.

    Poderamos passar window para as construtoras de QSpinBox e QSlider especificandoque estes widgets tivessem window como pai deles, mas no necessrio porque osistema de layout ir configurar isso sozinho e automaticamente atribuir o pai do spinbox e do slider, como veremos a seguir.

    As duas chamadas QObject::connect() mostradas nas linhas 14 at 17 asseguram que ospin Box e o slider estejam sincronizados para que eles sempre mostrem o mesmo valor.Sempre que o valor de um dos widgets mudar, o sinal valueChanged() de um deles seremitido, e o slot setValue(int) do outro ser chamado com o novo valor.

    A linha 18 predefine o valor do spin Box para 35. Quando isso acontece, o QSpinBoxemite o sinal valueChanged(int) com um argumento do tipo int valendo 35. Esseargumento passado para o slot setValue(int) do QSlider, que ajusta o valor do sliderpara 35. O slider ento emite um sinal valueChanged(int) porque o prprio valor mudou,ativando o slot setValue(int) do spin Box. Mas nesse ponto, setValue(int) no emitenenhum sinal, j que o valor do spin Box j 35. Isso evita a recurso infinita. A Figura1.5 ilustra a situao.

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Nas linhas 19 at 22, ns alinhamos o spin box e o slider usando um gerenciador delayouts. Este gerenciador um objeto que define o tamanho e a posio dos widgets que

    esto sob sua responsabilidade. Qt tem trs tipos principais de gerenciadores de layouts: QHBoxLayout alinha os widgets horizontalmente da esquerda para a direita (dadireita para a esquerda para algumas culturas). QVBoxLayoutalinha os widgets verticalmente de cima para baixo. QGridLayoutalinha os widgets em um grid.

    A chamada de QWidget::setLayout()na linha 22 instala o gerenciador na janela. Mas na

    verdade, o QSpinBoxe o QSlidertm seu pai redefinido para o widget no qual o layoutfoi instalado, e por essa razo no temos que especificar um pai explicito quandocostrurmos a widget que ser colocada em um layout.

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Apesar de no termos escolhido a posio e o tamanho dos widgets explicitamente, oQSpinBoxe o QSliderso dispostos visualmente de modo agradvel de um lado at ooutro. Isso ocorre porque QHBoxLayoutautomaticamente designa posies e tamanhos

    razoveis para os widgets dos quais responsvel, baseado nas necessidades deles.Os

    gerenciadores de layouts nos privam da ocupao de posicionar, por puro cdigo, osobjetos na tela e garantem que a janela se redimensione suavemente.O modo apresentado por Qt para construir interfaces de usurio simples de entender e muito flexvel. O procedimento mais comum que programadores Qt utilizam instanciar os widgets necessrios e depois definir suas propriedades conformenecessrio. Programadores adicionam widgets aos layouts, que automaticamente

    cuidam

    do posicionamento e redimensionamento. O comportamento da interface de usurio gerenciada conectando widgets uns aos outros usando o mecanismo de sinais e slots.

    As screenshots tiradas at agora foram tiradas no Linux, mas aplicaes Qt somostradas com a interface nativa de cada plataforma. Qt consegue fazer issoemulando o look and feel de cada plataforma, ao invs de conter um kit dewidgets de uma plataforma particular.

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    O estilo Plastique o estilo padro para aplicaes Qt/X11 rodando sob o KDE,e o Cleanlooks o padro sob o GNOME. Estes estilos utilizam gradientes eanti-aliasing para gerar um look nfeel moderno. Usurios de aplicaes Qtpodem substituir os estilos padro utilizando o comando style na linha de

    comando. Por exemplo, para iniciar a aplicao de idade acima utilizando oestilo Motif sob X11, simplesmente digite o comando:./age -style motif

    Diferente dos outros estilos, Windows XP, Windows Vista, e Mac apenas sovisualizados nas plataformas nativas, j que dependem e dispositivos de tema

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    de cada plataforma.Um estilo adicional chamado QtDotNet esta disponvel no Qt Solutions. Tambm possvel criar estilos customizados, como ser explicado no Captulo 19.UTILIZANDO A REFERNCIA

    A documentao de referncia do Qt uma ferramenta essencial para qualquerdesenvolvedor. Ela cobre todas as classes e funes no Qt. Esse livro faz o uso dediversas classes e funes do Qt, mas no cobre todas elas e nem fornece todos osdetalhes das que so mencionadas. Para tirar proveito mximo do Qt, voc deve sefamiliarizar com a documentao do Qt o mais rpido possvel.

    A documentao est disponvel em HTML no diretrio doc/HTML do Qt e pode ser lida

    atravs de qualquer browser. Voc tambm pode usar o Qt Assistant, o browser deajudado Qt, que tem recursos poderosos de busca e indexao que o tornam mais rpido efcil comparado com um web browser.Para iniciar o Qt Assistant, clique em Qt by Trolltech v4.x.x|Assistantno Windows, digiteassistant na linha de comando no Unix, ou d um duplo-clique em Assistant na busca doMac. Os links na seo Referncia API na pgina inicial fornecem diferentes modos denavegar pelas classes de Qt. A pgina Todas as classes list todas as classes na API doQt. A pgina Classes principais lista apenas as classes mais utilizadas de Qt. Como um

    exerccio, procure as classes e funo que utilizamos neste captulo.

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Note que funes herdadas so documentadas na classe base; por exemplo,QPushbutton no tem uma funo prpria show(), mas herda uma de QWidget.A Figura1.9mostra como as classes que vemos at agora se relacionam umas com as outras.

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    A documentao de referncia para a atual verso do Qt e para algumas verses maisrecentes est disponvel online em http://doc.trolltech.com/.Este site tambm temartigos selecionados do Qt Quarterly, o newsletter dos programadores Qt enviado paratodas as licenas comerciais.Este captulo introduziu os conceitos chave de conexes signal-slot e layouts. Eletambm comeou a revelar a perspectiva de total e consistente de orientao a objetosat construo e uso de widgets. Se voc procurar pela documentao do Qt, voc

    encontrar uma uniformidade de exibio que a torna bem direta no que se diz respeitoao uso de novos widgets, e voc tambm descobrir que Qt escolheu cuidadosamente

    osnomes para funes, parmetros, enums e assim por diante, que fazem com queprogramar em Qt se torne incrivelmente agradvel e fcil.Os captulos seguintes da parte 1 se apiam nos fundamentos aqui abordados,mostrando como criar uma GUI completa com menus, toolbars, janelas de documentos,status bars, e dialogs, em conjunto com a funcionalidade bsica de leitura,

    processamento e escritura de arquivos.

    2. Criando Dialogs

    Herdando de QDialog

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Signals e Slots a Fundo

    Design Rpido de Dialogs

    Modificando a Forma dos Dialogs

    Dialogs Dinmicos

    Classes Nativas de Widgets e Dialogs

    Este captulo vai te ensinar como criar caixas de dilogo utilizando Qt. Caixasde dilogo apresentam aos usurios opes e escolhas, e permitem que eles ajustemopes dos seus parmetros preferidos e que faam suas escolhas. Eles sochamados de caixas de dilogo, ou apenas dialogs, porque eles fornecem os meiospelos quais os usurios conversam com as aplicaes.

    A maioria das aplicaes GUI (graphics user interface, ou interface grfica deusurio) consiste em uma mainwindow com um menubar e uma toolbar, em conjuntocom dezenas de dialogs que complementam a mainwindow. Tambm possvel

    criar dialogs que respondam diretamente s escolhas do usurio aplicando as aesnecessrias (por exemplo, uma calculadora).Criaremos nosso primeiro dialog puramente por cdigo e mostrar como funciona.

    Depois veremos como criar dialogs pelo Qt Designer, a ferramenta visual de design doQt. Utilizar o Qt designer um jeito muito mais rpido (do que cdigo puro) e faz comque seja fcil testar designs diferentes e at mesmo modificar designs j existentes nofuturo.

    Herdando de QDialog

    Nosso primeiro exemplo um dialog de busca escrito totalmente em C++. Ele mostrado na Figura 2.1. Vamos implementar o dialog como uma classe prpria.Fazendo isso, a tornamos independente, um componente encapsulado, com signals eslots prprios.

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    O cdigo fonte est dividido em dois arquivos: finddialog.h e finddialog.cpp.

    Comearemos pelo header (finddialog.h):

    1 #ifndef FINDDIALOG_H

    2 #define FINDDIALOG_H

    3 #include

    4 class QCheckBox;

    5 class QLabel;

    6 class QLineEdit;

    7 class QPushButton;

    As linhas 1 e 2 (e 27) protegem o header contra mltiplos includes.

    A linha 3 inclui a definio de QDialog, a classe base para dialogs em Qt.QDialog derivado de QWidget.

    A linha 4 at 7 apresenta foward declarations das classes de Qt que sero

    utilizadas na implementao do dialog (em finddialog.cpp). [*] Uma foward declarationdiz ao compilador C++ que esta classe existe sem dar mais detalhes sobre a definioda classe (normalmente localizada no header da classe). Voltaremos a falar disso embreve.

    Depois, definimos FindDialog como uma subclasse de QDialog:

    8 class FindDialog : public QDialog

    9 {

    10 Q_OBJECT

    11 public:

    12 FindDialog(QWidget *parent = 0);

    O macro Q_OBJECT no comeo da definio da classe necessrio para todas

    as classes que definem seus prprios signals e slots.[*] Foward declarations s podem ser utilizadas quando as variveis forem

    ponteiros. O compilador no precisa, de inicio, de mais informaes sobre a classe. Jque todos os ponteiros tem tamanho fixo: 4 bytes.

    A construtora de FindDialog um exemplo tpico de classes Qt. O parmetroparent especifica o widget pai. O padro para este parmetro um ponteiro nulo,significando que o widget no tem pai.

    13 signals:

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    14 void findNext(const QString &str, Qt::CaseSensitivity cs);

    15 void findPrevious(const QString &str, Qt::CaseSensitivity cs);

    A seo signal declara dois sinais que o dialog emitir quando o usurio clicar

    no boto Find. Se a opo Search Backward estiver selecionada, o dialog emite

    findPrevious() caso contrrio, emite findNext().A palavra-chave signals , na verdade, um macro. O pr-processador C++

    converte-o para padres C++ antes que o compilador veja. Qt::CaseSensitivity umenum que pode assumir os valores Qt::CaseSensitive (um) e Qt::CaseInsensitive(zero).

    16 private slots:

    17 void findClicked();

    18 void enableFindButton(const QString &text);

    19 private:

    20 QLabel *label;

    21 QLineEdit *lineEdit;

    22 QCheckBox *caseCheckBox;

    23 QCheckBox *backwardCheckBox;

    24 QPushButton *findButton;

    25 QPushButton *closeButton;

    26 };

    27 #endif

    Na seo privada da classe, declaramos dois slots. Para implementar osslots, precisaremos acessar a maioria dos widgets filhos do dialog, ento mantemosponteiros para eles tambm. A palavra-chave slot , como signals, um macro que setransforma em uma construo que C++ pode digerir.

    Para as variveis private, usamos foward declarations das respectivas

    classes. Isso foi possvel porque so todos ponteiros e no precisamos acess-los noheader, ento o compilador no precisa de todas as definies da classe. Poderamoster includo os includes (, , etc.), mas utilizando fowarddeclarations quando

    possvel torna o tempo de compilao menor.

    Vamos para o arquivo da implementao da classe FindDialog, finddialog.cpp:1 #include

    2 #include "finddialog.h"

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Primeiramente inclumos , um arquivo header que contm a definiodas classes GUI de Qt. Qt consiste de vrio mdulos, cada um com sua prpria livraria.O mdulos mais importantes so QtCore, QtGui, QtNetwork, QtOpenGL, QtScript,QtSql, QtSvg e QtXml. O header contem a definio de todas as classes queso partedos mdulos QtCore e QtGui. Incluir este header nos economiza a incluso individualde cada classe do nosso dialog.

    No arquivo finddialog.h, ao invs de incluir e utilizar fowarddeclarations para QCheckBox, QLabel, QLineEdit e QPushButton, poderamossimplesmente ter includo . Entretanto no aconselhvel incluir umarquivo header to grande, especialmente em aplicaes grandes.

    3 FindDialog::FindDialog(QWidget *parent)

    4 : QDialog(parent)5 {

    6 label = new QLabel(tr("Find &what:"));

    7 lineEdit = new QLineEdit;

    8 label->setBuddy(lineEdit);

    9 caseCheckBox = new QCheckBox(tr("Match &case"));

    10 backwardCheckBox = new QCheckBox(tr("Search &backward")

    );

    11 findButton = new QPushButton(tr("&Find"));

    12 findButton->setDefault(true);

    13 findButton->setEnabled(false);14 closeButton = new QPushButton(tr("Close"));

    Na linha 3, passamos o parmetro parent para a construtora da classe base.

    Depois criamos os objetos filhos. A funo tr() marca a string literal para futurastradues para outras lnguas. Esta funo declara em QObject e em todas asclasses que contem o macro Q_OBJECT. um bom habito cercar strings visveisaos usurios com tr(), mesmo que voc no tenha planos imediatos para traduzir suaaplicao para outras lnguas. Tradues sero estudadas no Captulo 18.

    Em strings literais, utilizamos o smbolo & para indicar teclas de atalho. Por

    exemplo, a linha 11 cria o boto Find, o qual o usurio pode ativar utilizando Alt+F nasplataformas que suportam teclas de atalho. O smbolo & tambm pode ser utilizadopara controlar o foco: na linha 6 criamos uma label com a tecla de atalho (Alt+W), ena linha 8 nos definimos o lineedit como companheiro (buddy) da label. Um buddy um widget que aceita o foco quando a tecla de atalho do outro pressionada. Entoquando o usurio pressiona Alt+W (atalho da label), o foco vai para o lineedit (buddy da

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    label).Na linha 12, fazemos com que o boto Find seja o padro chamando

    setDefault(true). O boto padro o boto que, quando o usurio pressiona Enter, pressionado. Na linha 13, desabilitamos o boto Find. Quando um widget estdesabilitado ele geralmente mostrado em tons acinzentados e no responder sinteraes do usurio.

    15 connect(lineEdit, SIGNAL(textChanged(const QString &)),

    16 this, SLOT(enableFindButton(const QString &)));

    17 connect(findButton, SIGNAL(clicked()),

    18 this, SLOT(findClicked()));

    19 connect(closeButton, SIGNAL(clicked()),

    20 this, SLOT(close()));

    O slot privado enableFindButton(const QString &) chamado sempre que otexto do lineedit mudar. O slot privado findClicked() chamado quando o usurioclicar no boto Find. O dialog se fecha quando o usurio clicar em Close. O slotclose() herdado de QWidget, e o seu comportamento padro esconder o widget devisualizao (sem deletlo). Estudaremos o cdigo para os slots enableFindButton() efindClicked() mais adiante.

    J que QObject um dos ancestrais do nosso dialog, ento podemos omitir o

    prefixo QObject:: das chamadas de connect().

    21 QHBoxLayout *topLeftLayout = new QHBoxLayout;

    22 topLeftLayout->addWidget(label);

    23 topLeftLayout->addWidget(lineEdit);

    24 QVBoxLayout *leftLayout = new QVBoxLayout;

    25 leftLayout->addLayout(topLeftLayout);

    26 leftLayout->addWidget(caseCheckBox);

    27 leftLayout->addWidget(backwardCheckBox);

    28 QVBoxLayout *rightLayout = new QVBoxLayout;

    29 rightLayout->addWidget(findButton);

    30 rightLayout->addWidget(closeButton);

    31 rightLayout->addStretch();

    32 QHBoxLayout *mainLayout = new QHBoxLayout;

    33 mainLayout->addLayout(leftLayout);

    34 mainLayout->addLayout(rightLayout);

    35 setLayout(mainLayout);

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Depois disso, ns alinhamos os widgets filhos utilizando gerenciadoresde layout. Layouts podem conter ambos widgets ou outros layouts. MisturandoQHBoxLayouts, QVBoxLayout e QGridLayout, possvel gerar dialogs bemsofisticados.

    Para nosso dialog, usaremos dois QHBoxLayout e dois QVBoxLayout, comomostrados na Figura 2.2. O layout externo o principal; ele instalado no FindDialogna linha 35 e responsvel por toda a rea do layout. Os outros trs layouts sosub-layouts. A pequena mola na parte inferior direita da Figura 2.2. um spacer(ou stretch). Ele usa o espao vazio abaixo dos botes Find e Close, garantindo queesses botes ocupem o topo do layout em que esto.

    Um aspecto sutil de classes de gerenciamento de layouts que no so

    widgets. Ao invs disso, so derivadas de QLayout. Que por sua vez derivadode QObject. Na figura, widgets so representados por linhas solidas e layouts sorepresentados por linhas tracejadas para destacar a diferena entre eles. Durante aexecuo do programa, layouts so invisveis.

    Quando sub-layouts so adicionados ao layout pai (linhas 23, 33 e 34), os sub-layouts tm seus pais redefinidos. Da, quando o layout principal instalado no dialog(linha 35), ele se torna filho do dialog e todos os widgets dentro dos layouts tm seus

    pais redefinidos como o dialog. A hierarquia resultante mostrada na Figura 2.3.36 setWindowTitle(tr("Find"));

    37 setFixedHeight(sizeHint().height());

    38 }

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Finalmente, definimos o titulo a ser mostrado na barra de ttulo e uma altura

    fixa para a janela, j que no existem widgets dentro do dialog que possam ocupar umespao vertical significativo. A funo QWidget::sizeHint() retorna o tamanho ideal dowidget.

    Isso completa a reviso da construtora da classe FindDialog. J que criamos

    os objetos e layouts atravs de new, razovel pensar que devemos deletar cadawidget e layout com um delete. Mas no necessrio, Qt automaticamente deletaobjetos filhos quando o pai destrudo, e todos os widgets e layouts do nosso dialogso descendentes do prprio dialog.

    Agora, vamos definir os slots do dialog:39 void FindDialog::findClicked()

    40 {

    41 QString text = lineEdit->text();42 Qt::CaseSensitivity cs =

    43 caseCheckBox->isChecked() ? Qt::CaseSensitive

    44 : Qt::CaseInsensitive;

    45 if (backwardCheckBox->isChecked()) {

    46 emit findPrevious(text, cs);

    47 } else {

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    48 emit findNext(text, cs);

    49 }

    50 }

    51 void FindDialog::enableFindButton(const QString &text)

    52 {

    53 findButton->setEnabled(!text.isEmpty());

    54 }

    O slot FindClicked chamado quando o usurio clica no boto Find. Ele emite osinal findPrevious() ou findNext(), dependendo da opo Search Backward. A palavra-chave emit especfica do Qt; como outras extenses Qt ela convertida em C++padro pelo pr-processador C++. O slot enableFindButton() chamado sempre queo usurio muda o texto contido no lineedit. Isso ativa o boto se houver algum texto nolineedit, e desabilita caso contrrio. Estes dois slots finalizam o dialog. Podemos, ento,

    criar um main.cpp para testar nosso widget FindDialog:1 #include

    2 #include "finddialog.h"

    3 int main(int argc, char *argv[])

    4 {

    5 QApplication app(argc, argv);

    6 FindDialog *dialog = new FindDialog;

    7 dialog->show();

    8 return app.exec();

    9 }

    Para compilar o programa, utilize qmake como de usual. Uma vez que adefinio da classe FindDialog contem o macro Q_OBJECT, ento o makefile geradopelo qmake incluir regras especiais para executar o moc, o meta-object compiler doQt. (O sistema meta-object ser estudado na prxima seo).

    Para que o moc funcione corretamente necessrio colocar a definio daclasse em um arquivo header, fora da implementao. O cdigo gerado pelo moc incluiesse arquivo header e adiciona alguns cdigos padres do C++ por si prprio.

    Classes q utilizam o macro Q_OBJECT devem ser executadas pelo moc. Issono um problema porque qmake automaticamente adiciona as regras necessriaspara o makefile. Mas se voc esquecer de gerar seu makefile usando qmake e o mocno tiver rodado, o linker reclamar dizendo que algumas funes foram declaradasmas no

    implementadas. As mensagens podem ser relativamente obscuras. O GCCproduz mensagens de erro desse tipo:

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    finddialog.o: In function `FindDialog::tr(char const*, char

    const*)':

    /usr/lib/qt/src/corelib/global/qglobal.h:1430: undefined

    reference to

    `FindDialog::staticMetaObject'

    A sada do Visual C++ comea assim:finddialog.obj : error LNK2001: unresolved external symbol

    "public:~virtual int __thiscall MyClass::qt_metacall(enum

    QMetaObject

    ::Call,int,void * *)"

    Se isso acontecer com voc algum dia, execute o qmake de novo para atualizaro arquivo makefile, e reconstrua a aplicao.Fornecer uma ordem razovel para a tecla tab e outros atalhos garante que

    usurios que no querem (ou que no podem) usar um mouse sejam capazes deusar ao mximo a aplicao. Controle total sobre o teclado tambm apreciado pordigitadores rpidos.

    No Captulo 3, ns usaremos o dialogo de busca numa aplicao real, e ns

    conectaremos os sinais findPrevious() e findNext() a alguns slots.

    Signals e Slots a Fundo

    O mecanismo de sinais e slots fundamental para programao em Qt. Elepermite que o programador estabelea um elo entre os objetos sem que os objetossaibam uns dos outros. Ns j conectamos alguns sinais e slots, declaramos nossosprprios sinais e slots, implementamos nossos slots e emitimos nossos sinais. Vamosdar uma olhada no mecanismo mais de perto.

    Slots so quase idnticos a funes membro ordinrias do C++. Elas podemser virtuais, podem ser sobrecarregadas, podem ser publicas, protecteds ou privates,podem ser diretamente chamadas como qualquer outra funo membro do C++, e osseus parmetros podem ser de qualquer tipo. A diferena que um slot tambm podeser conectado a um sinal, que no caso ser chamado toda vez que o sinal for emitido.

    A declarao da funo connect() se d da seguinte forma:

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    connect(sender, SIGNAL(signal), receiver, SLOT(slot));

    Onde sender e receiver so ponteiros para QObjects e signal e slot soassinaturas de funes sem nomes de parmetros. Os macros SIGNAL() e SLOT()

    essencialmente convertem seus argumentos para uma string.

    Nos exemplos que vimos at agora, ns sempre conectamos sinais diferentescom slots diferentes. Existem outras possibilidades:

    Um sinal pode ser conectado a vrios slots:connect(slider, SIGNAL(valueChanged(int)),

    spinBox, SLOT(setValue(int)));

    connect(slider, SIGNAL(valueChanged(int)),this, SLOT(updateStatusBarIndicator(int)));

    Quando o sinal emitido, os slots so chamados um a um, numa ordem noespecificada.

    Vrios sinais podem ser conectados ao mesmo slot:

    connect(lcd, SIGNAL(overflow()),

    this, SLOT(handleMathError()));

    connect(calculator, SIGNAL(divisionByZero()),this, SLOT(handleMathError()));

    Quando qualquer dos sinais for emitido, o slot chamado.

    Um sinal pode ser conectado a outro sinal:

    connect(lineEdit, SIGNAL(textChanged(const QString &)),

    this, SIGNAL(updateRecord(const QString &)));

    Quando o primeiro sinal emitido, o Segundo sinal tambm emitido. Almdisso, conexes signal-signal so indistinguveis de conexes signal-slot.

    Conexes podem ser removidas:

    disconnect(lcd, SIGNAL(overflow()),

    this, SLOT(handleMathError()));

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Isso raramente necessrio, porque Qt automaticamente remove todas as

    conexes envolvendo um objeto quando ele deletado.Para conectar um sinal a um slot com sucesso (ou outro signal), eles precisam

    ter os mesmos tipos de parmetros na mesma ordem:connect(ftp, SIGNAL(rawCommandReply(int, const QString &)),

    this, SLOT(processReply(int, const QString &)));

    Excepcionalmente, se um signal tem mais parmetros que o slot ao qual est

    conectado, os parmetros adicionais so simplesmente ignorados.connect(ftp, SIGNAL(rawCommandReply(int, const QString &)),

    this, SLOT(checkErrorCode(int)));

    Se os tipos de parmetros so incompatveis, ou se o sinal ou slot no existir,

    Qt ira informar atravs de um warning em tempo de execuo (se a aplicao forconstruda no modo debug). Similarmente, Qt ir lanar um warning se os nomes dosparmetros estiverem inseridos nas assinaturas dos signals ou slots.

    At agora, apenas utilizamos sinais e slots com widgets. Mas o mecanismo

    implementado para QObject e no limitado a programao GUI. O mecanismo podeser usado por qualquer subclasse de QObject:

    class Employee : public QObject

    {

    Q_OBJECT

    public:

    Employee() { mySalary = 0; }

    int salary() const { return mySalary; }

    public slots:

    void setSalary(int newSalary);

    signals:

    void salaryChanged(int newSalary);private:

    int mySalary;

    };

    O Sistema Meta-Object de Qt

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Uma das maiores conquistas do Qt foi a extenso do C++ com um mecanismode criao de componentes de software independentes que podem ser ligados semnem saberem informaes sobre o componente aos quais esto conectados.

    O mecanismo chamado sistema meta-object e fornece dois servios chave:

    signals e slots, e introspeco. A funcionalidade da introspeco necessria paraimplementar signals e slots, e permite programadores obterem informaes metasobre sub-classes QObject em tempo de execuo, incluindo a lista de sinais e slotssuportados pelo objeto e nome da classe. O mecanismo tambm suporta propriedades(amplamente usadas pelo Qt Designer) e traduo de texto (para internacionalizao),e estabelece as bases do mdulo QtScript. A partir do Qt 4.2, propriedades podem seradicionadasdinamicamente, um recurso que veremos em ao nos captulos 19 e 22.

    O C++ padro no fornece suporte para as meta-informaes dinmicasque o sistema de meta-objeto de Qt precisa. Qt resolve isso com uma ferramentaseparada, o moc. Ele analisa as definies de Q_OBJECT e faz com que a informaofique disponvel atravs de funes C++. J que o moc implementa toda a suafuncionalidade usando C++ ento o sistema meta-objeto funciona com qualquercompilador C++.

    O mecanismo funciona da seguinte forma: O macro Q_OBJECT declara algumas funes de introspeco que devem ser

    implementadas em cada subclasse de QObject: metaObject(), tr(), qt_metacall(), entreoutras.

    A ferramenta moc gera implementaes para as funes declaradas porQ_OBJECT e para todos os signals.

    As funes membro de QObject (como connect() e disconnect() ) usam as

    funes de introspeco para fazer seus trabalhosTudo isso feito automaticamente pelo qmake, moc e QObject, ento

    voc dificilmente ter que pensar nisso. Mas se estiver curioso voc pode ler adocumentao da classe QMetaObject e os cdigos C++ gerados pelo moc para vercomo a implementao funciona.

    void Employee::setSalary(int newSalary)

    {

    if (newSalary != mySalary) {

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    mySalary = newSalary;

    emit salaryChanged(mySalary);

    }

    }

    Perceba como o slot setSalary() implementado. Ns emitimos o sinalsalaryChanged() apenas se newSalary != mySalary. Isso garante que as conexescclicas no levem a loops infinitos.

    Design Rpido de DialogsQt foi planejado para ser agradvel e intuitivo para desenvolver cdigo, e no

    difcil encontrar programadores que desenvolvem suas aplicaes inteiras escrevendocdigo C++. Porm, muitos programadores preferem utilizar uma aproximao visual

    para desenvolver formulrios. Porque eles acham que este mtodo mais natural erpido do que puro cdigo, e eles querem estar aptos a testar e mudar designs commais rapidez e facilidade do que quando desenvolvidos com cdigos puros.

    O Qt Designer expande as opes disponveis aos programadores fornecendo

    uma capacidade visual de design. Qt Designer pode ser usado para desenvolvertodos ou apenas alguns dos formulrios da aplicao. Formulrios que so criadosutilizando o Qt Designer so convertidos em cdigo C++, ento o Qt Designer pode serusado com uma variedade de ferramentas convencionais e no impe especificaesespeciais ao compilador.

    Nessa seo, usaremos o Qt Designer para criar o dilogo Ir para a clula

    mostrado na Figura 2.4. Criar o dialog no Qt Designer ou por cdigo sempre envolvealguns passos fundamentais:

    1. Criar e inicializar widgets filhos.

    2. Coloc-los em um layout.

    3. Atribuir a ordem dos tabs.

    4. Estabelecer conexes signal/slots.

    5. Implementar os prprios slots do dialog.

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Para iniciar o Qt Designer, clique em Qt by Trolltech v4.x.y|Designer nomenu Iniciar, digite designer na linha decomando do Unix, ou d um duplo-cliqueem Designer no MAC finder. Quando o Qt Designer iniciar, ele ir mostrar uma

    lista de templates. Clique no template Widget e depois clique em Create. (Otemplate Dialog with Buttons

    Bottom pode parecer tentador, mas para esse exemplo ns criaremos osbotes OK e Cancel manualmente e mostrar como feito.) Voc deve, agora, teruma janela chamada Untitled.

    Por padro, a interface de usurio do Qt consiste em vrias janelas top-level.Se voc preferir uma interface MDI (multiple document interface) com uma janela top-window e vrias subjanelas, como mostrado na Figura 2.5, clique em Edit|Preferences

    e ajuste o modo de interface do usurio para Docked Window.

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    O primeiro passo criar widgets filhos e coloc-los no formulrio. Criar umalabel, um line editor, um spacer horizontal, e dois botes. Para cada item, arraste onome ou o cone da caixa de widgets do Qt Designer e solte-o aproximadamente ondeele deveria estar no formulrio. O spacer, que invisvel no formulrio final, mostrado

    no QtDesigner como uma pequena mola azul.

    Agora arraste a borda inferior do formulrio pra encurt-lo. Isso deveria produzirum formulrio que similar ao da Figura 2.6. No gaste muito tempo posicionando ositens precisamente no formulrio. Os gerenciadores de layouts vo posicion-los deforma precisa posteriormente.

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Utilizando o editor de propriedades do Qt Designer ajuste as propriedades decada widget:

    1. Clique na label TextLabel. Certifique-se de que a propriedade objectNamedela seja label e mude a propriedade text para &Cell Location:.

    2. Clique no line editor. Certifique-se de que a propriedade objectName

    seja lineEdit.3. Clique no primeiro boto. Defina a propriedade objectName como okButton,

    a propriedade enabled para false, a propriedade text para OK, e a propriedadedefault para true.

    4. Clique no segundo boto. Defina a propriedade objectName

    para cancelButton e a propriedade texto para Cancel.5. Clique no fundo do formulrio para selecion-lo. Ajuste a propriedade

    objectName para GoToCellDialog e a propriedade windoTitle para Go to Cell.Todos os widgets parecem bem, exceto pela label que mostra &Cell Location.

    Escolha Edit|Edit Buddies para entrar em um modo especial de edio que te permiteescolher os Buddies. Depois, clique na tabela, mantenha o boto apertado e arrastea seta vermelha para o line Edit, e depois libere o boto. A label deveria exibir, agora,o texto Cell Location, como mostrado na Figura 2.7 e tem o line Edit com seu buddy.Para deixar o modo de edio de buddies clique em Edit|Edit Widgets.

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    O prximo passo alinhar os widgets no formulrio:

    1. Clique na label Cell Location , pressione a tecla Shift e clique no line Editpara selecionar os dois widgets. Clique em Form|Lay Out Horizontally.

    2. Clique no spacer, segure o Shift e clique em ambos os botes. Clique em

    Form|Lay Out Horizontally3. Clique no fundo do formulrio para remover a seleo anterior de qualquer

    widget, depois clique em Form|Lay Out Vertically.4. Clique em Form|Adjust Size para redimensionar o formulrio para o seu

    tamanho preferencial.

    As linhas vermelhas mostradas no formulrio mostram os layouts que foramcriados, como mostrado na Figura 2.8. Eles no so visveis quando o formulrio executado.

  • 5/21/2018 C Programando GUI Com Qt4 Segunda Edicao

    Agora clique em Edit|Edit Tab Order. Um nmero em um retngulo azul aparecerprximo de cada widget que possa admitir foco, como mostrado na Figura 2.9. Cliqueem cada widget para escolher a ordem de cada um, depois clique em Edit|Edit Widgetspara deixar o modo de edio de tabs.