Criado em 10/11/2010 às 22:58
Nesta parte do tutorial, vamos explorar um pouco as ferramentas do Qt Designer, sabendo como funcionam
as classes QHBoxLayout e QVBoxLayout por código. A partir de uma certa versão do Qt Creator, que eu não lembro
qual é, ele passou a incorporar o Designer dentro da sua interface possibilitando o desenvolvimento de
interfaces gráficamente dentro do creator. A maioria das screenshots abaixo foram tiradas utilizando o
Designer, mas faça o exemplo utilizando o Qt Creator.
Atenção: essa página tem umas 30 imagens de puro design, então faça uma pausa se estiver cansado!
Geometria Qtdesigniana
Abra o Qt Creator e abra um novo projeto:
File -> New File or Project
Uma janela parecida com a figura abaixo será mostrada:
Serão exibidos alguns modelos de aplicações. Sob a guia "Projects" (Qt C++ Project) escolha a opção "Qt GUI Application" (Qt Graphics User Interface Application).
A próxima janela te pergunta como será a "cara" da sua aplicação. O Qt já te dá as opções dos principais modos de janelas disponíveis (Dialog, Widget ou Mainwindow) então
se você vai fazer uma aplicação principal deve escolher mainwindow, mas como vamos apenas demonstrar as utilidades do designer então vamos criar um Dialog.
Não esqueça de deixar marcada a opção "Generate form" para que ele já crie um formulário vazio para que possamos usar.
Depois de clicar em "Next" mais algumas vezes, o Qt Creator abrirá uma interface de criação gráfica que nada mais é que o Qt Designer. O seu formulário está vazio e para começar a construir sua
interface gráfica basta começar a arrastar coisas pra dentro dele.
O que você pode ou não arrastar está localizado no lado esquerdo da janela sob algumas abas como "Layouts", "Spacers", "Item Views (Model Based)", "Containers", etc. Então para começar
arraste 2 GroupBoxes, 3 Radio Buttons, 2 Check Boxes e 2 Push Buttons. Posicione-os em lugares aleatórios como na imagem abaixo.
RadioButtons tem um comportamento muito interessante quando colocados dentro de um container (nesse caso, colocaremos dentro do GroupBox). Se três
RadioButtons estiverem dentro do mesmo container então apenas 1 deles poderá ser selecionado de cada vez. Se outro for selecionado o primeiro será descelecionado automaticamente.
Então arraste os RadioButtons para dentro de um dos GroupBoxes. Faça o mesmo para os CheckBoxes.
Dê uma olhadinha do outro lado da janela, o lado direito. Lá você encontra o "Object Inspector". Ele traz um esquema de hierarquia e dessa forma podemos saber quem é filho de quem. Observe também que a figura quer dizer que
nenhum layout foi aplicado ao formulário (Dialog), nem ao primeiro GroupBox, nem ao segundo GroupBox.
Observe também o "Property Editor". Ele traz informações importantes de cada widget arrastado para o formulário ao clicar em cada um. Ao clicar em um dos widgets do formulário o conteúdo do
"Property Editor" muda mostrando tanto as propriedades exclusivas do widget como propriedades herdadas de classes parent. Por exemplo, ao clicar no formulário, um dos GroupBoxes, um dos RadioButtons, um dos CheckBoxes e um dos PushButtons você tem a sequência
de propriedades abaixo.
Você pode acessar propriedades como o nome do objeto (presente na classe QObject, portanto todos eles tem essa propriedade) e escolher de que forma se referirá a esse objeto quando estiver escrevendo o código.
É aconselhável que você escolha nomes intuitivos para as propriedades objectName para evitar problemas do tipo "Qual era o nome daquele Widget mesmo??! Ahh! Lembrei!! RadioButton5112513332!"
Já que você já sabe se localizar na janela do designer, vamos começar a utilizar suas ferramentas. Primeiramente vamos aplicar layouts aos nossos widgets. Que tal começarmos alinhando verticalmente os nossos RadioButtons (QVBoxLayout)?
Selecione os 3 RadioButtons (pode ser tanto pelo Object Inspector quanto pelo formulário) -> Clique na ferramenta Layout Vertically (alinhar verticalmente)
Você perceberá que uma linha vermelha será criada ao redor dos objetos recem alinhados representando o Layout vertical. Essa linha é uma ferramenta visual e não será exibida quando o programa estiver em execução.
Bem, na verdade, nós não precisávamos aplicar o layout vertical aos 3 widgets que estão dentro do container GroupBox. Bastava aplicar o layout vertical ao próprio container que o layout já é aplicado às filhas! Então vamos fazer um serviço bem feito. Selecione o layout (linha vermelha) recém adicionada
e clique em "Break Layout" (Passos 1 ou 2, e 3). Se tiver dificuldade em clicar no layout pelo formulário, não hesite em usar o "Object Inspector". Perceba que o "Object Inspector" ajuda muito na organização dos seus widgets.
Agora ao invés de aplicar o layout vertical aos widgets internos, aplique-o a ambos os GroupBoxes (containers). O resultado está representado na figura da direita.
-->
Agora chega de mamata, brinque com os layouts (horizontais e verticais) até conseguir reproduzir a imagem abaixo. Obs: apenas 5 layouts são suficientes.
"hmmmmmmmmmmmm, esses botões tão estranhos, seria melhor encosta-los mais pra direita!". Concordo plenamente. Imagine que exista um componente gráfico que possa funcionar como uma mola, empurrando widgets para as extremidades da janela. Esse componente se chama
um Spacer. Spacers conseguem fazer esta função que estamos precisando mas também podem fazer muitas outras conforme suas propriedades são modificadas. Arraste um "Spacer" e solte exatamente entre o botão da esquerda e o delimitador de layout (linha vermelha).
Se tudo der certo, você terá algo do tipo:
Agora só resta adequar o tamanho da janela principal do Dialog ao conteúdo que acabamos de ajustar. Para isso, selecione o formulário (pode ser pelo "Object Inspector") e aplique um layout vertical ou horizontal. Não faz diferença
porque no fim das contas nos temos uma grande caixa que contém todo o resto. Aplicando o layout ao formulário (que também atua como um container) ele irá espalhar o conteúdo geométricamente como é mostrado abaixo:
"E meu Dialog vai ficar essa coisa esparramada?!?" Não! Ainda com o formulário selecionado clique no botão "Adjust Size" e tudo fica mais cute.
--->
Note que o ícone , no Object Inspector foi substituido por uma representação de layout para o Dialog e os GroupBoxes. Já aproveite para mudar os nomes dos objetos (propriedade objectName) e também os textos de exibição de cada um da seguinte forma:
Widget | objectName | Exibição |
QGroupBox | groupLanche | Lanche |
QRadioButton | xSalada | X-Salada |
QRadioButton | xFrango | X-Frango |
QRadioButton | xTudo | X-Tudo |
QGroupBox | groupBebida | Bebida |
QCheckBox | noGelo | Sem Gelo |
QCheckBox | noCal | Light |
QPushButton | ok | OK |
QPushButton | cancel | Cancelar |
Obs: É importante deixar estes nomes exatamente assim ou o futuro código que emplementaremos apresentará problemas.
Os textos de exibição podem ser alterados com duplo-cliques em cada widget ou pela propriedade correspondente (text na maioria deles)
Antes de pré-vizualizarmos o nosso formulário veja que as propriedades minimumSize e maximumSize (herdadas de QWidget) do nosso formulário estão setadas, por padrão, como "0x0" e "16777215x16777215".
Siga os passos abaixo para pré-visualizar o conteúdo:
Tools -> Form Editor -> Preview
Perceba que ao redimensionar, a janela cresce esparramando tudo denovo! o limite dela é "16777215x16777215" (propriedade maximumSize) e o limite mínimo é o tamanho do nosso layout aplicado (apesar de minimumSize está setado como "0x0".
Para modificar isso, faça o seguinte:
Clique com o botão direito sobre o formulário -> Size Constraints -> Set Minimum/Maximun Size (faça para os 2)
Com isso você disse "Ajuste os tamanhos máximo e mínimo para o tamanho atual da janela!":
Geometricamente a janela já está pronta. Agora para demonstrar o uso de style sheets será preciso, antes, mostrar como criar arquivos Resource. Acompanhe!
Criando um arquivo Resource
Arquivos resource servem como um acervo de imagens ou qualquer outro tipo de arquivo que você precise utilizar na sua aplicação. Todas aquelas imagens que aparecem em toolbars, por exemplo, deverão
fazer parte de resources. Com o objetivo de explorar os recursos de StyleSheets vamos criar um resource com uma imagem que servirá de fundo para a nossa aplicação.
- Clique com o botão direito sobre o título do projeto na guia "Projects"
- Clique em "Add New"
- Em "Files and Classes" escolha "Qt", e depois "Resource File"
- Escolha um local para o arquivo, geralmente na mesma pasta do projeto
- Na pasta do projeto, crie uma outra pasta com o nome "imagens" e coloque a imagem que utilizará de fundo dentro dela. Se
quiser utilizar a mesma imagem deste exemplo, faça o download dela aqui
Agora que o arquivo está criado basta adicionar a imagem a ele. Para adicionar, primeiro acesse o arquivo com um duplo-clique no arquivo correspondente na guia "Projects". Em "Prefix" escolha "/imagens", "Add", "Add Files", escolha a imagem, salve todos os documentos em "File -> Save all".
Com isso você já pode utilizar a imagem com StyleSheet.
Brincando de StyleSheets
Se você já brincou de HTML algum dia então provavelmente já deve ter lidado com CSS ou folhas de estilo. Qt apresenta a incrível façanha de deixar que usemos códigos HTML para formatar suas strings. E o melhor, também deixa que usemos CSS para formatar nossas janelas!! Ou seja, não há o que você não faça graficamente!
Para começar, vamos colocar a imagem de fundo no nosso Dialog. Selecione o Dialog e procure pela propriedade styleSheet que é herdada de QWidget. Se quiser pode escrever ali mesmo, mas ao clicar no botão com reticencias uma nova janela própria para isso será aberta (chamada "Edit Style Sheet").
Nessa nova janela você pode escrever as linhas a mão, se conhecer CSS, ou então ele fornece uma ajuda através dos botões "Add Resource", "Add Gradient", "Add Color", "Add Font". Esses quatro botões significam:
- Add Resource: Adicionar um arquivo da minha resource como .... imagem de fundo, imagem de borda ou apenas imagem.
- Add Gradient: Adicionar um gradiente de cores como .... cor do texto, cor do fundo, cor do texto na seleção, cor do fundo na seleção, etc.
- Add Color: Adicionar uma cor sólida como ... o mesmo que o acima.
- Add Font: Adiciona uma font escolhida para o texto da widget.
Então clique em "Add Resource", como na imagem acima e na nova janela que abrir "Select Resource" escolha a imagem do nosso arquivo. Caso a imagem não apareça tente dar um "Refresh" com o botãozinho de setinha verde. Caso não funcione tente re-salvar o projeto. Se ainda assim você não conseguir enxergar sua imagem de fundo, certifique-se de que ela
foi realmente adicionada ao seu arquivo resource.
Se tudo der certo, você deve ver algo assim:
Muito bem, mas pera ai... "Por quê tem esse fundo amarelão dentro do GroupBox da direita?". Isso acontece porque o background escolhido para o Dialog também é aplicado em todas as suas widgets filhas! Mas isso é facilmente resolvido escrevendo explicitamente para quem é destinado aquela linha CSS como no exemplo abaixo:
Agora use a imaginação e seja feliz. Dê uma olhada nos exemplos abaixo... que chique! Preste atenção no widget selecionado.
Perceba que ao escrever linhas CSS dentro de QGroupBox, QRadioButton, QCheckBox, você está configurando as folhas de estilos de qualquer widget filha desse tipo a partir do Dialog.
E este é o resultado final:
Qt Designer traz uma referência muito boa sobre style sheets. No Index do Assistant, procure por "style sheets reference". Ta tudo mastigadinho explicado, os pseudo-states (:), os sub-controls (::). Por exemplo:
::down-arrow (para a setinha do ComboBox)
::down-button (para a setinha para baixo de um ScrollBar
:active
:checked
:closed
:disabled
:enabled
:has-children
:hover
:selected
:unchecked
Procurando por "The Style Sheet Syntax" no Index do Assistant você encontra "List of Stylabe Widgets" (lista de widgets estiláveis!), "List of Properties" (lista de propriedades, como "color", "background", etc.), "List of Pseudo-States", "List of Sub-Controls".
O exemplo ficou bem simples, mas ainda dava pra mudar bastante coisa (por exemplo os botões). Vamos dar uma olhadinha, então, no código gerado pelo Qt Designer para todo esse trabalho gráfico que tivemos..... na próxima página!
|
2010-12-11 15:26:30, disse:
Rapaz.. material de primeira.
Seria legal, ter uma versão para poder imprimir completa, para ir seguindo. Gosto de ler no papel e seguir. Estou esperando os próximos.. também seria legal uma explicação abrangente, do porque se separa as declarações, e dessa divisão de arquivos no Qt. Ainda Não achei nada clareando isso, e como usar isso... seu material cita, mas isso vem do C++ e serial legal ter mais sobre isso. Desde já obrigado, e seu trabalho é positivo, mesmo que não se veja tanta gente aqui comentando! Excelente material!
|
2011-02-23 14:43:13, disse:
Como estou demorando para postar novas página, resolvi responder a dúvida do Adriano aqui mesmo (relativa a separação de arquivos).
Considerando um programinha simples, com uma classe, ele terá basicamente três coisas:
- o main
- o header de uma class X
- a implementação dessa classe X
Em C++, voce pode fazer tudo no MAIN.CPP:
class X { X(); //... }; //definição da classe
X::X(){ //... } //métodos da classe
void main() { //... } //main
---
Ou então pode separar sua classe do main, em um X.H:
arquivo X.H
class X { X(); //... };
X::X(){ //... }
e o main no MAIN.CPP:
void main() { //... }
---
E até mesmo separar geral (sem esquecer dos includes):
arquivo X.H
class X { X(); //... };
arquivo X.CPP
X::X(){ //... }
e o main no MAIN.CPP:
void main() { //... }
Com exceção de templates, que é mais complicadinho então a classe inteira fica no header.
Então em C++ isso fica a seu critério. O que não pode acontecer é colocar a implementação dos métodos dentro da interface da classe. Fazendo isso você não está errado mas está abalando as estruturas da programação orientada a objetos e encapsulamento.
-----------
Acontece que no Qt, as vezes é obrigatório que você desmembre em HEADER e IMPLEMENTAÇÃO(cpp). Para que o Qt "funcione" quando sua classe implementa os próprios SIGNALS/SLOTS (macro QOBJECT), por exemplo, é necessário separar. Se eu não me engano isso tem a ver com o Meta-Object-Compiler. Então pra não ter problema eu sempre separo as classes em HEADER e CPP.
|