41bb726c

Dia 9

Gráfica, fontes e cor

Laura Lemay


CONTEÚDOS

Saber os fundamentos de como o trabalho de applets só é o primeiro passo. O seguinte passo deve ficar familiar com as capacidades que Java lhe dá para desenhar à tela, executando atualização dinâmica, rato gerente e eventos de teclado e criação de elementos de interface de usuário. Fará todas estas coisas nesta semana. Começará hoje com como desenhar à tela - isto é, como produzir linhas e formas com os primitivos de gráficos construídos, como imprimir o texto usando fontes, e como usar e modificar a cor no seu applets. Hoje aprenderá, especificamente, o seguinte:

Observar
Hoje e para o resto desta semana, adquirirá uma introdução para muitas das classes que compõem as bibliotecas de classe de Java, especialmente as classes no pacote de java.awt. Tenha em mente, contudo, que só tenho o espaço para dar-lhe uma introdução para estas classes lá é muitas outras capacidades disponíveis para você nestas classes que pode usar nos seus próprios programas, dependendo do que tenta realizar. Depois que termina este livro (e possivelmente depois de cada uma destas lições), quererá familiarizar-se com as próprias classes e o que podem fazer. Sem falta verifique Java documentação de API de mais detalhes; pode encontrar que documentação API do Web site de Java em http://java.sun.com/products/JDK/1.0.2/api/packages.html.

A classe de Graphics

Com as capacidades de gráficos básicas incorporadas em bibliotecas de classe de Java, pode desenhar linhas, formas, carateres e imagens à tela dentro do seu applet. A maioria das operações de gráficos em Java são métodos definidos na classe de Graphics. Não tem de criar um exemplo de Graphics para desenhar algo no seu applet; no método de paint() do seu applet (sobre o qual aprendeu ontem), dão-lhe um objeto de Graphics. Atraindo aquele objeto, desenha para o seu applet e os resultados aparecem onscreen.

A classe de Graphics é parte do pacote de java.awt, portanto se o seu applet fizer alguma pintura (como normalmente vai), assegurar-se que importa aquela classe no início do seu arquivo de Java:

import java.awt.Graphics;

public class MyClass extends java.applet.Applet {
...
}

O sistema coordenado de gráficos

Para desenhar um objeto na tela, chama um dos métodos de desenho disponível na classe de Graphics. Todos os métodos de desenho têm argumentos que representam endpoints, esquinas ou posições iniciais do objeto como valores no sistema por exemplo coordenado do applet, uma linha começa no ponto 10,10 e termina no ponto 20,20.

O sistema coordenado de Java tem a origem (0,0) na esquina deixada o topo. Os valores de x positivos são aos valores de y direitos e positivos estão abaixo. Todos os valores de pixel são números inteiros; não há pixéis parciais ou fracionários. A figura 9.1 mostra como poderia desenhar um quadrado simples usando este sistema coordenado.

A figura 9.1: A gráfica de Java coordena o sistema.

O sistema coordenado de Java é diferente daquele de muitos pintura e programas de leiaute, que têm o seu x e y no fundo deixado. Se não estiver acostumado a trabalhar com isto o sistema de gráficos de pernas para o ar, pode precisar-se de alguma prática para tornar-se familiar com ele.

Desenho e recheio

A classe de Graphics fornece o grupo de primitivos de gráficos construídos simples para o desenho, inclusive linhas, retângulos, polígonos, ovais e arcos

.

Observar
As imagens de mapa de bits, como arquivos de GIF, também podem desenhar-se usando a classe de Graphics. Aprenderá sobre isto amanhã.

Linhas

Para desenhar linhas diretas, use o método de drawLine(). drawLine() toma quatro argumentos: o x e coordenadas de y do ponto de partida e o x e coordenadas de y do ponto que termina. Deste modo, por exemplo, a seguinte classe de MyLine desenha uma linha do ponto 25,25 ao ponto 75,75. Observe que o método de drawLine() se define na classe de Graphics (como são todos os outros métodos de gráficos aprenderá sobre hoje). Aqui usamos aquele método para o contexto de gráficos atual guardado no g variável:

import java.awt.Graphics;

public class MyLine extends java.applet.Applet {
    public void paint(Graphics g) {
        g.drawLine(25,25,75,75);
    }
}

A figura 9.2 mostra como a classe de MyLine simples olha em um browser permitido por Java como Netscape.

A figura 9.2: Desenho de linhas.

Retângulos

Os primitivos de gráfica de Java provêem não somente um, mas três espécies de retângulos:

Para cada um destes retângulos, tem dois métodos para selecionar: aquele que desenha o retângulo na forma de traçado e aquela que desenha o retângulo enchido da cor.

Para desenhar um retângulo claro, use o drawRect() ou métodos de fillRect(). Ambos tomam quatro argumentos: o x e coordenadas de y da esquina deixada o topo do retângulo, e a largura e altura do retângulo para desenhar. Por exemplo, a seguinte classe (MyRect) desenha dois quadrados: A esquerda cada um é um traçado e o direito enche-se (a Figura 9.3 mostra o resultado):

