Clique aqui para ler esse artigo em PDF.
Pinte o 7 com Java 2D – Parte 3: Animações e Impressão
public void run() {
while (true) {
this.repaint();
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException ie) { }
if (indice < nomeImagens.length - 1) indice++;
else indice = 0;
}
}
O código de paint() também é simples. Precisamos apenas desenhar a imagem do índice atual do Vector:
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawImage( (Image) imagens.get(indice), null, this );
}
A Figura 1 mostra a seqüência de imagens (em arquivos separados) que será exibida durante a animação. A Figura 2 mostra o JFrame exibindo a animação.
Mais sobre repaint()
Vimos na primeira parte da série como funciona o sistema de renderização do Java 2D, e trabalhamos bastante com o método paint(). Vimos também que este método não é chamado diretamente pela aplicação, mas sim pelo sistema de renderização, quando é necessário redesenhar o componente (por exemplo, quando o frame for redimensionado, maximizado etc.). Sendo assim, como podemos atualizar o frame durante a animação?
Como não é aconselhável chamar o método paint() diretamente – mesmo porque para chamá-lo precisamos ter uma instância do contexto gráfico Graphics – é disponibilizado um método que pode ser invocado pela aplicação, sempre que se deseja diretamente redesenhar um componente. O método repaint() permite que a aplicação chame paint() de forma assíncrona. Internamente, ele solicita ao sistema de renderização que o componente seja redesenhado.
Nem todas as chamadas a repaint() geram necessariamente chamadas a paint(). Por exemplo, se uma segunda chamada chegar antes que paint() tenha sido chamado ainda para uma invocação anterior de repaint(), paint() será chamado apenas uma vez.
Swing, AWT e flicker
O que vimos até aqui se aplica ao redesenho de componentes Swing (pacote javax.swing.*). Os componentes AWT (java.awt.*), entretanto, têm uma característica adicional que precisamos
conhecer. Um método intermediário, update(), é chamado para o desenho de componentes AWT. Chamar o método repaint() em um componente AWT invoca update(), que limpa a área do componente e
em seguida chama paint(). Mas isso pode trazer um efeito indesejado de flicker (“piscado”) na animação, pois cada vez que o quadro é substituído, toda a área do componente é apagada, antes que o novo quadro seja renderizado. Para resolver esse problema, ao utilizar componentes AWT precisamos redefinir o método update(), e chamar paint() diretamente.
Veja na Listagem 2 o código de Panel
AnimacaoAWT, utilizado para renderizar a animação. Ele é semelhante ao exemplo anterior; o que muda basicamente é a superclasse, que é java.awt.Panel (no exemplo anterior usamos javax.swing.JPanel). Note também que redefinimos o método update(), como recomendado. Experimente comentar esse método para verificar o efeito de flicker resultante.
Mais controle na animação
Vejamos agora um exemplo mais
elaborado de animação. Nele, teremos a opção de parar e reiniciar a animação, além de controlar o delay (tempo entre a mudança de quadros). Outro diferencial é que as imagens serão carregadas de
um arquivo único com várias imagens, como em um filme. Veja na Figura 3 a seqüência de imagens utilizada; as imagens são carregadas no construtor da classe,
como a seguir:
for (int i = 0; i < NUMERO_FRAMES; i++) {
BufferedImage bi = new BufferedImage(
larguraImagem, alturaImagem,
BufferedImage.TYPE_3BYTE_BGR
);
bi.createGraphics().drawImage(
sequenciaImagens, 0, 0, larguraImagem,"
[...] continue lendo...