Laura Lemay
Durante cinco últimos dias concentrou-se na criação applets que fazem coisas muito simples: o texto de exposição, jogo uma animação ou um som, ou interage com o usuário. Quando passa aquele ponto, contudo, pode querer começar a criar applets mais complexos que se comportam como verdadeiras aplicações introduzidas em uma página-da-Web-applets que começam a parecer a verdadeiras aplicações GUI com botões, cardápios, campos de texto e outros elementos.
É este tipo de verdadeiro trabalho em Java applets e aplicações para as quais a Caixa de ferramentas de Windowing Abstrata de Java ou awt, se projetou. Tem usado de fato o awt do início, como poderia ter adivinhado das classes que tem importado. A classe de Applet e a maioria das classes tem usado esta semana são todas as partes integrantes do awt.
O awt fornece o seguinte:
Hoje aprenderá sobre como usar todas estas coisas no seu Java applets. Amanhã aprenderá sobre a criação de janelas, cardápios e caixas de diálogo, que lhe permitem surgir janelas separadas da janela do navegador. Além disso, pode usar o awt em aplicações autônomas, portanto tudo que aprendeu portanto semana ainda pode usar-se. Se encontrar a armação do Navegador da Web que também limita, pode tomar o seu contexto awt e começar a escrever aplicações de Java crescidas.
Hoje, contudo, continuará concentrando-se em applets.
Observar |
Isto é de muito a lição mais complexa por enquanto, e é um capítulo longo também. Há muito cobrir e muito código para passar hoje, portanto se começar a ficar esmagador, poderia querer tomar dois dias (ou mais) para este. |
A ideia básica atrás do awt consiste em que um programa Java gráfico é grupo de componentes aninhados, que começam da janela externa durante todo o tempo abaixo ao componente UI mais pequeno. Os componentes podem incluir coisas que pode ver de fato na tela, como janelas, barras de cardápio, botões e campos de texto, e também podem incluir containeres, que à sua vez podem conter outros componentes. A figura 13.1 mostra como uma página de mostra em um browser de Java poderia incluir vários componentes diferentes, todos dos quais se dirigem pelo awt.
A figura 13.1: componentes de awt.
Este aninhamento de componentes dentro de containeres dentro de outros componentes cria uma hierarquia de componentes, da caixa de seleção mais pequena dentro de um applet à janela total na tela. A hierarquia de componentes determina o acordo de itens na tela e dentro de outros itens, ordem na qual se pintam, e como os eventos se passam de um componente ao outro.
Estes são os componentes principais com os quais pode trabalhar no awt:
As classes dentro do pacote de java.awt escrevem-se e organizam-se para refletir a estrutura abstrata de containeres, componentes e componentes UI individuais. A figura 13.2 mostra um pouco da hierarquia de classe que compõe as classes principais no awt. A raiz da maioria dos componentes awt é a classe Component, que fornece exposição básica e características tratam o evento. As classes Container, Canvas, TextComponent e muitos de outros componentes UI herdam de Component. Herdar da classe de Container é objetos que podem conter outros componentes awt - o Panel e classes de Window, especialmente. Observe que a classe de java.applet.Applet, embora viva no seu próprio pacote, herda de Panel, portanto os seus applets são uma parte integrante da hierarquia de componentes no sistema awt.
A figura 13.2: Uma Hierarquia de classe awt Parcial.
Um usuário gráfico aplicação baseada na interface que escreve usando o awt pode ser tão complexo como queira, com dúzias de containeres aninhados e componentes dentro de um a outro. O awt projetou-se para que cada componente possa desempenhar o seu papel no sistema awt total sem precisar de duplicar ou guardar a pista do comportamento de outras partes no sistema.
Além dos próprios componentes, o awt também inclui o grupo de gerentes de leiaute. Os gerentes de leiaute determinam como vários componentes se arranjam quando se expõem onscreen e os seus vários tamanhos um quanto a outro. Como Java applets e as aplicações que usam o awt podem correr em sistemas diferentes com exposições diferentes, fontes diferentes e resoluções diferentes, somente não pode picar um determinado componente em um determinado lugar na janela. Os gerentes de leiaute ajudam-no a criar o leiaute UI que se arranja dinamicamente e pode expor-se em qualquer lugar o applet ou a aplicação poderiam dirigir-se.
A forma mais simples do componente awt é o componente UI básico. Pode criar e acrescentar estes ao seu applet sem precisar de saber algo sobre a criação de containeres ou listas - o seu applet, até antes que comece a pintar e desenhar e tratar eventos, já é um container awt. Como um applet é um container, pode pôr outros componentes awt - como componentes de UI ou outros containeres - nele.
Nesta seção, aprenderá sobre os componentes UI básicos: etiquetas, botões, caixas de seleção, cardápios seletos e campos de texto. Em cada caso, o procedimento para criar o componente é o mesmo - primeiro cria o componente e logo acrescenta-o à lista que o mantém, em que ponto se expõe na tela. Acrescentar um componente a uma lista (como o seu applet, por exemplo), usam o método de add():
public void init() { Button b = new Button("OK"); add(b); }
Aqui o método de add() refere-se à corrente applet-em-outras-palavras, significa "acrescente-me este elemento". Também pode acrescentar elementos a outros containeres, como aprenderá depois.
Observe que onde o componente aparece na lista depende do gerente de leiaute que a lista se define para ter. Nestes exemplos usei tanto o leiaute de fluxo como o leiaute de grade, dependendo do qual faz o applet parecer melhor. Aprenderá mais sobre listas e leiaute na seguinte seção.
Também observe que cada um destes componentes manda associar uma ação com ele - isto é, algo que o componente faz quando se ativa. As ações geralmente provocam eventos ou outras atividades no seu applet (muitas vezes chamam-nos rechamadas em outras caixas de ferramentas de janela). Nesta seção, vai se concentrar em criar os próprios componentes; lhes aprenderá sobre ações acrescentam depois na lição de hoje.
Nos componentes!
A forma mais simples do componente UI é a etiqueta, que é, efetivamente, uma cadeia de texto que pode usar para etiquetar outros componentes UI. As etiquetas não são editables; somente etiquetam outros componentes na tela.
As vantagens que uma etiqueta tem sobre uma cadeia de texto ordinária (que desenharia a utilização drawString() no método de paint()) são
Uma etiqueta é uma cadeia de texto uneditable que substitui como uma descrição sob outros componentes awt.
Para criar uma etiqueta, use um dos seguintes construtores:
Pode modificar a fonte da etiqueta com o método de setFont(), pediu que a própria etiqueta modificasse a etiqueta individual, ou no componente de cerrado para modificar todas as etiquetas. Aqui está algum código simples para criar algumas etiquetas no Helvetica Corajoso (demonstrações da Figura 13.3 como isto olha onscreen):
A figura 13.3: Três etiquetas com vários alinhamentos.
Observar |
Este código usa o método de setl1ayout para criar um novo gerente de leiaute. Não se incomode com aquela linha agora mesmo; aprenderá mais sobre gerentes de leiaute na seguinte seção. |
import java.awt.*; public class LabelTest extends java.applet.Applet { public void init() { setFont(new Font ("Helvetica", Font.BOLD, 14)); setl1ayout(new GridLayout(3,1)); add(new Label("aligned left", Label.LEFT)); add(new Label("aligned center", Label.CENTER)); add(new Label("aligned right", Label.RIGHT)); } }
Quando tem um objeto de Label, pode usar métodos definidos na classe de Label para adquirir e estabelecer os valores do texto, como mostrado na Tabela 13.1.
Método | Ação |
getText() | Devolve uma cadeia que contém o texto desta etiqueta |
setText(String) | Modifica o texto desta etiqueta |
getAlignment() | Devolve um número inteiro que representa o alinhamento desta etiqueta:0 é Label.LEFT |
setAlignment(int) | Modifica o alinhamento desta etiqueta ao uso do número inteiro dado as variáveis de classe enumeradas no método de getAlignment() |
O segundo usuário inter-relaciona o componente para explorar é o botão. Os botões são componentes UI simples que provocam alguma ação na sua interface quando se apertam. Por exemplo, um calculador applet poderia ter botões de cada número e operador, ou uma caixa de diálogo poderia ter botões para OKAY e Cancelar.
Um botão é um componente UI que, quando "apertado" (selecionado) com o rato, provoca alguma ação.
Para criar um botão, use um dos seguintes construtores:
Uma vez que tem um objeto de Button, pode adquirir o valor da etiqueta do botão usando o método de getLabel() e estabelecer a etiqueta usando o método de setl1abel(String).
A figura 13.4 mostra alguns botões simples, utilização criada do seguinte código:
A figura 13.4: Quatro botões em Netscape.
public class ButtonTest extends java.applet.Applet { public void init() { add(new Button("Rewind")); add(new Button("Play")); add(new Button("Fast Forward")); add(new Button("Stop")); } }
As caixas de seleção são componentes de interface do usuário que têm dois estados: em e de (ou verificado e incontrolado, selecionado e não selecionado, verdadeiro e falso, e assim por diante). Diferentemente de botões, as caixas de seleção normalmente não provocam ações diretas em um UI, mas em vez disso usam-se para indicar características opcionais de alguma outra ação.
As caixas de seleção podem usar-se de dois modos:
A última espécie de caixas de seleção chama-se rádio-botões ou grupos de caixa de seleção, e descreve-se na seguinte seção.
As caixas de seleção são componentes UI que podem selecionar-se ou excluir-se (verificado ou incontrolado) para fornecer opções. As caixas de seleção não-exclusivas podem verificar-se ou incontroladas independentemente de outras caixas de seleção.
As caixas de seleção exclusivas, rádio-botões às vezes chamados, existem em grupos; só um no grupo pode verificar-se um dia.
As caixas de seleção não-exclusivas podem criar-se usando a classe de Checkbox. Pode criar uma caixa de seleção usando um dos seguintes construtores:
A figura 13.5 mostra algumas caixas de seleção simples (só Underwear se seleciona) a utilização gerada do seguinte código:
A figura 13.5: Cinco caixas de seleção, um selecionado.
import java.awt.*; public class CheckboxTest extends java.applet.Applet { public void init() { setl1ayout(new FlowLayout(FlowLayout.LEFT)); add(new Checkbox("Shoes")); add(new Checkbox("Socks")); add(new Checkbox("Pants")); add(new Checkbox("Underwear", null, true)); add(new Checkbox("Shirt")); } }
A tabela 13.2 enumera alguns métodos de caixa de seleção.
Método | Ação |
getLabel() | Devolve uma cadeia que contém a etiqueta desta caixa de seleção |
setl1abel(String) | Modifica o texto da etiqueta da caixa de seleção |
getState() | true de regressos ou false, baseado em se a caixa de seleção se seleciona |
setState(boolean) | Modifica o estado da caixa de seleção para o selecionado (true) ou não selecionou (false) |
Os rádio-botões têm a mesma aparência que caixas de seleção, mas só um em uma série pode selecionar-se de uma vez. Para criar uma série de rádio-botões, primeiro crie um exemplo de CheckboxGroup:
CheckboxGroup cbg = new CheckboxGroup();
Então crie e acrescente as caixas de seleção individuais usando o construtor com três argumentos (o primeiro é a etiqueta, o segundo é o grupo, e o terceiro é se aquela caixa de seleção se seleciona). Observe que porque os rádio-botões, por definição, têm só um no grupo selecionado de uma vez, o true último a acrescentar-se será aquele selecionado à revelia:
add(new Checkbox("Yes", cbg, true); add(new Checkbox("No", cbg, false);
Aqui está um exemplo simples (os resultados do qual se mostram na Figura 13.6):
A figura 13.6: Seis rádio-botões (caixas de seleção exclusivas), um selecionado.
import java.awt.*; public class CheckboxGroupTest extends java.applet.Applet { public void init() { setl1ayout(new FlowLayout(FlowLayout.LEFT)); CheckboxGroup cbg = new CheckboxGroup(); add(new Checkbox("Red", cbg, false)); add(new Checkbox("Blue", cbg, false)); add(new Checkbox("Yellow", cbg, false)); add(new Checkbox("Green", cbg, true)); add(new Checkbox("Orange", cbg, false)); add(new Checkbox("Purple", cbg, false)); } }
Todos os métodos de caixa de seleção mostrados na Tabela 13.2 na seção prévia podem usar-se com
as caixas de seleção no grupo. Além disso, pode usar o getCheckboxGroup() e métodos de setCheckboxGroup() (definido na classe de Checkbox()) para acessar e modificar o grupo de qualquer caixa de seleção dada.
Finalmente, o getCurrent() e os métodos de setCurrent(Checkbox), definidos em CheckboxGroup, podem usar-se para adquirir ou estabelecer a caixa de seleção atualmente selecionada.
O cardápio seleto é um componente UI mais complexo do que etiquetas, botões ou caixas de seleção. Os cardápios seletos são surgem (ou suspenso) cardápios dos quais pode selecionar um item. O cardápio então expõe aquela escolha na tela. A função de um cardápio seleto é o mesmo através de plataformas, mas a sua aparência real pode variar da plataforma à plataforma.
Observe que os cardápios seletos podem ter só um item selecionado de uma vez. Se quiser ser capaz de escolher múltiplos itens do cardápio, use uma lista que se enrola em vez disso (aprenderá mais sobre listas se enrolam depois hoje, na seção "mais Componentes UI").
Os cardápios seletos são os menus instantâneos dos itens dos quais pode escolher um item.
Para criar um cardápio seleto, crie um exemplo da classe de Choice e logo use o método de addItem() para acrescentar-lhe itens individuais na ordem na qual devem aparecer. Finalmente, acrescente o cardápio seleto inteiro à lista do modo habitual. Aqui está um programa simples que constrói um cardápio seleto de frutos; a Figura 13.7 mostra o resultado (com o cardápio derrubado):
A figura 13.7: Um cardápio seleto.
import java.awt.*; public class ChoiceTest extends java.applet.Applet { public void init() { Choice c = new Choice(); c.addItem("Apples"); c.addItem("Oranges"); c.addItem("Strawberries"); c.addItem("Blueberries"); c.addItem("Bananas"); add(c); } }
Mesmo depois que o seu cardápio seleto acrescentou-se a uma lista, pode continuar acrescentando itens àquele cardápio com o método de addItem(). A tabela 13.3 mostra alguns outros métodos que podem ser úteis no trabalho com cardápios seletos.
Método | Ação |
getItem(int) | Devolve o item de cadeia na posição dada (os itens dentro de uma escolha começam em 0, como tabelas) |
countItems() | Devolve o número de itens no cardápio |
getSelectedIndex() | Devolve a posição de índice do item isto seleciona-se |
getSelectedItem() | Devolve o item atualmente selecionado como uma cadeia |
select(int) | Seleciona o item na posição dada |
select(String) | Seleciona o item com a cadeia dada |
Diferentemente dos componentes UI até este ponto, que só lhe permitem selecionar entre várias opções de executar uma ação, os campos de texto lhe permitem entrar e editar o texto. Os campos de texto são geralmente só uma linha única e não têm scrollbars; as áreas de texto, sobre as quais aprenderá depois hoje, são melhores para montantes maiores do texto.
Os campos de texto são diferentes de etiquetas em que podem editar-se; as etiquetas são boas para expor somente texto, campos de texto para adquirir a entrada de texto do usuário.
Os campos de texto fornecem uma área onde pode entrar e editar uma linha única do texto.
Para criar um campo de texto, use um dos seguintes construtores:
Por exemplo, a seguinte linha cria um campo de texto 30 carateres largos com a cadeia "Enter Your Name" como os seus conteúdos iniciais:
TextField tf = new TextField("Enter Your Name", 30); add(tf);
Ponta |
Os campos de texto só incluem o próprio campo editable. Normalmente tem de incluir uma etiqueta com um campo de texto para indicar o que pertence naquele campo de texto. |
Também pode criar um campo de texto que obscurece os carateres datilografados nele por exemplo, para campos de senha. Para fazer isto, primeiro crie o próprio campo de texto; então use o método de setEchoCharacter() para estabelecer o caráter que se ecoa na tela. Aqui está um exemplo:
TextField tf = new TextField(30); tf.setEchoCharacter('*');
A figura 13.8 mostra três caixas de texto (e etiquetas) o que se criou usando o seguinte código:
A figura 13.8: Três campos de texto para permitir a entrada do usuário.
add(new Label("Enter your Name")); add(new TextField("your name here", 45)); add(new Label("Enter your phone number")); add(new TextField(12)); add(new Label("Enter your password")); TextField t = new TextField(20); t.setEchoCharacter('*'); add(t);
O texto no primeiro campo (your name here) inicializou-se no código; datilografei o texto no resto duas caixas justo antes da toma do instantâneo.
Os campos de texto herdam da classe TextComponent e têm uma suite inteira de métodos, ambos herdados daquela classe e definidos na sua própria classe, que pode ser útil para você nos seus programas Java. A tabela 13.4 mostra uma seleção daqueles métodos.
Método | Ação |
getText() | Devolve o texto que este campo de texto contém (como uma cadeia) |
setText(String) | Põe a cadeia de texto dada no campo |
getColumns() | Devolve a largura deste campo de texto |
select(int, int) | Seleciona o texto entre as duas posições de número inteiro (partida de posições de 0) |
selectAll() | Seleciona todo o texto no campo |
isEditable() | true de regressos ou false baseado em se o texto é editable |
setEditable(boolean) | true (o default) permite a texto editar-se; false congela o texto |
getEchoChar() | Devolve o caráter usado para mascarar a entrada |
echoCharIsSet() | true de regressos ou false baseado em se o campo tem um caráter dissimulador |
Observar |
As descrições do getEchoChar() e métodos de echoCharIsSet() referem-se ao disfarce de entrada de usuário. O disfarce de entrada de usuário é uma técnica de limitar a entrada de usuário a um tipo específico, como um número. Outros tipos do disfarce de entrada de usuário incluem datas e números de telefone, onde há um número específico de dígitos numéricos arranjados em um formato constante. |
as listas de awt podem conter componentes UI ou outras listas. A pergunta agora consiste em como aqueles componentes se arranjam de fato e se expõem onscreen.
Em outros sistemas windowing, os componentes de UI muitas vezes arranjam-se usando o pixel codificado posto nas medições um campo de texto na posição 10,30, para o exemplo - o mesmo modo que usou as operações de gráficos para pintar quadrados e ovais na tela. No awt, o seu desenho de UI pode expor-se em muitos sistemas de janela diferentes em muitas telas diferentes e com muitos tipos diferentes de fontes com a métrica de fonte diferente. Por isso, precisa de um método mais flexível de arranjar componentes na tela para que um leiaute que parece bonito em uma plataforma não seja um desordem misto, inútil no outro.
Com somente este objetivo, Java tem gerentes de leiaute, inserções, e faz alusão a que cada componente possa prover para ajudar dinamicamente a expor a tela.
Observe que a coisa bonita sobre componentes awt e os itens de interface do usuário consistem em que não tem de pintá-los - o sistema awt dirige tudo isto para você. Se tiver componentes gráficos ou imagens, ou quer criar a animação dentro de listas, ainda tem de fazer isto à mão, mas para a maioria dos componentes básicos, tudo que tem de fazer se põe eles na tela e Java tratará o resto.
A aparência real dos componentes awt na tela determina-se normalmente por duas coisas: como aqueles componentes se acrescentam à lista que os mantém (a ordem ou por argumentos a add()) e o gerente de leiaute que a lista usa atualmente para expor a tela. O gerente de leiaute determina como as porções da tela serão sectioned e como os componentes dentro daquela lista se colocarão.
O gerente de leiaute determina como os componentes awt se arranjam dinamicamente na tela.
Cada lista da tela pode ter o seu próprio gerente de leiaute. Por listas de aninhamento dentro de listas e utilização do gerente de leiaute apropriado de cada um, muitas vezes pode arranjar o seu UI para agrupar e arranjar componentes em um caminho que é funcionalmente útil e parece bom em várias plataformas e sistemas windowing. Aprenderá sobre listas de aninhamento em uma seção posterior.
O awt provê cinco gerentes de leiaute básicos: FlowLayout, GridLayout, BorderLayout, CardLayout e GridBagLayout. Para criar um gerente de leiaute de uma lista dada, crie um exemplo daquele gerente de leiaute e logo use o método de setl1ayout() para aquela lista. Este exemplo estabelece o gerente de leiaute do cerrado inteiro applet lista:
public void init() { setl1ayout(new FlowLayout()); }
Estabelecer o gerente de leiaute à revelia, como criação de componentes de interface do usuário, faz-se melhor durante a inicialização do applet, que é porque se inclui aqui.
Depois que o gerente de leiaute estabelece-se, pode começar a acrescentar componentes à lista. A ordem na qual os componentes se acrescentam ou os argumentos que usa para acrescentar aqueles componentes muitas vezes é significante, dependendo do qual o gerente de leiaute é atualmente ativo. Leia em para a informação sobre os gerentes de leiaute específicos e como apresentam componentes dentro da lista à qual se aplicam.
As seções seguintes descrevem cinco Java básico awt gerentes de leiaute.
A classe de FlowLayout é a mais básica do leiaute. Usando o leiaute de fluxo, os componentes acrescentam-se à lista um após outro, linha pela linha. Se um componente não se ajustar para uma linha, enrolou para a seguinte linha. O leiaute de fluxo também tem um alinhamento, que determina o alinhamento de cada linha. À revelia, cada linha centra-se.
O leiaute de fluxo arranja componentes de da esquerda à direita em linhas. As linhas alinham-se deixadas, direito, ou centram-se.
Para criar um leiaute de fluxo básico com um alinhamento centrado, use a seguinte linha do código na inicialização da sua lista (porque isto é o leiaute de vidro à revelia, não precisa de incluir esta linha se for a sua intenção):
setl1ayout(new FlowLayout());
Com o jogo de leiaute, a ordem na qual acrescenta elementos ao leiaute determina a sua posição. O seguinte código cria uma linha simples de seis botões em um leiaute de fluxo centrado (a Figura 13.9 mostra o resultado):
A figura 13.9: Seis botões, utilização arranjada de um gerente de leiaute de fluxo.
import java.awt.*; public class FlowLayoutTest extends java.applet.Applet { public void init() { setl1ayout(new FlowLayout()); add(new Button("One")); add(new Button("Two")); add(new Button("Three")); add(new Button("Four")); add(new Button("Five")); add(new Button("Six")); } }
Para criar um leiaute de fluxo com um alinhamento outro do que centrado, acrescente o FlowLayout.RIGHT ou variável de classe de FlowLayout.LEFT como um argumento:
setl1ayout(new FlowLayout(FlowLayout.LEFT));
Também pode estabelecer valores de fenda horizontais e verticais usando o leiaute de fluxo. A fenda é o número de pixéis entre componentes em uma lista; à revelia, os valores de fenda horizontais e verticais são três pixéis, que de fato podem ser muito fechados. A fenda horizontal espalha componentes à esquerda e à direita; a fenda vertical estende-os ao topo e o fundo de cada componente. Acrescente argumentos de número inteiro ao construtor de leiaute de fluxo para aumentar a fenda. A figura 13.10 mostra o resultado de acrescentar uma fenda de 30 pontos no horizontal e 10 nas direções verticais, como isto:
A figura 13.10: leiaute de fluxo com uma fenda de 10 pontos.
setl1ayout(new FlowLayout(FlowLayout.LEFT, 30, 10));
O leiaute de grade oferece mais controle sob a colocação de componentes dentro de uma lista. Usando um leiaute de grade, você porção da área de exposição da lista em linhas e colunas. Cada componente que então acrescenta à lista coloca-se em uma célula da grade, começando da fila superior e progredindo por cada linha de da esquerda à direita (aqui está onde a ordem de chamadas ao método de add() é muito relevante para como a tela se expõe).
Para criar um leiaute de grade, indique o número de linhas e colunas que quer que a grade tenha quando cria um novo exemplo da classe de GridLayout. Aqui está um leiaute de grade com três linhas e duas colunas (a Figura 13.11 mostra o resultado):
import java.awt.*; public class GridLayoutTest extends java.applet.Applet { public void init() { setl1ayout(new GridLayout(3,2); add(new Button("One")); add(new Button("Two")); add(new Button("Three")); add(new Button("Four")); add(new Button("Five")); add(new Button("Six")); } }
O leiaute de grade também pode ter uma fenda horizontal e vertical entre componentes. Para criar fendas, acrescente aqueles valores de pixel:
setl1ayout(new GridLayout(3, 3, 10, 30));
A figura 13.12 mostra um leiaute de grade com uma fenda horizontal de 10 pixéis e uma fenda vertical de 30 pixéis.
A figura 13.12: Um leiaute de grade com fendas horizontais e verticais.
O leiaute de borda comporta-se diferentemente de leiaute de grade e fluxo. Quando acrescenta um componente a uma lista que usa um leiaute de borda, indica a sua colocação como uma direção geográfica: Norte, o Sul, Leste, Oeste ou centro. (Ver a Figura 13.13.) Os componentes em volta de todas as bordas expõem-se com tanto tamanho como precisam; o componente no centro, se algum houver, adquire qualquer espaço deixado.
A figura 13.13: Onde os componentes entram em um leiaute de borda.
Para usar um leiaute de borda, cria-o como faz outro leiaute; então acrescenta os componentes individuais com um método de add() especial que tem dois argumentos. O primeiro argumento é uma cadeia que indica a posição do componente dentro do leiaute, e o segundo é o componente para acrescentar:
add("North", new TextField("Title", 50));
Também pode usar esta forma de add() de outros gerentes de leiaute; o argumento de cadeia somente vai se ignorar se não for necessário.
Aqui está o código para gerar o leiaute de borda mostrado na Figura 13.13:
import java.awt.*; public class BorderLayoutTest extends java.applet.Applet { public void init() { setl1ayout(new BorderLayout()); add("North", new Button("One")); add("East", new Button("Two")); add("South", new Button("Three")); add("West", new Button("Four")); add("Center", new Button("Five")); add(new Button("Six")); } }
O leiaute de borda também pode ter fendas horizontais e verticais. Observe que os componentes do Norte e do Sul se estendem durante todo o tempo à borda da lista, portanto a fenda resultará em menos espaço vertical do Leste, direito, e centrar componentes. Para acrescentar fendas a um leiaute de borda, inclua aqueles valores de pixel no construtor como com outros gerentes de leiaute:
setl1ayout(new BorderLayout(10, 10));
O leiaute de cartão comporta-se muito diferentemente de outro leiaute. Quando acrescenta componentes a um de outros gerentes de leiaute, todos aqueles componentes aparecem na tela ao mesmo tempo. O leiaute de cartão usa-se para produzir apresentações de slides de componentes, um após outro. Se tenha usado alguma vez o programa HyperCard no Macintosh ou tenha visto caixas de diálogo em janelas com várias páginas tabbed diferentes, trabalhou com a mesma ideia básica.
Quando cria um leiaute de cartão, os componentes que acrescenta à lista exterior serão outros componentes normalmente de container outras listas. Então pode usar o leiaute diferente para aqueles cartões individuais para que cada tela tenha a sua própria olhada.
Os cartões, em um leiaute de cartão, são listas diferentes acrescentadas um após outro e expostas um após outro. Se pensar em um arquivo de cartão, adquirirá a ideia; só um cartão pode expor-se ao mesmo tempo, mas pode ligar entre cartões.
Quando acrescenta cada cartão à lista, pode dar-lhe um nome. Então, para sacudir entre os cartões de container, pode usar métodos definidos na classe de CardLayout para mover-se para um cartão denominado, avançar ou atrás ou mover-se para o primeiro cartão ou para o cartão último. Tipicamente terá grupo de botões que chamam estes métodos para fazer a navegação do leiaute de cartão mais fácil.
Aqui está um fragmento simples do código que cria um leiaute de cartão que contém três cartões:
setl1ayout(new CardLayout()); //add the cards Panel one = new Panel() add("first", one); Panel two = new Panel() add("second", two); Panel three = new Panel() add("third", three); // move around show(this, "second"); //go to the card named "second" show(this, "third"); //go to the card named "third" previous(this); //go back to the second card first(this); // got to the first card
Salvei o leiaute de bolsa de grade para o último porque embora sejam o modo mais potente de dirigir o leiaute awt, também se complicam extremamente.
Usando um de outros quatro gerentes de leiaute, pode ser às vezes difícil adquirir o leiaute exato que quer sem fazer muito aninhamento de listas dentro de listas. As bolsas de grade fornecem uma solução mais de uso geral. Como leiaute de grade, o leiaute de bolsa de grade permite-lhe arranjar os seus componentes em um leiaute parecido a uma grade. Contudo, o leiaute de bolsa de grade também lhe permite controlar o palmo de células individuais na grade, as proporções entre as linhas e colunas e o acordo de componentes dentro de células na grade.
Para criar um leiaute de bolsa de grade, de fato usa duas classes: GridBagLayout, que provê o gerente de leiaute total e GridBagConstraints, que define as propriedades de cada componente na grade - a sua colocação, dimensões, alinhamento, e assim por diante. É a relação entre a bolsa de grade, os constrangimentos e cada componente que define o leiaute total.
Na sua forma mais geral, criando um leiaute de bolsa de grade implica os seguintes passos:
Aqui está algum código simples que funda o leiaute e logo cria constrangimentos de um botão único (não se incomode com vários valores dos constrangimentos; cobrirei estes mais tarde nesta seção):
// set up layout GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); setl1ayout(gridbag); // define constraints for the button Button b = new Button("Save"); constraints.gridx = 0; constraints.gridy = 0; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 30; constraints.weighty = 30; constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.CENTER; // attach constraints to layout, add button gridbag.setConstraints(b, constraints); add(b);
De muito, a parte mais tediosa deste processo funda os constrangimentos de cada componente (como pode ver deste exemplo, tem de estabelecer todos aqueles constrangimentos de cada componente que quer acrescentar à lista). Além do tédio, os constrangimentos não são tudo que fácil entender; têm muitos valores diferentes, muitos dos quais se relacionam, que significa que a modificação daquela pode ter efeitos estranhos sobre outros.
Considerando os constrangimentos numerosos, ajuda a ter um plano e tratar com cada espécie do constrangimento um após outro. Há quatro passos que eu gosto de seguir neste processo. Vamos andar por cada um deles.
O primeiro lugar de começar no leiaute de bolsa de grade está no papel. Esboçar fora o seu UI projeta anteriormente - antes que escreva que até uma linha única do código - ajudará enormemente na corrida longa com a tentativa compreender onde tudo vai. Assim deixam de lado o seu editor durante um segundo, apanham uma folha de papel e um lápis, e vamos construir a grade.
A figura 13.14 mostra o leiaute de lista que estaremos construindo neste exemplo. A figura 13.15 mostra o mesmo leiaute com uma grade imposta em cima dele. O seu leiaute terá uma grade semelhante a este, com linhas e colunas que formam células individuais.
A figura 13.14: Um leiaute de bolsa de grade.
A figura 13.15: O leiaute de bolsa de grade da Figura 13.14, com grade imposta.
Tenha em mente como desenha a sua grade que cada componente deve ter a sua própria célula. Não pode pôr mais de um componente na mesma célula. O reverso não é verdade, contudo; um componente pode medir por palmos múltiplas células no x ou direções y (como na Tecla OK na fila inferior, que mede por palmos duas colunas). Observe na Figura 13.15 que as etiquetas e os campos de texto têm as suas próprias grades e que o botão mede por palmos duas células de coluna.
Enquanto ainda trabalha no papel, algo que o ajudará depois deve etiquetar as células com o seu x e coordenadas de y. Estas não são coordenadas de pixel; melhor são coordenadas de célula. A célula deixada o topo é 0,0. A seguinte célula para a direita disto na fila superior é 1,0. A célula para a direita disto é 2,0. Movendo-se para a seguinte linha, a célula mais à esquerda é 1,0, a seguinte célula na linha é 1,1, e assim por diante. Etiquete as suas células no papel com estes números; precisará deles depois quando fizermos o código deste exemplo. A figura 13.16 mostra os números de cada uma das células neste exemplo.
A figura 13.16: O leiaute de bolsa de grade da Figura 13.14, com coordenadas de célula.
Vamos atrás a Java e partida implementando o leiaute acaba de atrair o papel. Inicialmente vamos enfocar exclusivamente a obtenção do leiaute a grade e o direito de proporções. Para isto, ajuda não a trabalhar com elementos UI reais. Eu gosto de usar botões como placeholders para os elementos reais no leiaute até que possa adquirir tudo direito fundado, e logo modificar os botões para os elementos direitos.
Para reduzir no montante da datilografia temos de fazer para fundar todos aqueles constrangimentos, vou começar definindo um método de ajudante que toma vários valores e estabelece os constrangimentos daqueles valores. buildConstraints() toma sete argumentos: um objeto de GridBagConstraints e seis números inteiros que representam as variáveis de exemplo de GridBagConstraints gridx, gridy, gridwidth, gridheight, weightx e weighty. Aprenderá o que estes de fato fazem logo; por agora, aqui está o código ao método de ajudante em que usaremos além disso neste exemplo:
void buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw, int gh, int wx, int wy) { gbc.gridx = gx; gbc.gridy = gy; gbc.gridwidth = gw; gbc.gridheight = gh; gbc.weightx = wx; gbc.weighty = wy; }
Agora vamos mudar ao método de init(), onde todo o leiaute de fato ocorre. Aqui está a definição de método básica, onde definiremos o GridBagLayout para ser o gerente de leiaute inicial e criar um objeto de constraints (um exemplo de GridBagConstraints):
public void init() { GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); setl1ayout(gridbag); constraints.fill = GridBagConstraints.BOTH; }
Uma mais pequena nota de explicação: Aquela linha última, que estabelece o valor de constraints.fill, vai se retirar (e vai se explicar) depois. Está lá para que os componentes encham a célula inteira na qual se contêm, que facilita ver o que está acontecendo. Acrescente-o por agora e adquirirá uma ideia mais clara de para que é depois.
Agora acrescentaremos o botão placeholders ao leiaute (lembre-se, concentramo-nos na organização de grade básica no momento atual, portanto usaremos botões como placeholders para os elementos UI reais acrescentará depois). Vamos começar com um botão único portanto pode adquirir uma sensação para estabelecer os seus constrangimentos. Este código entrará no método de init() somente depois da linha de setl1ayout:
// Name label buildConstraints(constraints, 0, 0, 1, 1, 100, 100); Button label1 = new Button("Name:"); gridbag.setConstraints(label1, constraints); add(label1);
Estas quatro linhas fundam os constrangimentos de um objeto, criam um novo botão, anexam aqueles constrangimentos àquele botão, e logo acrescentam-no à lista. Observe que os constrangimentos de um componente se guardam no objeto de GridBagConstraints, portanto o componente não tem de até existir para fundar os seus constrangimentos.
Agora vamos começar detalhes: Somente quais são os valores dos constrangimentos que ligamos o método de ajudante buildConstraints?
Dois primeiros argumentos de número inteiro são o gridx e valores de gridy dos constrangimentos. Estas são as coordenadas de célula da célula que contém este componente. Lembre-se como escreveu estes no papel no passo um? Com as células quase numeradas no papel, tudo que tem de fazer é ligam os valores direitos. Observe que se tiver um componente que mede por palmos múltiplas células, as coordenadas de célula são aqueles da célula na esquina deixada o topo.
Aqui este botão está na esquina deixada o topo, portanto o seu gridx e gridy (dois primeiros argumentos a buildConstraints()) são 0 e 0, respectivamente.
Dois segundos argumentos de número inteiro são o gridwidth e gridheight. Estas não são as larguras de pixel e as alturas das células; melhor são o número de células este componente palmos: gridwidth das colunas e gridheight das linhas. Aqui este componente mede por palmos só uma célula, portanto os valores para ambos são 1.
Dois argumentos de número inteiro últimos são para weightx e weighty. Estes usam-se para fundar as proporções das linhas e colunas - isto é, que largo ou profundo serão. Os pesos podem ficar muito confusos, portanto por agora somente jogo ambos os valores a 100. Tratará com pesos no passo três.
Depois que os constrangimentos construíram-se, pode anexá-los a um objeto usando o método de setConstraints(). setConstraints90, que é um método definido em GridBagLayout, toma dois argumentos: o componente (aqui um botão) e os constrangimentos daquele botão. Finalmente, pode acrescentar o botão à lista.
Depois que estabeleceu e destinou os constrangimentos a um componente, pode reutilizar aquele objeto de GridBagConstraints de fundar os constrangimentos do seguinte objeto. Isto efetivamente significa duplicar aquelas quatro linhas de cada componente na grade, com valores diferentes do método de buildConstraints(). Para salvar o espaço, somente vou mostrar-lhe os métodos de buildConstraints() de quatro células últimas.
A segunda célula que acrescentaremos é aquela que manterá a caixa de texto do nome. As coordenadas de célula para este são 1,0 (segunda coluna, primeira linha); também mede por palmos só uma célula, e os pesos (por agora) também ambos são 100:
buildConstraints(constraints, 1, 0, 1, 1, 100, 100);
Dois seguintes componentes, que serão uma etiqueta e um campo de texto, são quase exatamente o mesmo como os dois prévios; a única diferença está nas suas coordenadas de célula. A etiqueta de senha está em 0,1 (primeira coluna, segunda linha), e o campo de texto de senha está em 1,1 (segunda coluna, segunda linha):
buildConstraints(constraints, 0, 1, 1, 1, 100, 100); buildConstraints(constraints, 1, 1, 1, 1, 100, 100);
E, finalmente, há Tecla OK, que é um componente que mede por palmos duas células na fila inferior da lista. Aqui as coordenadas de célula são a célula esquerda e o mais alta onde o palmo começa (0,2). Aqui, diferentemente dos componentes prévios, faremos que gridwidth e gridheight sejam outra coisa do que 1 porque esta célula mede por palmos múltiplas colunas. O gridweight é 2 (mede por palmos duas células), e o gridheight é 1 (mede por palmos só uma linha):
buildConstraints(constraints, 0, 2, 2, 1, 100, 100);
Adquiriu-o? Aqueles são os constrangimentos de colocação de todos os componentes que acrescentará ao leiaute de grade. Também precisará de destinar constrangimentos de cada componente ao gerente de leiaute e logo acrescentar cada componente à lista. A figura 13.17 mostra o resultado por enquanto. Observe que não se preocupa com proporções exatas aqui, ou com assegurar-se tudo se enfileira. De que deve guardar a pista neste ponto assegura-se que a grade trabalha, que há número direito de linhas e colunas, que os palmos são corretos, e que nada estranho continua (células no lugar errado, sobreposição de células, aquela espécie da coisa).
A figura 13.17: leiaute de bolsa de grade, primeiro passe.
O seguinte passo deve determinar as proporções das linhas e colunas em relação a outras linhas e colunas. Por exemplo, neste caso quererá que as etiquetas (nome e senha) tomem menos espaço do que as caixas de texto. E poderia querer que a Tecla OK no fundo fosse só a metade da altura das duas caixas de texto acima dele. Arranja as proporções das células dentro do seu leiaute usando constrangimentos de weighty e o weightx.
O modo mais fácil de pensar em weightx e weighty consiste em que os seus valores são percentagens da largura total e altura da lista ou 0 se o peso ou a altura se tenham estabelecido por alguma outra célula. Os valores de weightx e weighty de todos os seus componentes, por isso, devem somar a 100.
Nota técnica |
De fato, o weightx e os valores de weighty não são percentagens; são simplesmente proporções - podem ter qualquer valor em absoluto. Quando as proporções se calculam, todos os valores em uma direção somam-se para que cada valor individual esteja na proporção àquele total (em outras palavras, dividido no total para adquirir de fato uma percentagem). Como isto é inacreditavelmente não-intuitivo, acho muito mais fácil olhar para os pesos como percentagens e assegurar-me que todos eles sumariam a 100 para assegurar-se que sai tudo o direito. |
Assim, que células adquirem valores e que células adquirem 0? As células que medem por palmos múltiplas linhas ou colunas sempre devem ser 0 na direção que medem por palmos. Além disso, é simplesmente uma pergunta de escolher uma célula para ter um valor, e logo todas as outras células naquela linha ou colunas devem ser 0.
Vamos olhar para as cinco chamadas a buildConstraints() que fizemos no passo último:
buildConstraints(constraints, 0, 0, 1, 1, 100, 100); //name buildConstraints(constraints, 1, 0, 1, 1, 100, 100); //name text buildConstraints(constraints, 0, 1, 1, 1, 100, 100); //password buildConstraints(constraints, 1, 1, 1, 1, 100, 100); //password text buildConstraints(constraints, 0, 2, 2, 1, 100, 100); //OK button
Estaremos modificando aqueles dois argumentos últimos em cada chamada a buildConstraints para ser um valor ou 0. Vamos começar com a direção x (as proporções das colunas), que é o segundo-a-último argumento naquela lista.
Se rememorar à Figura 13.15 (o quadro da lista com a grade imposta), observará que a segunda coluna é muito maior do que o primeiro. Se ia escolher percentagens teóricas daquelas colunas, poderia dizer que o primeiro é 10 por cento e o segundo é 90 por cento (faço uma suposição aqui; isto é tudo que tem de fazer também). Com aquelas duas suposições, vamos destiná-los a células. Não queremos destinar qualquer valor à célula com a Tecla OK porque aquela célula mede por palmos tanto colunas, como as percentagens lá não trabalhariam. Por isso vamos acrescentá-los a duas primeiras células, o rótulo e o campo de texto de nome:
buildConstraints(constraints, 0, 0, 1, 1, 10, 100); //name buildConstraints(constraints, 1, 0, 1, 1, 90, 100); //name text
E os valores do resto duas células, a etiqueta de senha e campo de texto? Como as proporções das colunas já se fundaram pelo rótulo e campo, não temos de reinicializá-los aqui. Daremos ambas destas células e aquela para o OKAY caixa valores de 0:
buildConstraints(constraints, 0, 1, 1, 1, 0, 100); //password buildConstraints(constraints, 1, 1, 1, 1, 0, 100); //password text buildConstraints(constraints, 0, 2, 2, 1, 0, 100); //OK button
Observe aqui que um valor de 0 não significa que a célula tem 0 largura. Estas são proporções, não valores de pixel. Um 0 simplesmente significa que a proporção se estabeleceu em outro lugar; todo o 0 diz é "esticamento ele para ajustar-se".
Agora que os totais de todos os constrangimentos de weightx são 100, vamos entrar para o weighty s. Aqui há três linhas; olhadela sobre a grade que desenhamos, parece que o botão tem aproximadamente 20 por cento e os campos de texto têm o resto (40 por cento cada um). Como com os valores de x, só temos de estabelecer o valor de uma célula por linha (as duas etiquetas e o botão), com todas as outras células que têm um weightx de 0.
Aqui estão cinco chamadas finais a buildConstraints() com os pesos no lugar:
buildConstraints(constraints, 0, 0, 1, 1, 10, 40); //name buildConstraints(constraints, 1, 0, 1, 1, 90, 0); //name text buildConstraints(constraints, 0, 1, 1, 1, 0, 40); //password buildConstraints(constraints, 1, 1, 1, 1, 0, 0); //password text buildConstraints(constraints, 0, 2, 2, 1, 0, 20); //OK button
A figura 13.18 mostra o resultado com as proporções corretas.
A figura 13.18: leiaute de bolsa de grade segundo passo.
Neste passo, a meta aqui é tentar surgir com algumas proporções básicas a como as linhas e as células serão espaçadas na tela. Pode fazer algumas estimativas básicas baseadas em de que tamanho espera que vários componentes sejam, mas as possibilidades são vai usar muita prova e erro nesta parte do processo.
Com o leiaute e as proporções no lugar, agora pode substituir o botão placeholders com etiquetas reais e campos de texto. E porque funda tudo já, deve trabalhar tudo perfeitamente, certo? Bem, quase. A figura 13.19 mostra o que adquire se usar os mesmos constrangimentos que antes e substituir os botões com componentes reais.
A figura 13.19: leiaute de bolsa de grade, quase lá.
É fechado, mas é esquisito. As caixas de texto são demasiado altas, e a Tecla OK estica a largura da célula.
O que falha são os constrangimentos que arranjam os componentes dentro da célula. Há dois deles: fill e anchor.
O constrangimento de fill determina, para componentes que podem estender-se em qualquer direção (como caixas de texto e botões), em que direção estender-se. fill pode ter um de quatro valores, definidos como variáveis de classe na classe de GridBagConstraints:
Observar |
Tenha em mente que isto é o leiaute dinâmico. Não vai fundar as dimensões de pixel reais de qualquer componente; melhor diz estes elementos em que direção podem tornar-se dados uma lista que pode ser de qualquer tamanho. |
À revelia, o constrangimento de fill de todos os componentes é NONE. Então, por que são aqueles campos de texto e as etiquetas que enchem as células? Se se lembra do caminho atrás à partida do código deste exemplo, acrescentei esta linha ao método de init():
constraints.fill = GridBagConstraints.BOTH;
Agora sabe o que faz. Para a versão final deste applet, quererá retirar aquela linha e acrescentar valores de fill de cada componente independente.
O segundo constrangimento que afeta como um componente aparece na célula é anchor. Este constrangimento só aplica-se a componentes que não enchem a célula inteira, e diz ao awt onde dentro da célula colocar o componente. Os valores possíveis do constrangimento de anchor são GridBagConstraints.CENTER, que alinha o componente tanto verticalmente como horizontalmente dentro da célula ou um de oito valores de direção: GridBagConstraints.NORTH, GridBagConstraints.NORTHEAST, GridBagConstraints.EAST, GridBagConstraints.SOUTHEAST, GridBagConstraints.SOUTH, GridBagConstraints.SOUTHWEST, GridBagConstraints.WEST ou GridBagConstraints.NORTHWEST. O valor à revelia de anchor é GridBagConstraints.CENTER.
Estabelece estes constrangimentos de mesmo modo fez todos os outros: modificando variáveis de exemplo no objeto de GridBagConstraints. Aqui pode modificar a definição de buildConstraints() para tomar mais dois argumentos (são int s), ou somente pode estabelecê-los no corpo do método de init(). Prefiro o último caminho.
Tenha cuidado com defaults. Tenha em mente que porque reutiliza o mesmo objeto de GridBagConstraints de cada componente, podem haver alguns valores deixados acabados depois que se faz com um componente. De outro lado, se um fill ou anchor de um objeto não são o mesmo como aquele antes dele, não tem de reinicializar aquele objeto.
Para este exemplo, vou fazer três modificações do fill s e anchor s dos componentes:
Não vou mostrar-lhe todo o código para isto aqui; o código cheio do exemplo é no fim desta seção. Pode ver as modificações que fiz lá.
Acrescentei este passo à lista porque na minha própria experimentação com o leiaute de bolsa de grade, encontrei que até pelo seguinte todos os passos, normalmente o leiaute resultante não foi exatamente, e tinha de fazer um montante considerável de conserto e jogo com vários valores dos constrangimentos para conseguir que ele saia o direito (isto é o que futzing significa) não há nada mal com isto; a meta de três passos prévios foi adquirir coisas regularmente perto das suas posições finais, para não sair com um leiaute perfeito todo ou cada tempo.
A listagem 13.1 mostra o código completo do leiaute de lista que temos acumulado nesta seção. Se tinha a preocupação depois da discussão até este ponto, poderia achar útil atravessar esta linha de código pela linha para assegurar-se que entende vários bits.
A listagem 13.1. A lista com o leiaute de bolsa de grade final.
1:import java.awt.*; 2: 3:public class GridBagTestFinal extends java.applet.Applet { 4: 5: void buildConstraints(GridBagConstraints gbc, int gx, int gy, 6: int gw, int gh, 7: int wx, int wy) { 8: gbc.gridx = gx; 9: gbc.gridy = gy; 10: gbc.gridwidth = gw; 11: gbc.gridheight = gh; 12: gbc.weightx = wx; 13: gbc.weighty = wy; 14: } 15: 16: public void init() { 17: GridBagLayout gridbag = new GridBagLayout(); 18: GridBagConstraints constraints = new GridBagConstraints(); 19: setl1ayout(gridbag); 20: 21: // Name label 22: buildConstraints(constraints, 0, 0, 1, 1, 10, 40); 23: constraints.fill = GridBagConstraints.NONE; 24: constraints.anchor = GridBagConstraints.EAST; 25: Label label1 = new Label("Name:", Label.LEFT); 26: gridbag.setConstraints(label1, constraints); 27: add(label1); 28: 29: // Name text field 30: buildConstraints(constraints, 1, 0, 1, 1, 90, 0); 31: constraints.fill = GridBagConstraints.HORIZONTAL; 32: TextField tfname = new TextField(); 33: gridbag.setConstraints(tfname, constraints); 34: add(tfname); 35: 36: // password label 37: buildConstraints(constraints, 0, 1, 1, 1, 0, 40); 38: constraints.fill = GridBagConstraints.NONE; 39: constraints.anchor = GridBagConstraints.EAST; 40: Label label2 = new Label("Password:", Label.LEFT); 41: gridbag.setConstraints(label2, constraints); 42: add(label2); 43: 44: // password text field 45: buildConstraints(constraints, 1, 1, 1, 1, 0, 0); 46: constraints.fill = GridBagConstraints.HORIZONTAL; 47: TextField tfpass = new TextField(); 48: tfpass.setEchoCharacter('*'); 49: gridbag.setConstraints(tfpass, constraints); 50: add(tfpass); 51: 52: // OK Button 53: buildConstraints(constraints, 0, 2, 2, 1, 0, 20); 54: constraints.fill = GridBagConstraints.NONE; 55: constraints.anchor = GridBagConstraints.CENTER; 56: Button okb = new Button("OK"); 57: gridbag.setConstraints(okb, constraints); 58: add(okb); 59: } 60:}
Antes de terminar com o leiaute de bolsa de grade (não é ele acabado ainda?), há uns mais dois constrangimentos que merecem a menção: ipadx e ipady. Estes dois constrangimentos controlam o enchimento - isto é, o extra espaço em volta de um componente individual. À revelia, nenhum componente tem o extra espaço em volta deles (que é o mais fácil ver em componentes que enchem as suas células).
ipadx acrescenta o espaço a qualquer lado do componente, e ipady acrescenta-o em cima e abaixo.
A fenda horizontal e vertical, criada quando cria um novo gerente de leiaute (usando ipadx e ipady no leiaute de bolsa de grade), usa-se para determinar o montante do espaço entre componentes em uma lista. As inserções, contudo, usam-se para determinar o montante do espaço em volta da própria lista. A classe de Insets inclui valores do topo, fundo, deixado, e inserções direitas, que então se usam quando a própria lista se desenha.
As inserções determinam o montante do espaço entre as bordas de uma lista e que os componentes de lista.
Para incluir uma inserção, ignore o método de insets() na sua classe (a sua classe de Applet ou outra classe que serve de uma lista). Dentro do método de insets(), crie um novo objeto de Insets, onde o construtor à classe de Insets toma quatro valores inteiros que representam as inserções no topo, deixado, fundo e direito à lista. O método de insets() então deve devolver aquele objeto de Insets. Aqui está algum código para acrescentar inserções de um leiaute de grade, 10 ao topo e fundo, e 30 à esquerda e direito. (A figura 13.20 mostra a inserção):
public Insets insets() { return new Insets(10, 30, 10, 30); }
Os argumentos ao construtor de Insets fornecem inserções de pixel para o topo, fundo, deixado, e as bordas direitas da lista, respectivamente. Este determinado exemplo fornece uma inserção de 10 pixéis nos quatro lados da lista.
Se deixou de ler a lição de hoje agora mesmo, pode sair e criar um applet que tinha muitos pequenos componentes UI, agradavelmente expostos na tela com o gerente de leiaute próprio, fenda e inserções. Se realmente parasse aqui mesmo, contudo, o seu applet seria realmente enfadonho, porque nenhum dos seus componentes UI faria de fato nada quando se apertaram, se datilografaram em ou se selecionaram.
Para os seus componentes UI para fazer algo quando se ativam, tem de ligar a ação do UI com uma operação. As ações são uma forma do evento, e testando para uma ação por um componente UI implica a gestão de eventos. Tudo que aprendeu ontem sobre eventos entrará prático aqui.
As ações de UI são eventos que ocorrem quando um componente UI se ativa - apertado, selecionado, datilografado em, e assim por diante.
Para interceptar um evento de ação gerado por qualquer componente UI, define um método de action() no seu applet ou classe:
public boolean action(Event evt, Object arg) { ... }
O método de action() deve parecer semelhante ao rato básico e métodos de evento de teclado. Como aqueles métodos, passa-se o objeto de evento que representa este evento. Também adquire um extra objeto (neste código, o parâmetro arg), que pode ser de qualquer tipo de classe.
Que tipo de objeto que o segundo argumento ao método de ação é depende do componente UI isto gera a ação. A definição básica é que é qualquer argumento arbitral - quando um componente gera um evento, pode passar ao longo de qualquer extra informação que poderia ser útil para você usar no processamento daquela ação.
Todos os componentes UI básicos (exceto etiquetas, que não têm ação) têm ações diferentes e argumentos:
Observe que com ações, diferentemente de com eventos ordinários, pode ter muitos tipos diferentes de objetos que geram o evento de ação, ao contrário de um movimento único (uma prensa de rato) geração de um evento único (como um mouseDown). Para tratar com aqueles componentes UI diferentes e as ações geram, tem de testar para o tipo do objeto que enviou/criou o evento em primeiro lugar dentro do corpo do seu método de action(). Aquele objeto guarda-se na variável de exemplo de target do evento, e pode usar o operador instanceof para descobrir que tipo de componente UI lhe enviou:
public boolean action(Event evt, Object arg) { if (evt.target instanceof TextField) return handleText(evt.target); else if (evt.target instanceof Choice) return handleChoice(arg); ... }
Embora possa tratar ações UI no corpo do método de action(), é muito mais comum simplesmente definir um método especial no seu método de action() e chamada aquele método em vez disso. Aqui, há dois métodos especiais: um para tratar a ação no campo de texto (handleText()) e um para tratar a ação no cardápio seleto (handleChoice()). Dependendo da ação quer tratar, também pode querer transmitir o argumento da ação, o componente UI que o enviou, ou qualquer outra informação que o evento poderia conter.
Como com outros métodos de evento, action() devolve um valor booleano. Como com todos os métodos de evento, deve devolver true se próprio action() tratar com o método ou false se transmitir o método em outro lugar (ou o ignora).
A listagem 13.2 mostra um applet simples que tem cinco botões etiquetados com cores. Os testes de método de action() de uma ação de botão e logo passam o controle a um método chamado changeColor(), que modifica a cor de fundo do baseado applet no qual o botão se apertou (ver a Figura 13.21 para ver o applet na ação).
A figura 13.21: O ButtonAction applet.
A listagem 13.2. O ButtonActionsTest applet.
1:import java.awt.*; 2: 3:public class ButtonActionsTest extends java.applet.Applet { 4: 5: public void init() { 6: setBackground(Color.white); 7: 8: add(new Button("Red")); 9: add(new Button("Blue")); 10: add(new Button("Green")); 11: add(new Button("White")); 12: add(new Button("Black")); 13: } 14: 15: public boolean action(Event evt, Object arg) { 16: if (evt.target instanceof Button) { 17: changeColor((String)arg); 18: return true; 19: } else return false; 20: } 21: 22: void changeColor(String bname) { 23: if (bname.equals("Red")) setBackground(Color.red); 24: else if (bname.equals("Blue")) setBackground(Color.blue); 25: else if (bname.equals("Green")) setBackground(Color.green); 26: else if (bname.equals("White")) setBackground(Color.white); 27: else setBackground(Color.black); 28: 29: repaint(); 30: } 31:}
Como com a maior parte de applets situado em awt, estas partidas com um método de init() que inicializa o estado do applet e cria e acrescentam componentes ao leiaute. O método de init() definido em linhas 8 para 13 aqui escolhe a cor de fundo do applet ao branco e cria cinco novos botões com etiquetas a cores. Aqui usaremos o gerente de leiaute à revelia, que é um FlowLayout. Os botões aparecerão todos sucessivamente em cima da tela.
Com os botões no lugar, o segundo passo deve anexar ações àqueles botões. O método de action(), definido em linhas 15 para 20, faz isto. A primeira coisa a verificar é assegurar-se que é uma ação de botão isto gerou-se (linha 16) e, nesse caso para passar o extra argumento (forma a uma cadeia) ao método de changeColor(), que fará todo o trabalho para modificar a cor. Se o evento de fato for uma ação de botão, devolveremos true para interceptar aquele evento. De outra maneira, devolveremos false e deixaremos algum outro componente tratar o evento.
O método de changeColor() é onde todo o trabalho continua. Aqui testamos para cada uma das etiquetas de botão à sua vez para ver que botão foi isto apertou-se e estabelecer o contexto na cor apropriada. Um repinte final no fim faz a modificação real (escolhendo a cor de fundo não provoca automaticamente um repinte; terá de fazê-lo você mesmo).
Acrescentar componentes de UI a listas individuais ou applets é divertimento, mas trabalhando com o awt começa a transformar-se em muito divertimento quando começa a trabalhar com listas aninhadas. Pelo aninhamento listas diferentes dentro do seu applet e listas dentro daquelas listas, pode criar o leiaute diferente de partes diferentes da área applet total, isolar contexto e cores de primeiro plano e fontes a partes individuais de um applet, e dirigir o desenho dos seus componentes UI individualmente e em grupos distintos. Mais complexo o leiaute do seu applet, mais provavelmente vai querer usar listas aninhadas.
As listas, como já aprendeu, são componentes que podem expor-se de fato onscreen; a superclasse de Panel Container fornece o comportamento genérico para manter outros componentes dentro dele. A classe de Applet, da qual o seu applets todos herdam, é uma subclasse de Panel. Para aninhar outras listas dentro de um applet, simplesmente cria uma nova lista e acrescenta-o ao applet, tão como acrescentaria qualquer outro componente UI:
setl1ayout(new GridLayout(1, 2, 10, 10)); Panel panel1 = new Panel(); Panel panel2 = new Panel(); add(panel1); add(panel2);
Então pode fundar um leiaute independente daquelas sublistas e acrescentar-lhes componentes awt (inclusive ainda mais sublistas) chamando o método de add() na lista apropriada:
panel1.setl1ayout(new FlowLayout()); panel1.add(new Button("Up")); panel1.add(new Button("Down"));
Embora possa fazer tudo isso em uma classe única, é comum em applets gráfico e aplicações que fazem o uso pesado de sublistas ao fator fora o leiaute e o comportamento das sublistas em classes separadas e comunicar-se entre as listas usando métodos. Olhará para um exemplo extenso disto depois na lição de hoje na seção "Um Exemplo Completo: Convertedor de RGB-to-HSB".
Quando cria applets com listas aninhadas, aquelas listas formam uma hierarquia da lista externa (o applet, normalmente) ao componente UI íntimo. Esta hierarquia é importante para como cada componente na interface interage com outros componentes; por exemplo, a hierarquia componente determina a ordem na qual aqueles componentes se pintam à tela.
O que é mais importante, contudo, a hierarquia também afeta o manejo de evento, em particular para eventos introduzidos pelos usuários como eventos de teclado e rato.
Os eventos recebem-se pelo componente íntimo na hierarquia componente e deixaram passar a cadeia à lista do applet (ou à janela de raiz em aplicações de Java). Suponha, por exemplo, que tem um applet com uma sublista que pode tratar eventos de rato (usando o mouseDown() e métodos de mouseUp()), e aquela lista contém um botão. O clique no botão significa que o botão recebe o evento antes que a lista faça; se o botão não se interessar em que mouseDown(), o evento se passa à lista, que então pode processá-lo ou passá-lo além disso a hierarquia.
Lembrar-se da discussão sobre os métodos de evento básicos ontem? Aprendeu que os métodos de evento básicos todo o regresso valores booleanos. Aqueles valores booleanos ficam importantes quando fala sobre manejo de eventos ou transmissão deles.
Um método que trata o evento, se é o jogo de métodos de evento básicos ou o handleEvent() mais genérico, pode fazer uma de três coisas, considerando qualquer evento casual:
Depois que domina os componentes UI básicos e como acrescentá-los a listas, organizar o seu leiaute e dirigir os seus eventos, pode acrescentar mais componentes UI. Nesta seção, aprenderá sobre áreas de texto, listas se enrolam, scrollbars, e lonas.
Observe que a maioria dos componentes nesta seção não produzem ações, portanto não pode usar o método de action() para tratar o seu comportamento. Em vez disso, tem de usar um método de handleEvent() genérico para testar para eventos específicos que estes componentes UI geram. Aprenderá mais sobre isto na seguinte seção.
As áreas de texto parecem-se com campos de texto, exceto têm mais funcionalidade para tratar grandes montantes do texto. Como os campos de texto se limitam no tamanho e não se enrolam, são melhores para respostas de uma linha e entrada de dados simples; as áreas de texto podem ser qualquer largura dada e altura e ter scrollbars à revelia, portanto pode tratar com montantes maiores do texto mais facilmente.
As áreas de texto são componentes de entrada do texto maiores, enroláveis. Ao passo que os campos de texto só fornecem uma linha do texto, as áreas de texto podem manter qualquer montante do texto editable.
Para criar uma área de texto, use um dos seguintes construtores:
A figura 13.22 mostra uma área de texto simples gerada do seguinte código:
A figura 13.22: Uma área de texto.
import java.awt.*; public class TextAreaTest extends java.applet.Applet { public void init() { String str = "Once upon a midnight dreary, while I pondered, weak and weary,\n" + "Over many a quaint and curious volume of forgotten lore,\n" + "While I nodded, nearly napping, suddenly there came a tapping,\n" + "As of some one gently rapping, rapping at my chamber door.\n" + "\"'Tis some visitor,\" I muttered, \"tapping at my chamber door-\n" + "Only this, and nothing more.\"\n\n"; // more text deleted for space add(new TextArea(str,10,50)); } }
Tanto as áreas de texto como os campos de texto herdam da classe de TextComponent, portanto muito comportamento de campos de texto (em particular obtenção e colocação de texto e seleções) é usável em áreas de texto também (refira-se à Tabela 13.4). As áreas de texto também têm um número dos seus próprios métodos que pode achar útil. A tabela 13.5 mostra uma amostragem daqueles métodos.
Método | Ação |
getColumns() | Devolve a largura da área de texto, em carateres ou colunas |
getRows() | Devolve o número de linhas na área de texto (não o número de linhas do texto que a área de texto contém) |
insertText(String, int) | Insere a cadeia na posição dada no texto (partida de posições de texto em 0) |
replaceText(String, int, int) | Substitui o texto entre as posições de número inteiro dadas com a nova cadeia |
Lembre-se do cardápio seleto, com que pode escolher uma de várias opções diferentes? Uma lista que se enrola é funcionalmente semelhante a um cardápio seleto em que o deixa escolher várias opções de uma lista, mas as listas se enrolam se diferenciam de dois modos significantes:
As listas se enrolam fornecem um cardápio de itens que podem selecionar-se ou excluir-se. Diferentemente de cardápios seletos, as listas se enrolam não são menus instantâneos e podem definir-se para permitir múltiplas seleções.
Para criar uma lista que se enrola, crie um exemplo da classe de List e logo acrescente itens individuais àquela lista. A classe de List tem dois construtores:
Depois de criar um objeto de List, acrescente-lhe itens usando o método de addItem() e logo acrescente a própria lista à lista que o contém. Aqui está um exemplo que cria uma lista cinco itens altos que permite múltiplas seleções (o resultado deste código mostra-se na Figura 13.23):
A figura 13.23: Uma lista que se enrola.
import java.awt.*; public class ListsTest extends java.applet.Applet { public void init() { List lst = new List(5, true); lst.addItem("Hamlet"); lst.addItem("Claudius"); lst.addItem("Gertrude"); lst.addItem("Polonius"); lst.addItem("Horatio"); lst.addItem("Laertes"); lst.addItem("Ophelia"); add(lst); } }
As listas se enrolam geram ações quando o usuário clica duas vezes em um item de lista (o clique único gera um LIST_SELECT ou carteira de identidade de evento de LIST_DESELECT; aprenderá mais sobre estes na seção "mais Eventos UI"). Uma ação de lista que se enrola tem o argumento da cadeia do item que se clicou duas vezes.
A tabela 13.6 mostra alguns métodos disponíveis para listas se enrolam. Ver a documentação API de um conjunto completo.
Método | Ação |
getItem(int) | Devolve o item de cadeia na posição dada |
countItems() | Devolve o número de itens no cardápio |
getSelectedIndex() | Devolve a posição de índice do item que isto selecionou (usado para listas que permitem seleções só únicas) |
getSelectedIndexes() | Devolve uma tabela de posições de índice (usado para listas que permitem múltiplas seleções) |
getSelectedItem() | Devolve o item atualmente selecionado como uma cadeia |
getSelectedItems() | Devolve uma tabela de cadeias que contêm todos os itens selecionados |
select(int) | Seleciona o item na posição dada |
select(String) | Seleciona o item com aquela cadeia |
As áreas de texto e as listas se enrolam vêm com os seus próprios scrollbars, que se incorporam naqueles componentes UI e lhe permitem dirigir tanto o corpo da área ou a lista como o seu scrollbar como uma unidade única. Também pode criar scrollbars individual ou corredores, para manipular uma variedade de valores.
Scrollbars usam-se para selecionar um valor entre um máximo e um valor mínimo. Para modificar o valor atual disto scrollbar, pode usar três partes diferentes do scrollbar (seeFigure 13.24):
A figura 13.24: partes de Scrollbar.
Escolher algum destes elementos visuais causa uma modificação no valor do scrollbar; não tem de atualizar nada ou tratar qualquer evento. Tudo que tem de fazer é dão ao scrollbar um máximo e mínimo, e Java tratará o resto.
Um scrollbar é um elemento UI visual que lhe permite escolher um valor entre algum mínimo e algum máximo. Scrollbars chamam-se às vezes corredores.
Para criar um scrollbar, pode usar um de três construtores:
Aqui está um exemplo simples de um scrollbar que incrementa um valor único (ver a Figura 13.25). A etiqueta para a esquerda do scrollbar atualiza-se cada vez as modificações de valor do scrollbar:
import java.awt.*; public class SliderTest extends java.applet.Applet { Label l; public void init() { setl1ayout(new GridLayout(1,2)); l = new Label("0", Label.CENTER); add(l); add(new Scrollbar(Scrollbar.HORIZONTAL,0,0,1,100)); } public Insets insets() { return new Insets(15,15,15,15); } public boolean handleEvent(Event evt) { if (evt.target instanceof Scrollbar) { int v = ((Scrollbar)evt.target).getValue(); l.setText(String.valueOf(v)); repaint(); return true; } else return false; } }
A classe de Scrollbar fornece vários métodos para dirigir os valores dentro de scrollbars. (Ver a Tabela 13.7.)
Método | Ação |
getMaximum() | Devolve o valor máximo. |
getMinimum() | Devolve o valor mínimo. |
getOrientation() | Devolve a orientação deste scrollbar: 0 é Scrollbar.HORIZONTAL; 1 é Scrollbar.VERTICAL. |
getValue() | Devolve o valor atual do scrollbar. |
setValue(int) | Estabelece o valor atual do scrollbar. |
setl1ineIncrement(int inc) | Modifique o incremento para a que distância enrolar-se quando os endpoints do scrollbar se selecionam. O default é 1. |
getLineIncrement() | Devolve o incremento para a que distância enrolar-se quando os endpoints do scrollbar se selecionam. |
setPageIncrement(int inc) | Modifique o incremento para a que distância enrolar-se quando a variedade interior do scrollbar se seleciona. O default é 10. |
getPageIncrement() | Devolve o incremento para a que distância enrolar-se quando a variedade interior do scrollbar se seleciona. |
Embora possa atrair a maior parte de componentes awt como listas usando os métodos de gráficos sobre os quais aprendeu no Dia 11, "Mais Animação, Imagens e Som", as lonas fazem pouco exceto o deixado atrai-os. Não podem conter outros componentes, mas podem aceitar eventos, e pode criar a animação e expor imagens neles. Se tiver uma lista que não precisa de fazer nada exceto imagens de exposição ou animação, uma lona faria uma superfície de peso mais leve do que uma lista ia.
Uma lona é um componente que pode atrair.
Para criar uma lona, use a classe de Canvas e acrescente-o a uma lista como ia qualquer outro componente:
Canvas can = new Canvas(); add(can);
Ontem, aprendeu sobre alguns tipos de evento básicos que se geram da entrada de usuário ao rato ou o teclado. Estes tipos de evento guardam-se no objeto de Event como a carteira de identidade de evento e podem testar-se para no corpo de um método de handleEvent() usando variáveis de classe definidas em Event. Para muitos eventos básicos, como mouseDown() e keyDown(), pode definir métodos daqueles eventos para tratar o evento diretamente. Aprendeu um mecanismo semelhante hoje de ações UI onde criar um método de action() tratou uma ação específica gerada por um componente UI.
O modo mais geral de dirigir eventos, contudo, continua sendo o método de handleEvent(). Para eventos que se relacionam scrollbars e listas se enrolam, o único modo de interceptar estes eventos é ignorar handleEvent().
Para interceptar um evento específico, teste para a carteira de identidade daquele evento. As carteiras de identidade disponíveis definem-se como variáveis de classe na classe de Event, portanto pode testá-los de nome. Aprendeu sobre alguns eventos básicos ontem; a Tabela 13.8 mostra eventos adicionais que podem ser úteis para você para os componentes sobre os quais aprendeu hoje (ou que poderia achar útil em geral).
Carteira de identidade de evento | O que representa |
ACTION_EVENT | Gerado quando uma ação componente UI ocorre |
GOT_FOCUS | Gerado quando o usuário clica dentro de uma área de texto |
LOST_FOCUS | Gerado quando o usuário clica em qualquer lugar do lado de fora de uma área de texto (depois de ser dentro de um) |
LIST_DESELECT | Gerado quando um item em uma lista que se enrola se exclui |
LIST_SELECT | Gerado quando um item em uma lista que se enrola se seleciona |
SCROLL_ABSOLUTE | Gerado quando a caixa de um scrollbar se moveu |
SCROLL_LINE_DOWN | Gerado quando o fundo de um scrollbar ou o endpoint deixado (botão) se selecionam |
SCROLL_LINE_UP | Gerado quando o topo de um scrollbar ou o direito endpoint (botão) se selecionam |
SCROLL_PAGE_DOWN | Gerado quando o campo do scrollbar abaixo (ou para a esquerda de) a caixa se seleciona |
SCROLL_PAGE_UP | Gerado quando o campo do scrollbar em cima (ou para a direita de) a caixa se seleciona |
A classe de Component é a raiz de todos os objetos de awt: todos os elementos UI, listas, lonas, até applets. Quase tudo que pode expor, expor, modificar a cor de, desenhar a ou interagir com a utilização de eventos no awt é um componente.
Os componentes têm o grupo de métodos que lhe permitem modificar a sua aparência ou modificar o seu comportamento. Viu o uso de alguns destes métodos já (setBackground(), setFont, size()), apresentou-se especificamente a applets. Mas os métodos definidos em Component podem usar-se com qualquer componente, permitindo-lhe modificar a aparência ou o comportamento de quase qualquer elemento no seu programa. Também pode criar componentes alfandegários (classes que herdam de Panel ou Canvas) fazer os seus próprios elementos awt especiais ou coisas de interface de usuário.
A tabela 13.9 resume alguns métodos que pode usar com componentes individuais. Para mais métodos, verifique Java documentação de API da classe Component. O JDK 1.0.2 documentação é online em
http://java.sun.com:80/products/JDK/CurrentRelease/api/
getBackground() | Devolve um objeto de Color que representa a cor de fundo do componente. |
setBackground(Color) | Escolhe a cor de fundo do componente. |
getForeground() | Devolve um objeto de Color que representa a cor de primeiro plano atual do componente. |
setForeground(Color) | Escolhe a cor de primeiro plano do componente |
getFont() | Devolve um objeto de Font que representa a fonte atual do componente. |
setFont(Font) | Modifica a fonte atual do componente. |
size() | Devolve um objeto de Dimension que representa o tamanho atual do componente. Então pode vir à largura individual e altura usando size().width() e size().height(). |
minimumSize() | O tamanho mais pequeno possível do componente como um objeto de Dimension. minimumSize() só se usa normalmente por gerentes de leiaute para determinar como pequeno pode desenhar um componente; se criar um componente alfandegário quererá ignorar este método para devolver o tamanho mínimo daquele componente. |
preferredSize() | O tamanho preferencial do componente (normalmente igual a ou maior do que o minimumSize() do componente) como um objeto de Dimension. |
resize(Dimension) | Modifica o tamanho do applet para ser o tamanho atual. Para componentes alfandegários quererá chamar também validate() depois de alterar o tamanho do applet para que o leiaute possa desenhar-se novamente. |
inside(x, y) | true de regressos se o x dado e as coordenadas de y são dentro do componente. |
hide() | Esconde o componente. Os componentes escondidos não descobrem onscreen. |
show() | Mostra um componente anteriormente escondido. |
isVisible() | true de regressos ou false dependendo de se este componente é visível (não escondido). |
disable() | Inutiliza o componente - isto é, paradas gerar eventos. Os componentes fora do serviço não podem apertar-se, selecionar-se de, datilografar-se em, e assim por diante. |
enable() | Permite um objeto anteriormente fora do serviço. |
isEnabled() | true de regressos ou false dependendo de se o componente se permite. |
Vamos descansar um pouco aqui de teoria e mais pequenos exemplos para criar um exemplo maior que junta a maior parte do que aprendeu por enquanto. O seguinte exemplo applet demonstra leiaute, listas de aninhamento, criando componentes de interface do usuário, e pegando e tratando ações, bem como usando múltiplas classes para juntar um applet único. Em resumo, é o applet mais complexo que criou por enquanto.
A figura 13.26 mostra o applet que estará criando neste exemplo. O ColorTest applet permite-lhe escolher cores baseadas em RGB (vermelho, verde, e azul) e HSB (cor, saturação e brilho) valores.
A figura 13.26: O ColorTest applet.
Observar |
Um sumário muito rápido em caso de que não é familiar com a teoria a cores básica: a cor de RGB define uma cor pelos seus valores vermelhos, verdes, e azuis; alguma combinação destes valores pode produzir qualquer cor no espectro (vermelho, verde, e azul chamam-se cores adicionais; isto é como o seu monitor e a sua TV representam cores diferentes). HSB significa a cor, a saturação e o brilho e é um modo diferente de indicar a cor. A cor é a cor real no espectro que representa (pense nele como valores ao longo de uma roda a cores). A saturação é o montante daquela cor; a saturação baixa resulta em pastéis; as cores de alta saturação são mais vibrantes e "coloridas". O brilho, finalmente, é a leveza ou a escuridade da cor. Nenhum brilho é preto; o brilho cheio é branco. Uma cor única pode representar-se pelos seus valores de RGB ou pelos seus valores de HSB, e há algoritmos matemáticos para converter entre eles. O ColorTest applet fornece um convertedor gráfico entre os dois. |
O ColorTest applet tem três partes principais: uma caixa colorida no lado abandonado e dois grupos de campos de texto à direita. O primeiro grupo indica valores de RGB; o direito, HSB. Modificando algum dos valores em alguma das caixas de texto, a caixa colorida atualiza-se à nova cor, como são os valores em outro grupo de caixas de texto.
Observar |
Se tentar este applet, sabem que tem de pressionar Entram ou Regresso depois de modificar um número da atualização para ocorrer. Usar a tecla Tab para mover-se entre campos de texto ou clicar com o rato não farão que ao applet atualize. |
Este applet usa duas classes:
Vamos trabalhar por isto passo a passo, porque é muito complicado e pode tornar-se confuso. Todo o código deste applet vai se mostrar no fim desta seção.
O melhor modo de começar a criar um applet que usa componentes awt é incomodar-se com o leiaute primeiro e logo incomodar-se com a funcionalidade. Tratando com o leiaute, deve começar com a lista externa primeiro e trabalhar para dentro.
Fazer um esboço do seu desenho de UI pode ajudá-lo a compreender como organizar as listas dentro do seu applet ou janela para aproveitar-se melhor de leiaute e espaço. Os desenhos de papel são úteis mesmo quando não usa o leiaute de bolsa de grade, mas duplamente portanto quando é (estaremos usando um leiaute de grade simples para este applet).
A figura 13.27 mostra o ColorTest applet com uma grade desenhada sobre ele para que possa adquirir uma ideia de como as listas e as listas introduzidas trabalham.
A figura 13.27: As listas ColorTest applet e componentes.
Vamos começar com a lista externa - o próprio applet. Esta lista tem três partes: a caixa a cores à esquerda, os campos de texto RGB no meio e os campos HSB à direita.
Como a lista externa é o próprio applet, a sua classe de ColorTest será a classe applet e herdará de Applet. Também importará as classes awt aqui (observe que porque usa tantos deles neste programa, é o mais fácil importar somente o pacote inteiro):
import java.awt.*; public class ColorTest extends java.applet.Applet { ... }
Este applet tem três coisas principais a guardar a pista de: a caixa a cores e as duas sublistas. As duas sublistas que cada um envia a coisas diferentes, mas são essencialmente a mesma lista e se comportam dos mesmos modos. Em vez de duplicar muito código aqui nesta classe, isto é uma oportunidade perfeita de criar outra classe somente das sublistas, usar exemplos daquela classe aqui no applet e comunicar entre tudo métodos de utilização. Em um bocado definiremos aquela nova classe, chamada ColorControls.
Por agora, contudo, sabemos que temos de guardar uma maçaneta às três partes do applet portanto pode atualizá-los quando se modificam. Por isso vamos criar três variáveis de exemplo: um de tipo Canvas da caixa a cores e outros dois de tipo ColorControls dos painéis de controle:
ColorControls RGBcontrols, HSBcontrols; Canvas swatch;
Agora entraremos para o método de init(), onde toda a inicialização básica e o leiaute do applet se realizam. Há três passos à inicialização deste applet:
Passo cada um é o leiaute. Vamos usar um leiaute de grade e uma fenda de 10 pontos para separar cada um dos componentes:
setl1ayout(new GridLayout(1, 3, 5, 15));
O passo dois cria os componentes - a lona primeiro. Tem uma variável de exemplo para considerar que um. Aqui criaremos a lona e inicializaremos o seu contexto ao preto:
swatch = new Canvas(); swatch.setBackground(Color.black);
Tem de criar dois exemplos do seu "desde ainda" listas de ColorControls não existentes aqui também, mas porque não criamos a classe ainda não sabemos a que os construtores àquela classe parecerão. Vamos instalar em alguns construtores placeholder aqui; preencheremos os detalhes depois:
RGBcontrols = new ColorControls(...) HSBcontrols = new ColorControls(...);
O passo três acrescenta os três componentes à lista applet:
add(swatch); add(RGBcontrols); add(HSBcontrols);
Enquanto trabalha no leiaute, vamos acrescentar inserções do applet: 10 pontos ao longo de todas as bordas:
public Insets insets() { return new Insets(10, 10, 10, 10); }
Adquiriu-o por enquanto? Neste ponto tem três variáveis de exemplo, um método de init() com dois construtores incompletos e um método de insets() na sua classe de ColorTest. Vamos mudar agora à criação do leiaute de sublista na classe de ColorControls portanto podemos preencher aqueles construtores e terminar o leiaute.
A classe de ColorControls terá comportamento para expor e tratar as sublistas que representam o RGB e valores de HSB da cor. ColorControls não precisa de ser uma subclasse de Applet porque não é de fato um applet; é somente uma lista. Defina-o para herdar de Panel:
import java.awt.* class ColorControls extends Panel { ... }
Observar |
Pus o texto fonte de ColorControls no seu próprio arquivo, chamado ColorControls.java. Contudo, pode pôr a classe de ColorControls no mesmo arquivo que a classe de ColorTest. Até este ponto, só definiu uma classe por arquivo, com o nome de arquivo o mesmo nome que a classe. Em Java pode ter múltiplas definições de classe em um arquivo até só uma daquelas classes declara-se pelo público (e o nome do arquivo original é o mesmo como aquela classe pública). Neste caso, a classe de ColorTest é pública (é um applet, portanto tem de ser), mas a classe de ColorControls não é pública, portanto pode estar no mesmo arquivo original. Quando compilar o arquivo, Java criará múltiplos arquivos de classe apropriados de cada definição de classe. Aprenderá mais sobre classes públicas no Dia 15, "Modificadores, Controle de acesso e Desenho de Classe", e Dia 16, "Pacotes e Interfaces". Em geral, contudo, prefiro usar arquivos originais separados para as minhas classes. Facilita para mim encontrar a fonte de uma determinada classe porque não tenho de lembrar-me em que arquivo o defini. |
A classe de ColorControls precisará de um número de variáveis de exemplo para que a informação da lista possa voltar ao applet. A primeira destas variáveis de exemplo é um gancho suportam à classe applet que contém esta lista. Como é a classe applet exterior que controla a atualização de cada lista, esta lista precisará de um modo de dizer ao applet que algo se modificou. E chamar um método nisto applet, precisa de uma referência para aquele objeto. Deste modo, a variável de exemplo número um é uma referência um exemplo da classe ColorTest:
ColorTest applet;
Se compreender que a classe applet é aquela isto vai estar atualizando tudo, que classe se indo interessar-se nos campos de texto individuais nesta sublista. Criaremos variáveis de exemplo daqueles campos de texto:
TextField tfield1, tfield2, tfield3;
Agora vamos mudar ao construtor desta classe. Como esta classe não é um applet, não usaremos init() para inicializá-la; em vez disso usaremos um método de construtor.
Dentro do construtor fará a maior parte do que fez dentro de init(): crie o leiaute da sublista, crie os campos de texto e acrescente-os à lista.
A meta aqui é fazer a classe de ColorControls bastante genérica para que possa usá-lo tanto para os campos RGB como para os campos HSB. Aquelas duas listas diferenciam-se em só um respeito: as etiquetas do texto. Isto é três valores para vir antes que possa criar o objeto. Pode passar aqueles três valores em pelos construtores em ColorTest. Também precisa de um mais: aquela referência para o cerrado applet, que pode adquirir do construtor também.
Agora tem quatro argumentos ao construtor básico da classe de ColorControls. Aqui está a assinatura daquele construtor:
ColorControls(ColorTest parent, String l1, String l2, String l3) { }
Vamos começar este construtor pela primeira colocação o valor de parent à variável de exemplo applet:
applet = parent;
Depois, crie o leiaute desta lista. Também pode usar um leiaute de grade para estas sublistas, como fez para a lista applet, mas esta vez a grade terá três linhas (um para cada um do campo de texto e etiquetará pares) e duas colunas (um para as etiquetas e um para os campos). Também definiremos uma fenda de 10 pontos entre os componentes na grade:
setl1ayout(new GridLayout(3,2,10,10));
Agora podemos criar e acrescentar os componentes à lista. Em primeiro lugar, criaremos os objetos de campo de texto (inicializado à cadeia "0") e os destinaremos às variáveis de exemplo apropriadas:
tfield1 = new TextField("0"); tfield2 = new TextField("0"); tfield3 = new TextField("0");
Agora acrescentaremos aqueles campos e as etiquetas apropriadas à lista, usando o resto três parâmetros ao construtor como o texto das etiquetas:
add(new Label(l1, Label.RIGHT)); add(tfield1); add(new Label(l2, Label.RIGHT)); add(tfield2); add(new Label(l3, Label.RIGHT)); add(tfield3);
Isto termina o construtor da classe de sublista ColorControls. Fazemo-nos com o leiaute? Não exatamente. Também acrescentaremos uma inserção em volta do único pela sublista nas bordas inferiores e superiores - para remendar o leiaute. Acrescente a inserção aqui como fez na classe de ColorTest, usando o método de insets():
public Insets insets() { return new Insets(10, 10, 0, 0); }
Está quase lá. Tem 98 por cento da estrutura básica no lugar e pronto para ir, mas há um passo deixado: a volta a ColorTest e a fixação daqueles construtores placeholder da sublista portanto combinam com os construtores reais de ColorControls.
O construtor de ColorControls que somente criamos agora tem quatro argumentos: o objeto de ColorTest e três etiquetas (cadeias). Lembre-se atrás a quando criamos o método de init() de ColorTest: acrescentamos dois placeholders para criar novos objetos de ColorControls; substituiremos aqueles placeholders com as versões corretas agora. Assegure-se que acrescenta os quatro argumentos que o construtor tem de trabalhar: o objeto de ColorTest e três cadeias. Para passar o ColorTest objetam àqueles construtores, podemos usar a palavra-chave de this:
RGBcontrols = new ColorControls(this, "Red", "Green", "Blue"); HSBcontrols = new ColorControls(this, "Hue", "Saturation", "Brightness");
Observar |
Pelos valores iniciais de todos os campos de texto neste exemplo, usei o número 0 (de fato, a cadeia "0"). Para o preto a cores, tanto o RGB como os valores de HSB são 0, que é porque posso fazer esta suposição. Se quis inicializar o applet para ser alguma outra cor, poderia querer reescrever a classe de ColorControls para usar valores de initializer bem como inicializar etiquetas. Este caminho faz-se para um exemplo mais curto. |
Com o leiaute feito, o seu tempo para fundar o manejo de evento e a atualização entre vários componentes para que quando o usuário interage com o applet, o applet possa responder.
A ação deste applet ocorre quando o usuário modifica um valor em algum dos campos de texto e as prensas Entram. Causando uma ação em um campo de texto, as modificações a cores, as atualizações de caixa a cores da nova cor e os valores dos campos na sublista oposta modificam-se para refletir a nova cor.
A classe de ColorTest é responsável por fazer de fato a atualização porque guarda a pista de todas as sublistas. Como o evento real ocorre na sublista, contudo, precisará de seguir a pista e interceptar aqueles eventos naquela sublista usando o método de action() na classe de ColorControls:
public boolean action(Event evt, Object arg) { if (evt.target instanceof TextField) { applet.update(this); return true; } else return false; }
No método de action(), testa para assegurar-se que a ação de fato se gerou por um campo de texto (porque só há os campos de texto disponíveis, isto é a única ação que adquirirá, mas é uma boa ideia de testar para ele de qualquer maneira). Se de fato houve uma ação de campo de texto, chamaremos um método para atualizar todas as sublistas. Aquele método, que chamaremos update(), define-se na classe de cerrado, portanto o chamaremos usando o objeto guardado na variável de exemplo applet (e passaremos ao longo de uma referência para a lista para que o applet possa alcançar os nossos valores). E, finalmente, devolveremos true ou false para que outras ações que poderiam ocorrer neste applet possam passar-se ao longo ao cerrado de listas ou componentes.
Agora vem a parte difícil: de fato fazer a atualização baseada nos novos valores de qualquer campo de texto modificou-se. Para isto, define o método de update() na classe de ColorTest. Este método de update() toma um argumento único - o exemplo de ColorControls que contém o valor modificado (adquire aquele argumento do método de action() no objeto de ColorControls).
Observar |
Este método de update() não mexerá no método de update() do sistema? Não. Lembre-se, os métodos podem ter o mesmo nome, mas assinaturas diferentes e definições. Como este update() tem um argumento único do tipo ColorControls, não mexe em outra versão de update(). Normalmente, todos os métodos chamados update() devem significar basicamente a mesma coisa; não é verdade aqui, mas é só um exemplo. |
O método de update() é responsável por atualizar todas as listas no applet. Saber que lista atualizar, tem de saber que lista se modificou. Pode descobrir testando para ver se o argumento passou-se da lista é o mesmo como as sublistas que guardou no RGBcontrols e variáveis de exemplo de HSBcontrols:
void update(ColorControls controlPanel) { if (controlPanel == RGBcontrols) { // RGB has changed, update HSB ... } else { // HSB has changed, update RGB ... } }
Este teste é o coração do método de update(). Vamos começar com aquele primeiro número de caso-a modificou-se nos campos de texto RGB. Assim, agora, baseado naqueles novos valores de RGB, tem de gerar um novo objeto de Color e atualizar os valores na lista HSB. Para reduzir alguma datilografia, cria algumas variáveis locais para manter alguns valores básicos. Especialmente, os valores dos campos de texto são cadeias cujos valores pode adquirir à utilização do método de getText() definido nos objetos de TextField do objeto de ColorControls. Como a maior parte do tempo neste método quereremos tratar com aqueles valores como números inteiros, adquiriremos aqueles valores de cadeia, os converteremos em números inteiros e os guardaremos em variáveis locais (value1, value2, value3). Aqui está o código para fazer isto (parece mais complicado do que de fato é):
int value1 = Integer.parseInt(controlPanel.tfield1.getText()); int value2 = Integer.parseInt(controlPanel.tfield2.getText()); int value3 = Integer.parseInt(controlPanel.tfield3.getText());
Enquanto definimos aqui variáveis locais, também precisaremos um para o novo objeto de Color:
Color c;
OKAY. Vamos supor que um dos campos de texto no lado RGB do applet tenha modificado e acrescente o código à parte de if do método de update(). Precisaremos de criar um novo objeto de Color e atualizar o lado HSB da lista. Aquela primeira parte é fácil; considerando os três valores de RGB, pode criar um novo objeto de Color usando aqueles como argumentos ao construtor:
c = new Color(value1, value2, value3);
Observar |
Esta parte do exemplo não é muito robusta; supõe que o usuário de fato tenha entrado em números inteiros de 0 a 255 nos campos de texto. Uma melhor versão disto testaria para assegurar-se que nenhum erro de entrada de dados tinha ocorrido (tentava guardar este exemplo pequeno). |
Agora converteremos os valores de RGB em HSB. Há algoritmos padrão para converter uma cor baseada em RGB em uma cor de HSB, mas não temos de ir procuram-nos. A classe de Color tem um método de classe que podemos usar chamou RGBtoHSB() que fará o trabalho para nós - ou, pelo menos, a maioria dela. Há dois problemas com o método de RGBtoHSB(), contudo:
Nenhum destes problemas é insuperável; somente significa algumas extra linhas do código. Vamos começar chamando RGBtoHSB() com os novos valores de RGB que temos. O tipo de regresso daquele método é uma tabela de bóias, portanto criaremos uma variável local (HSB) para guardar os resultados do método de RBGtoHSB(). (Observe que também precisará de criar e passar em uma tabela vazia de bóias como o quarto argumento a RGBtoHSB()):
float[] HSB = Color.RGBtoHSB(value1, value2, value3, (new float[3]));
Agora converteremos aqueles valores de ponto flutuante que variam de 0.0 a 1.0 a valores que variam de 0 e 100 (para a saturação e brilho) e 0 a 360 da cor multiplicando os números apropriados e redestinando o valor atrás à tabela:
HSB[0] *= 360; HSB[1] *= 100; HSB[2] *= 100;
Agora temos os números que queremos. A parte última da atualização deve repôr aqueles valores nos campos de texto. Naturalmente, aqueles valores ainda são números de ponto flutuante, portanto teremos de lançá-los a int s antes de convertê-los em cadeias e guardá-los:
HSBcontrols.tfield1.setText(String.valueOf((int)HSB[0])); HSBcontrols.tfield2.setText(String.valueOf((int)HSB[1])); HSBcontrols.tfield3.setText(String.valueOf((int)HSB[2]));
É a meia distância lá. A seguinte parte do applet é que a parte que atualiza os valores de RGB onde um campo de texto no lado HSB se modificou. Isto é o else no grande if-else que define este método e determina que atualizar, considerando uma modificação.
É de fato mais fácil gerar valores de valores de HSB do que deve fazê-lo outro caminho em volta. Há um método de classe na classe de Color, chamada getHSBColor(), que cria um novo objeto de Color de três valores de HSB, e uma vez que tem um objeto de Color fora do qual que pode puxar facilmente os valores de RGB lá. O proveito, naturalmente, é que getHSBColor toma três argumentos de ponto flutuante, e os valores que temos são os valores inteiros que prefiro usar. Assim na chamada a getHSBColor, teremos de lançar os valores inteiros dos campos de texto a bóias e dividi-los pelo fator de conversão próprio. O resultado de getHSBColor é um objeto de Color, portanto simplesmente podemos destinar aquele objeto ao nosso c variável local portanto podemos usá-lo novamente depois:
c = Color.getHSBColor((float)value1 / 360, (float)value2 / 100, (float)value3 / 100);
Com o objeto de Color todo o jogo, a atualização dos valores de RGB implica a extração daqueles valores daquele objeto de Color. O getRed(), getGreen() e métodos de getBlue(), definidos na classe de Color, fará somente que:
RGBcontrols.tfield1.setText(String.valueOf(c.getRed())); RGBcontrols.tfield2.setText(String.valueOf(c.getGreen())); RGBcontrols.tfield3.setText(String.valueOf(c.getBlue()));
E finalmente, mesmo que o valor de HSB ou RGB se tenha modificado, precisará de atualizar a caixa a cores à esquerda para refletir a nova cor. Como temos um novo objeto de Color guardado no c variável, podemos usar o método de setBackground para modificar aquela cor. Também observe que setBackground não repinta automaticamente a tela, portanto quererá disparar um repaint() também:
swatch.setBackground(c); swatch.repaint();
É isso! Faz-se. Compile tanto o ColorTest como classes de ColorControls, crie um arquivo de HTML para carregar o ColorTest applet e verificá-lo.
A listagem 13.3 mostra o texto fonte completo da classe applet ColorTest, e a Listagem 13.4 mostra a fonte da classe de ajudante ColorControls. Muitas vezes é mais fácil compreender o que está acontecendo em um applet quando é tudo em um lugar e pode seguir as chamadas de método e como os valores se passam para a frente e para trás. Comece com o método de init() no ColorTest applet e vá daí.
A listagem 13.3. O ColorTest applet.
1:import java.awt.*; 2: 3:public class ColorTest extends java.applet.Applet { 4: ColorControls RGBcontrols, HSBcontrols; 5: Canvas swatch; 6: 7: public void init() { 8: setl1ayout(new GridLayout(1,3,5,15)); 9: 10: // The color swatch 11: swatch = new Canvas(); 12: swatch.setBackground(Color.black); 13: 14: // the subpanels for the controls 15: RGBcontrols = new ColorControls(this, "Red", "Green", "Blue"); 16: HSBcontrols = new ColorControls(this, "Hue", "Saturation", "Brightness"); 17: 18: //add it all to the layout 19: add(swatch); 20: add(RGBcontrols); 21: add(HSBcontrols); 22: } 23: 24: public Insets insets() { 25: return new Insets(10,10,10,10); 26: } 27: 28: void update(ColorControls controlPanel) { 29: Color c; 30: // get string values from text fields, convert to ints 31: int value1 = Integer.parseInt(controlPanel.tfield1.getText()); 32: int value2 = Integer.parseInt(controlPanel.tfield2.getText()); 33: int value3 = Integer.parseInt(controlPanel.tfield3.getText()); 34: 35: if (controlPanel == RGBcontrols) { // RGB has changed, update HSB 36: c = new Color(value1, value2, value3); 37: 38: // convert RGB values to HSB values 39: float[] HSB = Color.RGBtoHSB(value1, value2, value3, (new float[3])); 40: HSB[0] *= 360; 41: HSB[1] *= 100; 42: HSB[2] *= 100; 43: 44: // reset HSB fields 45: HSBcontrols.tfield1.setText(String.valueOf((int)HSB[0])); 46: HSBcontrols.tfield2.setText(String.valueOf((int)HSB[1])); 47: HSBcontrols.tfield3.setText(String.valueOf((int)HSB[2])); 48: 49: } else { // HSB has changed, update RGB 50: c = Color.getHSBColor((float)value1 / 360, 51: (float)value2 / 100, (float)value3 / 100); 52: 53: // reset RGB fields 54: RGBcontrols.tfield1.setText(String.valueOf(c.getRed())); 55: RGBcontrols.tfield2.setText(String.valueOf(c.getGreen())); 56: RGBcontrols.tfield3.setText(String.valueOf(c.getBlue())); 57: } 58: 59: //update swatch 60: swatch.setBackground(c); 61: swatch.repaint(); 62:} 63:}
A listagem 13.4. A classe de ColorControls.
1:import java.awt.*; 2: 3:class ColorControls extends Panel { 4: TextField tfield1, tfield2, tfield3; 5: ColorTest applet; 6: 7: ColorControls(ColorTest parent, 8: String l1, String l2, String l3) { 9: 10: // get hook to outer applet parent 11: applet = parent; 12: 13: //do layouts 14: setl1ayout(new GridLayout(3,2,10,10)); 15: 16: tfield1 = new TextField("0"); 17: tfield2 = new TextField("0"); 18: tfield3 = new TextField("0"); 19: 20: add(new Label(l1, Label.RIGHT)); 21: add(tfield1); 22: add(new Label(l2, Label.RIGHT)); 23: add(tfield2); 24: add(new Label(l3, Label.RIGHT)); 25: add(tfield3); 26: } 27: 28: public Insets insets() { 29: return new Insets(10,10,0,0); 30: } 31: 32: public boolean action(Event evt, Object arg) { 33: if (evt.target instanceof TextField) { 34: applet.update(this); 35: return true; 36: } else return false; 37: } 38:}
Tudo que aprendeu até este ponto está disponível em 1.0.2 Java API. Java 1.1, contudo, acrescentará muitas outras características ao awt, bem como melhorará a realização e a robustez através de plataformas. A meta do awt é mover-se além dos fundamentos que 1.0.2 fornecidos e fazem o mais conveniente awt do desenvolvimento de aplicações amplo. Observe, também, que os 1.1 API serão para trás e compatíveis com as 1.0.2 características; nenhum do código que escreve depois de ler este capítulo será obsoleto em 1,1.
Os detalhes explícitos sobre as modificações do awt para 1,1 não estiveram disponíveis enquanto este livro se escrevia. O sol anunciou os seguintes importunadores, contudo para novas características em 1,1:
Para mais informação sobre Java 1,1 modificações do awt, verifique a 1,1 página de visualização em http://java.sun.com/products/JDK/1.1/designspecs/.
Java awt ou Caixa de ferramentas de Windowing Abstrata, é um pacote de classes de Java e interfaces para criar o acesso crescido a um sistema de interface de usuário gráfico baseado na janela, com mecanismos de exposição de gráficos, gestão de eventos, texto e primitivos de gráficos, componentes de interface do usuário e leiaute de transversal plataforma. Applets também são uma parte integrante do awt.
Hoje foi um grande dia; a lição reconciliou tudo que aprendeu até este ponto sobre a gestão applet simples e acrescentou muito mais sobre criação applets, listas, e componentes de interface do usuário e direção das interações entre todos eles. Com a informação veio hoje e os poucos bits que aprenderá amanhã, pode criar a transversal plataforma aplicações de Java que fazem quase algo que quer.
Eu realmente não gosto de trabalhar com gerentes de leiaute; são demasiado simplistas ou demasiado complicados (leiaute de bolsa de grade). Mesmo com um lote inteiro do conserto, nunca posso conseguir que o meu applets pareça que os quero a. Tudo que quero fazer é definem os tamanhos dos meus componentes e põem-nos em um x e posição y quanto à tela. Posso fazer isto? | |
Vou dizer-lhe como fazer isto, mas não sem uma conferência. As aplicações de Java e o awt projetaram-se tais que a mesma interface de usuário gráfica pode correr igualmente bem em plataformas diferentes e com resoluções diferentes, fontes diferentes, tamanhos de tela diferentes, e assim por diante. A confiança em coordenadas de pixel neste caso é uma ideia realmente má; as variações de uma plataforma ao outro ou até de um ambiente de Java ao outro na mesma plataforma podem estragar o seu leiaute cuidadoso tal que pode ter facilmente sobreposição de componentes ou obscurecer um a outro, as bordas do seu applet cortado, ou outros desastres de leiaute. Tão como um exemplo-I encontrou diferenças significantes no leiaute do mesmo applet que corre no appletviewer do JDK e no Netscape, ambos no Windows 95, ombro a ombro. Pode garantir que o seu applet sempre se dirigirá em precisamente o mesmo ambiente que aquele em que o projetou? Os gerentes de leiaute, colocando dinamicamente elementos na tela, vêm em volta destes problemas. Isto realmente significa que o seu applet pode terminar de parecer não exatamente direito em qualquer plataforma - mas pelo menos é usável em qualquer plataforma. As novas versões do awt prometem oferecer melhor leiaute e controles de desenho de UI. Ainda não convencido? Bem, então. Para fazer um componente um tamanho específico e colocá-lo em uma determinada posição, use um gerente de leiaute nulo e o método de reshape():
setl1ayout (nulo); Pode descobrir mais sobre reshape() na classe de Component. | |
Explorava as classes awt, e vi este subpacote chamado peer. Também há as referências para as classes de par salpicadas em todas as partes da documentação API. O que faz os pares fazem? | |
Os pares são responsáveis pelas partes específicas para a plataforma do awt. Por exemplo, quando cria Java awt janela, tem um exemplo da classe de Window que fornece o comportamento de janela genérico, e logo tem um exemplo de uma classe implementando WindowPeer que cria a janela muito específica daquela janela de motivo de plataforma-a abaixo de X Janela, uma janela de estilo de Macintosh sob o Macintosh ou uma janela do Windows 95 abaixo do Windows 95. Estas classes "de par" também tratam a comunicação entre o sistema de janela e a própria janela Java. Separando o comportamento componente genérico (as classes awt) da implementação de sistema real e aparência (as classes de par), pode concentrar-se em fornecer o comportamento na sua aplicação de Java e deixar a implementação de Java tratar com os detalhes específicos para a plataforma. | |
Há um lote inteiro da funcionalidade no awt sobre que não falou aqui. Porque? | |
Considerando que até uma introdução básica tomou isto muito tempo, compreendi que se instalei em até mais detalhe do que já tenho, este livro iria se transformar Ensinam-se Java durante 21 Dias mais alguns Extra para o Material de awt. | |
Como é, deixei janelas, cardápios e caixas de diálogo até amanhã, portanto terá de esperar por aqueles. Mas pode descobrir sobre muitas outras características de awt simplesmente explorando a documentação API. Comece com a classe de Applet e examine os tipos de métodos que pode chamar. Então olhada em Panel, do qual Applet herda - tem a funcionalidade de toda aquela classe também. A superclasse de Panel é Container, que fornece o detalhe ainda mais interessante. Component vem depois. Explore o API e ver o que pode fazer com ele. Poderia achar algo interessante. | |
Tenho uma nova classe de botão que defini para parecer diferente do padrão awt objetos de botão. Eu gostaria de implementar rechamadas neste botão (isto é, para realizar uma função arbitral quando o botão se aperta), mas não posso compreender como conseguir que Java realize um método arbitral. Em C ++ somente teria um ponteiro para uma função. Em Smalltalk usaria perform:. Como posso fazer isto em Java? | |
Não pode; Java não tem esta facilidade. É por isso que as ações de botão normais se realizam do método de action() genérico em vez de usar um mecanismo para ações anexadas ao próprio botão (que mais se orientaria ao objeto, mais fácil estender-se e não necessitaria um lote inteiro de if...else s dentro de action()). |