A figura 9.3: retângulos.

import java.awt.Graphics;

public class MyRect extends java.applet.Applet {
    public void paint(Graphics g) {
        g.drawRect(20,20,60,60);
        g.fillRect(120,20,60,60);
    }
}

Os retângulos arredondados são, como poderia esperar, retângulos com esquinas arredondadas. O drawRoundRect() e os métodos de fillRoundRect() para desenhar retângulos arredondados são semelhantes a retângulos regulares exceto que os retângulos arredondados têm dois extra argumentos pela largura e altura do ângulo das esquinas. Aqueles dois argumentos determinam a que distância ao longo das bordas do retângulo o arco da esquina começará; o primeiro do ângulo ao longo do avião horizontal, o segundo do vertical. Os valores maiores da largura de ângulo e altura fazem o retângulo total mais arredondado; os valores iguais à largura e a altura do próprio retângulo produzem um círculo. A figura 9.4 mostra alguns exemplos de esquinas arredondadas.

A figura 9.4: esquinas arredondadas.

O seguinte é um método de paint() dentro de uma classe chamada MyRRect que desenha dois retângulos arredondados: um como um traçado com uma esquina arredondada quadrado de pixéis de 10; o outro, enchido, com uma esquina arredondada quadrado de pixéis de 20 (a Figura 9.5 mostra os quadrados resultantes):

A figura 9.5: retângulos arredondados.

import java.awt.Graphics;

public class MyRRect extends java.applet.Applet {
    public void paint(Graphics g) {
        g.drawRoundRect(20,20,60,60,10,10);
        g.fillRoundRect(120,20,60,60,20,20);
    }
}

Finalmente, há retângulos tridimensionais. Estes retângulos não são realmente 3D; em vez disso, têm um efeito de sombra leve que os faz parecer levantados ou encomendados da superfície do applet. Os retângulos tridimensionais têm quatro argumentos pelo x e y da posição de partida e a largura e altura do retângulo. O quinto argumento é uma indicação booleana se o efeito 3D é levantar o retângulo (true) ou encomendar ele (false). Como com outros retângulos, também há os métodos diferentes para desenhar e encher-se: draw3DRect() e fill3DRect(). O seguinte é uma classe chamada My3DRect, que produz dois quadrados 3D - a esquerda um levantado, o direito encomendou (a Figura 9.6 mostra o resultado):

A figura 9.6: Três retângulos dimensionais.

import java.awt.Graphics;

public class My3DRect extends java.applet.Applet {
    public void paint(Graphics g) {
        g.draw3DRect(20,20,60,60,true);
        g.draw3DRect(120,20,60,60,false);
    }
}

Observar
Os retângulos 3D na Figura 9.6 não parecem muito 3D, não é? Na versão atual do Conjunto de Desenvolvedor de Java, é extremamente difícil ver o efeito 3D sobre retângulos 3D, devido a uma largura de linha muito pequena. Se estiver tendo preocupações com retângulos 3D, isto pode ser porque. Os retângulos do desenho 3D em qualquer cor outra do que preto fazem-nos mais fáceis ver.

Polígonos

Os polígonos são formas com um número ilimitado de lados. Para desenhar um polígono, precisa do grupo de x e coordenadas de y. O polígono então desenha-se como grupo de linhas diretas do primeiro ponto ao segundo, o segundo ao terceiro, e assim por diante.

Como com retângulos, pode desenhar um traçado ou um polígono enchido (usando o drawPolygon() e métodos de fillPolygon(), respectivamente). Também tem uma escolha de como quer indicar a lista de coordenadas - como as tabelas do x e coordenadas de y ou como um exemplo da classe de Polygon.

Usando o primeiro modo de desenhar polígonos, o drawPolygon() e os métodos de fillPolygon() tomam três argumentos:

O x e as tabelas de y devem ter, naturalmente, o mesmo número de elementos.

Aqui está um exemplo de desenhar o traçado de um polígono usando este método (a Figura 9.7 mostra o resultado):

A figura 9.7: Um polígono.

import java.awt.Graphics;

public class MyPoly extends java.applet.Applet {
    public void paint(Graphics g) {
        int exes[] = { 39,94,97,142,53,58,26 };
        int whys[] = { 33,74,36,70,108,80,106 };
        int pts = exes.length;

        g.drawPolygon(exes,whys,pts);
    }
}

Observe que Java não fecha automaticamente o polígono; se quiser concluir a forma, tem de incluir o ponto de partida do polígono no fim da tabela. Desenhar um polígono enchido, contudo, junta o começo e fim de pontos.

O segundo modo de chamar drawPolygon() e fillPolygon() é usar um objeto de Polygon de guardar os pontos individuais do polígono. A classe de Polygon é útil se pretender acrescentar pontos ao polígono ou se estiver construindo o polígono durante o voo. Usando a classe de Polygon, pode tratar o polígono como um objeto em vez de ter necessidade de tratar com tabelas individuais.

Para criar um objeto de polígono, pode criar primeiro um polígono vazio:

Polygon poly = new Polygon();

ou crie um polígono do grupo de pontos usando tabelas de número inteiro, como no exemplo prévio:

int exes[] = { 39,94,97,142,53,58,26 };
int whys[] = { 33,74,36,70,108,80,106 };
int pts = exes.length;
Polygon poly = new Polygon(exes,whys,pts);

Uma vez que tem um objeto de polígono, pode acrescentar pontos ao polígono como precisa:

poly.addPoint(20,35);

Então, para desenhar o polígono, somente use o objeto de polígono como um argumento a drawPolygon() ou fillPolygon(). Aqui está que o exemplo prévio, reescrito esta vez com um Polygon objeta. Também encherá este polígono em vez de desenhar somente o seu traçado (a Figura 9.8 mostra a produção):

A figura 9.8: Outro polígono.

import java.awt.Graphics;

public class MyPoly2 extends java.applet.Applet {
    public void paint(Graphics g) {
        int exes[] = { 39,94,97,142,53,58,26 };
        int whys[] = { 33,74,36,70,108,80,106 };
        int pts = exes.length;
        Polygon poly = new Polygon(exes,whys,pts);
        g.fillPolygon(poly);
    }
}

Ovais

Usa ovais para desenhar elipses ou círculos. Os ovais são como retângulos com esquinas demais arredondadas. Desenha-os usando quatro argumentos: o x e y da esquina superior, e a largura e altura do próprio oval. Observe que porque desenha um oval, o ponto de partida é alguma distância à esquerda e do traçado real do próprio oval. Novamente, se pensa nele como um retângulo, é mais fácil colocar.

Como com outras operações de desenho, o método de drawOval() desenha um traçado de um oval, e o método de fillOval() desenha um oval enchido.

O seguinte exemplo desenha dois círculo de ovais-a e uma elipse (demonstrações da Figura 9.9 como estes dois ovais aparecem onscreen):

A figura 9.9: ovais.

import java.awt.Graphics;

public class MyOval extends java.applet.Applet {
    public void paint(Graphics g) {
        g.drawOval(20,20,60,60);
        g.fillOval(120,20,100,60);
    }
}

Arcos

De todas as formas pode construir métodos de utilização na classe de Graphics, os arcos são os mais complexos para construir, que é porque os salvei para o último. Um arco é uma parte de um oval; de fato, o modo mais fácil de pensar em um arco é como uma seção de um oval completo. A figura 9.10 mostra alguns arcos.

A figura 9.10: arcos.

O método de drawArc() toma seis argumentos: a esquina inicial, a largura e altura, o ângulo no qual começar o arco e os graus para desenhá-lo antes da paragem. Mais uma vez, há um método de drawArc para desenhar o traçado do arco e o método de fillArc() para encher o arco. Os arcos enchidos desenham-se como se fossem as seções da torta; em vez de juntar os dois endpoints, ambos endpoints juntam-se ao centro do círculo.

A coisa importante a entender sobre arcos consiste em que formula de fato o arco como um oval e logo desenhando só um pouco disto. A esquina inicial e a largura e a altura não são o ponto de partida e largura e altura do arco real como atraído a tela; são a largura e a altura da elipse cheia da qual o arco é uma parte. Aqueles primeiros pontos determinam o tamanho e a forma do arco; dois argumentos últimos (para os graus) determinam o começo e fim de pontos.

Vamos começar com um arco simples, uma forma de C em um círculo, como mostrado na Figura 9.11.

A figura 9.11: Um arco de C.

Para construir o método para desenhar este arco, a primeira coisa que faz é pensam nele como um círculo completo. Então encontra o x e coordenadas de y e a largura e altura daquele círculo. Aqueles quatro valores são quatro primeiros argumentos a métodos de fillArc() ou o drawArc(). A figura 9.12 mostra como adquirir aqueles valores do arco.

A figura 9.12: Construção de um arco circular.

Para adquirir dois argumentos últimos, pense em graus no círculo, indo em sentido inverso ao movimento dos ponteiros do relógio. Os graus nulos são às 3, 90 graus é às 12, 180 às 9, e 270 às 6. A partida do arco é o valor de grau da partida do arco. Neste exemplo, o ponto de partida é o topo do C em 90 graus; 90 é o quinto argumento.

O argumento sexto e último é outro valor de grau que indica a que distância em volta do círculo para varrer e a direção para entrar (não é o ângulo de grau que termina, como poderia pensar). Neste caso, porque vai a meio caminho em volta do círculo, varre 180 graus - e 180, por isso, é o argumento último no arco. A parte importante é que varre 180 graus em sentido inverso ao movimento dos ponteiros do relógio, que está na direção positiva em Java. Se for desenho a para trás C, varre 180 graus na direção negativa, e o argumento último é -180. Ver a Figura 9.13 da ilustração final de como isto trabalha.

A figura 9.13: Arcos em círculos.

Observar
Não importa com que lado do arco começa. Como a forma do arco já se determinou pelo oval completo é uma seção de, começando em qualquer que endpoint trabalhará.

Aqui está o código deste exemplo; desenhará um traçado do C e um C enchido à sua direita, como mostrado na Figura 9.14:

A figura 9.14: Dois arcos circulares.

import java.awt.Graphics;

public class MyOval extends java.applet.Applet {
    public void paint(Graphics g) {
        g.drawArc(20,20,60,60,90,180);
        g.fillArc(120,20,60,60,90,180);
    }
}

Os círculos são um modo fácil de visualizar arcos em círculos; os arcos em elipses são ligeiramente mais difíceis. Vamos por meio deste mesmo processo para desenhar o arco mostrado na Figura 9.15.

A figura 9.15: Um arco elíptico.

Como o arco no círculo, este arco é uma parte de um oval completo, neste caso, oval elíptico. Concluindo o oval de que este arco é uma parte, pode adquirir os pontos de partida e os argumentos de altura e largura pelo drawArc() ou método de fillArc() (ver a Figura 9.16).

A figura 9.16: Arcos em elipses.

Então tudo do qual precisa deve compreender o ângulo inicial e o ângulo para varrer. Este arco não começa em um limite bonito como 90 ou 180 graus, portanto precisará de alguma prova e erro. Este arco começa em algum lugar aproximadamente 25 graus, e logo varre no sentido do movimento dos ponteiros do relógio aproximadamente 130 graus (ver a Figura 9.17).

A figura 9.17: Começo e fim de pontos.

Com todas as porções do arco no lugar, pode escrever o código. Aqui está o código de Java deste arco, tanto desenhado como enchido (nota no caso enchido como os arcos enchidos se desenham como se fossem seções de torta):

import java.awt.Graphics;

public class MyOval extends java.applet.Applet {
    public void paint(Graphics g) {
        g.drawArc(10,20,150,50,25,-130);
        g.fillArc(10,80,150,50,25,-130);
    }
}

A figura 9.18 mostra dois arcos elípticos.

A figura 9.18: Dois arcos elípticos.

Para resumir, aqui estão os passos para tomar para construir arcos em Java:

  1. Pense no arco como uma fatia de um oval completo.
  2. Construa o oval cheio com o ponto de partida e a largura e altura (muitas vezes ajuda a desenhar o oval cheio na tela para adquirir uma ideia do posicionamento de direito).
  3. Determine o ângulo inicial do começo do arco.
  4. Determine a que distância varrer o arco e em que direção (em sentido inverso ao movimento dos ponteiros do relógio indica valores positivos, no sentido do movimento dos ponteiros do relógio indica negativo).

Um exemplo de gráficos simples

Aqui está um exemplo de um applet que usa muitos dos primitivos de gráficos construídos para desenhar uma forma rudimentar. Neste caso, é uma lâmpada com uma sombra notada (ou uma espécie de cogumelo cubista, dependendo do seu ponto de vista). A listagem 9.1 tem o código completo da lâmpada; a Figura 9.19 mostra o applet resultante.

A figura 9.19: A Lâmpada applet.


A listagem 9.1. A classe de Lamp.

 1: import java.awt.*;
 2:
 3: public class Lamp extends java.applet.Applet {
 4:
 5:    public void paint(Graphics g) {
 6:        // the lamp platform
 7:        g.fillRect(0,250,290,290);
 8:
 9:        // the base of the lamp
10:        g.drawLine(125,250,125,160);
11:        g.drawLine(175,250,175,160);
12:
13:        // the lamp shade, top and bottom edges
14:         g.drawArc(85,157,130,50,-65,312);
15:         g.drawArc(85,87,130,50,62,58);
16:
17:         // lamp shade, sides
18:         g.drawLine(85,177,119,89);
19:         g.drawLine(215,177,181,89);
20:
21:         // dots on the shade
22:         g.fillArc(78,120,40,40,63,-174);
23:         g.fillOval(120,96,40,40);
24:         g.fillArc(173,100,40,40,110,180);
25:    }
26: }

Cópia e clareira

Uma vez que desenhou algumas coisas na tela, pode querer deslocá-los ou compensar o applet inteiro. A classe de Graphics fornece métodos para fazer ambas estas coisas.

O método de copyArea() copia uma área retangular da tela a outra área da tela. copyArea() toma seis argumentos: o x e y da esquina superior do retângulo para copiar, a largura e a altura daquele retângulo e a distância no x e direções de y às quais copiá-lo. Por exemplo, esta linha copia uma área quadrada pixéis de 100 em um lado pixéis de 100 diretamente à sua direita:

g.copyArea(0,0,100,100,100,0);

Para compensar uma área retangular, use o método de clearRect(). clearRect(), que toma os mesmos quatro argumentos que o drawRect() e métodos de fillRect(), enche o retângulo dado da cor de fundo atual do applet (aprenderá como escolher a cor de fundo atual depois hoje).

Para compensar o applet inteiro, pode usar o método de size(), que devolve um objeto de Dimension que representa a largura e a altura do applet. Então pode vir aos valores real de largura e altura usando as variáveis de exemplo de altura e largura:

g.clearRect(0,0,size().width,size().height);

Texto e fontes

Usando a classe de Graphics, também pode imprimir o texto na tela, em conjunto com a classe de Font (e, às vezes, a classe de FontMetrics). A classe de Font representa uma fonte dada - o seu nome, estilo, e o tamanho de ponto - e FontMetrics dá-lhe a informação sobre aquela fonte (por exemplo, a altura real ou a largura de um caráter dado) para que possa expor precisamente o texto no seu applet.

Observe que o texto aqui se desenha à tela uma vez e se destina para ficar lá. Aprenderá sobre a entrada em texto do teclado depois nesta semana.

Criação de objetos de fonte

Para desenhar o texto à tela, primeiro tem de criar um exemplo da classe de Font. Os objetos de fonte representam uma fonte individual - isto é, o seu nome, estilo (corajoso, itálico), e tamanho de ponto. Os nomes de fonte são cadeias que representam a família da fonte, por exemplo, "TimesRoman", "Courier" ou "Helvetica". Os estilos de fonte são constantes definidas pela classe de Font; pode vir-lhes usando variáveis por exemplo de classe, Font.PLAIN, Font.BOLD ou Font.ITALIC. Finalmente, o tamanho de ponto é o tamanho da fonte, como definido pela própria fonte; o tamanho de ponto pode ou pode não ser a altura dos carateres.

Para criar um objeto de fonte individual, use estes três argumentos à classe de Font construtor de new:

Font f = new Font("TimesRoman", Font.BOLD, 24);

Este exemplo cria um objeto de fonte da fonte de TimesRoman BOLD, em pontos de 24. Observe que como a maior parte de classes de Java, tem de importar a classe de java.awt.Font antes que possa usá-la.

Ponta
Os estilos de fonte são de fato constantes de número inteiro que podem acrescentar-se para criar estilos combinados; por exemplo, Font.BOLD + Font.ITALIC produz uma fonte que é tanto corajosa como itálica.

As fontes que tem disponível para você no seu applets dependem no qual as fontes se instalam no sistema onde o applet corre. Se escolher uma fonte do seu applet e aquela fonte não está disponível no sistema atual, Java substituirá uma fonte à revelia (normalmente Mensageiro). Pode adquirir uma tabela dos nomes das fontes atuais disponíveis no sistema usando este bit do código:

String[] fontslist = this.getToolkit().getFontList();

Desta lista, então muitas vezes pode decidir inteligentemente que fontes quer usar no seu applet. Para os melhores resultados, contudo, é uma boa ideia de picar com fontes padrão como "TimesRoman", "Helvetica" e "Courier".

Desenho de carateres e cadeias

Com um objeto de fonte na mão, pode desenhar o texto na tela usando os métodos drawChars() e drawString(). Primeiro, entretanto, tem de estabelecer a fonte atual no seu objeto de fonte usando o método de setFont().

A fonte atual é parte do estado de gráficos que se guarda pela pista de pelo objeto de Graphics no qual desenha. Cada vez quando desenha um caráter ou uma cadeia à tela, Java desenha aquele texto na fonte atual. Para modificar a fonte do texto, por isso, primeiro modificam a fonte atual. O seguinte método de paint() cria uma nova fonte, estabelece a fonte atual naquela fonte e desenha a cadeia "This is a big font.", no ponto 10,100:

public void paint(Graphics g) {
    Font f = new Font("TimesRoman", Font.PLAIN, 72);
    g.setFont(f);
    g.drawString("This is a big font.", 10, 100);
}

Isto deve parecer tudo familiar para você; isto é como o Hello World e Hello Again applets em todas as partes deste livro se produziram.

Dois últimos argumentos a drawString() determinam o ponto onde a cadeia começará. O valor de x é a partida da borda mais à esquerda do texto; y é a base da cadeia inteira.

Semelhante a drawString() é o método de drawChars() que, em vez de tomar uma cadeia como um argumento, toma uma tabela de carateres. drawChars() tem cinco argumentos: a tabela de carateres, um número inteiro que representa o primeiro caráter na tabela a desenhar, outro número inteiro do caráter último na tabela a desenhar (todos os carateres entre em conjunto se desenham), e o x e y do ponto de partida. A maior parte do tempo, drawString() é mais útil do que drawChars().

A listagem 9.2 mostra um applet que desenha várias linhas do texto em fontes diferentes; a Figura 9.20 mostra o resultado.

A figura 9.20: A produção do ManyFonts applet.


A listagem 9.2. Muitas fontes diferentes.
 1: import java.awt.Font;
 2: import java.awt.Graphics;
 3:
 4: public class ManyFonts extends java.applet.Applet {
 5:
 6:    public void paint(Graphics g) {
 7:        Font f = new Font("TimesRoman", Font.PLAIN, 18);
 8:        Font fb = new Font("TimesRoman", Font.BOLD, 18);
 9:        Font fi = new Font("TimesRoman", Font.ITALIC, 18);
10:        Font fbi = new Font("TimesRoman", Font.BOLD + Font.ITALIC, 18);
11:
12:        g.setFont(f);
13:        g.drawString("This is a plain font", 10, 25);
14:        g.setFont(fb);
15:        g.drawString("This is a bold font", 10, 50);
16:        g.setFont(fi);
17:        g.drawString("This is an italic font", 10, 75);
18:        g.setFont(fbi);
19:        g.drawString("This is a bold italic font", 10, 100);
20:    }
21:
22: }

Descobrir informação sobre uma fonte

Às vezes pode querer tomar decisões no seu programa Java baseado nas qualidades da fonte por exemplo atual, o seu tamanho de ponto e a altura total dos seus carateres. Pode descobrir um pouco de informação básica sobre fontes e objetos de fonte usando métodos simples em Graphics e nos objetos de Font. A tabela 9.1 mostra alguns destes métodos.

A tabela 9.1. Métodos de fonte.

Nome de métodoEm objeto Ação
getFont() Graphics Devolve o objeto de fonte atual como anteriormente estabelecido por setFont()
getName() Font Devolve o nome da fonte como uma cadeia
getSize() Font Devolve o tamanho de fonte atual (um número inteiro)
getStyle() Font Devolve o estilo atual da fonte (os estilos são constantes de número inteiro: 0 é claro, 1 é corajoso, 2 é itálico, 3 é negrito itálico)
isPlain() Font true de regressos ou false se o estilo da fonte é claro
isBold() Font true de regressos ou false se o estilo da fonte é corajoso
isItalic() Font true de regressos ou false se o estilo da fonte é itálico

Para a informação mais detalhada sobre as qualidades da fonte atual (por exemplo, o comprimento ou a altura de carateres dados), tem de trabalhar com a métrica de fonte. A classe de FontMetrics descreve a informação específica para uma fonte dada: o principal entre linhas, a altura e largura de cada caráter, e assim por diante. Para trabalhar com estes tipos de valores, cria um objeto de FontMetrics baseado na fonte atual usando o método applet getFontMetrics():

Font f = new Font("TimesRoman", Font.BOLD, 36);
FontMetrics fmetrics = getFontMetrics(f);
g.setfont(f);

A tabela 9.2 mostra algumas coisas pode descobrir a métrica de fonte de utilização. Todos estes métodos devem chamar-se em um objeto de FontMetrics.

A tabela 9.2. Métodos de métrica de fonte.

Nome de métodoAção
stringWidth(string) Considerando uma cadeia, devolve a largura cheia daquela cadeia, em pixéis
charWidth(char) Considerando um caráter, devolve a largura daquele caráter
getAscent() Devolve a subida da fonte, isto é, a distância entre a base da fonte e o topo dos carateres
getDescent() Devolve a descida da fonte - isto é, a distância entre a base da fonte e os fundos dos carateres (para carateres como p e q que caem em baixo da base)
getLeading() Devolve o principal da fonte, isto é, o espaçamento entre a descida de uma linha e a subida de outra linha
getHeight() Devolve a altura total da fonte, que é a soma da subida, descida, e conduzindo valor

Como um exemplo dos tipos da informação que pode usar com a métrica de fonte, a Listagem 9.3 mostra o código de Java de um applet que automaticamente centra uma cadeia horizontalmente e verticalmente dentro de um applet. A posição que centra é diferente dependendo do tamanho de fonte e fonte; usando a métrica de fonte para descobrir o tamanho real de uma cadeia, pode desenhar a cadeia no lugar apropriado.

A figura 9.21 mostra o resultado (que é menos interessante que se de fato compilar e experimentar com vário applet e tamanhos de fonte).

A figura 9.21: O texto centrado.


A listagem 9.3. Centrar uma cadeia.
 1: import java.awt.Font;
 2: import java.awt.Graphics;
 3: import java.awt.FontMetrics;
 4:
 5: public class Centered extends java.applet.Applet {
 6:
 7:    public void paint(Graphics g) {
 8:        Font f = new Font("TimesRoman", Font.PLAIN, 36);
 9:        FontMetrics fm = getFontMetrics(f);
10:        g.setFont(f);
11:
12:        String s = "This is how the world ends.";
13:        int xstart = (size().width - fm.stringWidth(s)) / 2;
14:        int ystart = size().height / 2;
15:
16:        g.drawString(s, xstart, ystart);
17:    }
18:}

Análise
Observe o método de size() em linhas 13 e 14, que devolve a largura e altura da área applet total como um objeto de Dimension. Então pode vir à largura individual e altura usando o width e variáveis de exemplo de height de que Dimension, aqui encadeando o método chama e o nome da variável. Adquirir a corrente applet tamanho deste modo é uma melhor ideia do que a codificação difícil do tamanho do applet no seu código; este código trabalha igualmente bem com um applet de qualquer tamanho.

Também observe que a linha do texto, como mostrado na Figura 9.21, não se centra precisamente verticalmente na caixa delimitadora applet. Este exemplo centra a base do texto dentro do applet; usando o getAscent() e métodos de getDescent() da classe de FontMetrics (para adquirir o número de pixéis da base ao topo dos carateres e o número de pixéis da base ao fundo dos carateres), pode compreender exatamente o meio da linha do texto.

Cor

Desenhar manchas negras e texto em um contexto cinza é tudo muito bonito, mas ser capaz de usar cores diferentes é muito mais bonito. Java fornece métodos e comportamentos para tratar com a cor em geral pela classe de Color, e também fornece métodos para estabelecer o primeiro plano atual e cores de fundo para que possa desenhar das cores que criou.

O modelo a cores abstrato de Java usa a cor de 24 bits, em que uma cor se representa como uma combinação de valores vermelhos, verdes, e azuis. Cada componente da cor pode ter um número entre 0 e 255. 0,0,0 é preto, 255,255,255 é branco, e Java pode representar milhões de cores entre também.

Os mapas modelares a cores abstratos de Java para o modelo a cores da plataforma Java continua, que normalmente tem só 256 ou menos cores que selecionar. Se uma cor solicitada em um objeto a cores não estiver disponível para a exposição, a cor resultante pode fazer-se o mapa ao outro ou tremeu, dependendo de como o browser que examina a cor o implementou, e dependendo da plataforma na qual corre. Em outras palavras, embora Java dê a capacidade de milhões gerentes de cores, muito poucos podem estar de fato disponíveis para você na vida real.

Utilização de objetos a cores

Para desenhar um objeto em uma determinada cor, deve criar um exemplo da classe de Color para representar aquela cor. A classe de Color define o grupo de objetos a cores padrão, guardados em variáveis de classe, para adquirir rapidamente um objeto a cores de algumas cores mais populares. Por exemplo, Color.red devolve um objeto de Color que representa vermelho (os valores de RGB do 255, 0 e 0), Color.white devolve uma cor branca (os valores de RGB do 255, 255 e 255), e assim por diante. A tabela 9.3 mostra as cores padrão definidas por variáveis na classe de Color.

A tabela 9.3. Cores padrão.

Nome a coresValor de RGB
Color.white 255,255,255
Color.black 0,0,0
Color.lightGray 192,192,192
Color.gray 128,128,128
Color.darkGray 64,64,64
Color.red 255,0,0
Color.green 0,255,0
Color.blue 0,0,255
Color.yellow 255,255,0
Color.magenta 255,0,255
Color.cyan 0,255,255
Color.pink 255,175,175
Color.orange 255,200,0

Se a cor na qual quer desenhar não é um dos objetos de Color padrão, medo não. Pode criar um objeto a cores de qualquer combinação de vermelho, verde, e azul, enquanto tem os valores da cor que quer. Somente crie um novo objeto a cores:

Color c = new Color(140,140,140);

Esta linha do código de Java cria um objeto a cores que representa um cinzento escuro. Pode usar qualquer combinação de valores vermelhos, verdes, e azuis para construir um objeto a cores.

Alternativamente, pode criar um objeto a cores usando três bóias de 0.0 a 1.0:

Color c = new Color(0.55,0.55,0.55);

Testar e escolher as cores atuais

Para desenhar um objeto ou texto usando um objeto a cores, tem de escolher a cor atual para ser que o objeto a cores, tão como tem de estabelecer a fonte atual na fonte na qual quer desenhar. Use o método de setColor() (um método de objetos de Graphics) para fazer isto:

g.setColor(Color.green);

Depois de escolher a cor atual, todas as operações de desenho ocorrerão naquela cor.

Além de escolher a cor atual do contexto de gráficos, também pode estabelecer o contexto e cores de primeiro plano do próprio applet usando métodos de setForeground() e o setBackground(). Ambos destes métodos definem-se na classe de java.awt.Component, que Applet - e por isso as suas classes automaticamente herdam.

O método de setBackground() escolhe a cor de fundo do applet, que é normalmente um cinzento claro (para combinar com o contexto à revelia do browser). Toma um argumento único, objeto de Color:

setBackground(Color.white);

O método de setForeground() também toma uma cor única como um argumento, e afeta tudo que se desenhou no applet, apesar da cor na qual se desenhou. Pode usar setForeground() para modificar a cor de tudo no applet ao mesmo tempo, em vez de ter necessidade de desenhar novamente tudo:

setForeground(Color.black);

Além do setColor(), setForeground() e métodos de setBackground(), há métodos de get correspondentes que lhe permitem recuperar a cor de gráficos atual, contexto ou primeiro plano. Aqueles métodos são getColor() (definido em objetos de Graphics), getForeground() (definido em Applet), e getBackground() (também em Applet). Pode usar estes métodos para escolher cores baseadas em cores existentes no applet:

setForeground(g.getColor());

Um exemplo a cores simples

A listagem 9.4 mostra o código de um applet que enche a área de desenho do applet de caixas quadradas, cada uma das quais tem uma cor à toa escolhida nela. Escreve-se para que possa tratar qualquer tamanho de applet e automaticamente encher a área do número direito de caixas.


A listagem 9.4. Caixas a cores casuais.
 1:  import java.awt.Graphics;
 2:  import java.awt.Color;
 3:
 4:  public class ColorBoxes extends java.applet.Applet {
 5:
 6:      public void paint(Graphics g) {
 7:          int rval, gval, bval;
 8:
 9:          for (int j = 30; j < (size().height -25); j += 30)
10:             for (int i = 5; i < (size().width -25); i += 30) {
11:                 rval = (int)Math.floor(Math.random() * 256);
12:                 gval = (int)Math.floor(Math.random() * 256);
13:                 bval = (int)Math.floor(Math.random() * 256);
14:
15:                 g.setColor(new Color(rval,gval,bval));
16:                 g.fillRect(i, j, 25, 25);
17:                 g.setColor(Color.black);
18:                 g.drawRect(i-1, j-1, 25, 25);
19:             }
20:     }
21: }

Análise
Os dois laços de for são o coração deste exemplo; o primeiro desenha as linhas e os segundos sorteios as caixas individuais dentro de cada linha. Quando uma caixa se desenha, a cor casual calcula-se primeiro, e logo a caixa desenha-se. Um traçado preto desenha-se em volta de cada caixa, porque alguns deles tendem a misturar-se no contexto do applet.

Como este método de paint gera novas cores cada vez quando o applet pinta-se, pode regenerar as cores deslocando a janela ou cobrindo a janela do applet do outro (ou recarregando a página). A figura 9.22 mostra o final applet (embora dado que este quadro é preto e branco, não pode adquirir o efeito cheio dos quadrados multicores).

A figura 9.22: As cores casuais applet.

Sumário

Apresenta algo na tela pintando dentro do seu applet: formas, gráfica, texto ou imagens. Hoje aprendeu os fundamentos de como pintar, inclusive como usar os primitivos de gráficos para desenhar formas rudimentares, como usar fontes e métrica de fonte para desenhar o texto, e como usar objetos de Color de modificar a cor do que atrai a tela. É esta fundação na pintura que lhe permite fazer a animação dentro de um applet (que basicamente implica somente a pintura repetidamente à tela) e trabalhar com imagens. Estes são tópicos sobre os quais aprenderá amanhã.

Perguntas e Respostas

Q:
Em todos os exemplos mostra, e em todos os testes fiz, os primitivos de gráficos, como drawLine() e drawRect(), produzem linhas que são um pixel largo. Como posso desenhar linhas mais grossas?
A:
No estado atual da classe de Gráfica de Java, não pode; nenhum método existe para modificar a largura de linha à revelia. Se realmente precisar de uma linha mais grossa, tem de desenhar múltiplas linhas um pixel à parte para produzir aquele efeito.
Q:
Quero desenhar uma linha do texto com uma palavra negrita no meio. Entendo que preciso de dois objetos de fonte um para a fonte regular e um para a corajosa - e que precisarei de reinicializar a fonte atual no meio. O problema consiste em que drawString() necessita um x e uma posição de y da partida de cada cadeia, e não pode encontrar nada que se refere "ao ponto atual". Como posso compreender onde começar a palavra negrita?
A:
As capacidades de exposição de texto de Java são regularmente primitivas. Não há conceito do ponto atual, portanto terá de compreender manualmente onde o fim de uma cadeia foi para que possa começar a seguinte cadeia. Os métodos de stringWidth() podem ajudá-lo com isto, tanto a descobrir a largura da cadeia que somente desenhou como acrescentar o espaço depois dela.
Q:
Como uso fontes não-romanas como kanji em Java?
A:
O suporte de Java de fontes internacionais na 1.0.2 versão do JDK é esboçado, além da codificação dos carateres crus como Unicode. A sua aposta melhor deve esperar pela 1,1 versão do JDK, que oferecerá muito mais flexibilidade no caminho de exposição de caráter de Unicode, suporte da internacionalização e fontes não-romanas.
Q:
Provei o applet que desenha caixas de cores casuais, mas cada vez desenha, muitas caixas são a mesma cor. Se as cores forem realmente casuais, porque faz isto?
A:
Duas razões. O primeiro é que o gerador de números aleatórios que usei naquele código (da classe de Math) não é um gerador de números aleatórios muito bom; de fato, a documentação daquele método diz outro tanto. Para um melhor gerador de números aleatórios, use a classe de Random do pacote de java.util.
 
Os segundos, mais provavelmente, raciocinam é que somente não há bastantes cores disponíveis no seu browser ou no seu sistema para desenhar todas as cores que o applet gera. Se o seu sistema não puder produzir a ampla variação de cores utilização disponível da classe de Color, ou se o browser tenha alocado demasiadas cores de outras coisas, pode terminar de cores duplicadas nas caixas, dependendo de como o browser e o sistema se escreveram para tratar isto. Normalmente o seu applet não usará bastante tantas cores, portanto não baterá neste problema bastante tão muitas vezes.
Q:
Tenho um contexto coberto com telhas na minha Página da Web. Posso criar imagens com contextos transparentes para que o contexto de página coberto com telhas mostre por. Posso criar applets transparente?
A:
Não com os 1.02 JDK (e possivelmente não com 1,1 qualquer). Para applets, a sua aposta melhor deve usar um contexto de cor clara e fazer que o contexto do seu applet seja que a mesma cor.

Outra ideia se usar uma telha para o contexto de página é importar aquela imagem e desenhá-lo como o contexto do seu applet (aprenderá sobre imagens amanhã). Contudo, usando aquele mecanismo, é improvável que as bordas da telha correspondam exatamente. Infelizmente, não parece haver um bom workaround deste problema.