JFrame com imagem em Fade

22 respostas
M

Boa tarde companheiros,

Gostaria de saber se existe um modo simples de criar o efeito Fade em uma imagem(.GIF) em um JLabel. Fade é aquele efeito que a imagem some ou aparece lentamente até torna-se nitido ou invisível.

Arigato Gosaimasu :smiley:

22 Respostas

M

Se alguém também tiver resposta pra fazer isso com outras imagens sem ser necessariamente JLabel também agradeço xD

V

Por favor, evite ficar ressuscitando tópicos antigos.

Respondendo a questão desse tópico, você faz isso no Java com Java2D e a classe AlphaComposite.

M

Opa… Malz xD

E como se usa AlphaComposite? Eu to tentando usar, mas ta dificil de entender .-.

V

Primeiro dê uma lida nos artigos do outro tópico, para entender como funciona o objeto Graphics2D e o java 2D.
Mas basicamente basta definir o tipo de composição que você quer, e depois desenhar a imagem.

Para transparência, use:

Em transparency, passe um valor entre 0 e 1, onde 0 é totalmente opaco e 1 totalmente transparente.

M
ViniGodoy:
Primeiro dê uma lida nos artigos do outro tópico, para entender como funciona o objeto Graphics2D e o java 2D. Mas basicamente basta definir o tipo de composição que você quer, e depois desenhar a imagem. Para transparência, use:
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, transparency));

Em transparency, passe um valor entre 0 e 1, onde 0 é totalmente opaco e 1 totalmente transparente.

Os parâmetros da transparencia (0 a 1, tipo float) eu já saquei...mas não sei como usar, também já li um pouco de java2d e Graphics2d mas não sei direito como usar...tem até uma classe que eu tinha pegado aqui no GUJ pra tentar entender:

package teste;

import java.awt.*;
import javax.swing.*;

public class Transparencia extends JPanel {

   private Image img;

   public Transparencia() {
   }

   @Override
   protected void paintComponent(Graphics g) {

      Graphics2D g2 = (Graphics2D) g.create(); 

      int x = 1; 
      int y = 1;

      int w = this.getWidth() - 2; 
      int h = this.getHeight() - 2; 

      int inc = 50; 
      float alpha = 1.0f; 
      float dec = 0.28f; 

      AlphaComposite comp = AlphaComposite.SrcOver.derive(alpha); 
      g2.setComposite(comp); 


      System.out.println("bounds: " + x + ", " + y 
              + ", " + (w - x) + ", " + (h - y));
      System.out.println("alpha : " + alpha); 

      g2.drawImage(img, x, y, w - x, h - y, null);

      x += inc;
      y += inc;

      if (x > (w - inc)) {
         x = w - inc;
      }
      if (y > (h - inc)) {
         y = h - inc; 
      }

      alpha -= dec; 

      if (alpha < 0) {
         alpha = 0; 
      }
      g2.setComposite(comp.derive(alpha)); 


      g2.dispose();


   }

   public static void loadImages(CompositePanel cp) {
      
      Toolkit tk = Toolkit.getDefaultToolkit(); /
      String base = "/home/melissa/Imagens/xD/imagem"; 
      String ext = ".jpg";
      MediaTracker mt = new MediaTracker(cp); 

      for (int i = 0; i < 4; i++) {
         Image im = tk.createImage(base + i + ext); 
         mt.addImage(im, i);
         System.out.println(base + i + ext); 
         cp.getImagesList().add(im); 
      }//for

      try {

         mt.waitForAll(); 

      } catch (Exception ex) {
         ex.printStackTrace();
      }//try

   }//loadImages()

   public static void main(String[] args) {
      JFrame f = new JFrame("Transparencia"); 
      f.setBounds(200, 200, 307, 332); 
      f.setLayout(null); 
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

      CompositePanel cp = new CompositePanel(); 
      loadImages(cp); 
      cp.setBounds(2, 2, 695, 695); 
      cp.setBorder(BorderFactory.createLineBorder(Color.BLUE)); 

      f.add(cp); 
      f.setVisible(true); 
   }//main()
}//class

Mas como ela refaz um método do JPanel, eu não consegui exatamente usar pra fazer um método comum, e nem entender a parte do Alpha

V

Vou elaborar um exemplo para você.

PS: Carregar imagens com o MediaTracker é um tanto arcaico. Já deu uma olhada na classe ImageIO?

M

Brigadão! ^^"

PSresp: hauhuahuahauhauahauhauhau o meu “professor” (Ele tb não sabe alpha composite, infelizmente :frowning: ) aqui do trabalho me ensinou o ImageIO já…mas como eu disse, a classe não é minha xD

V

Bom, aqui está um exemplo:

package demo;

import java.awt.AlphaComposite;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class ExemploAlphaComposite extends JFrame {
	private BufferedImage img1;
	private BufferedImage img2;
	
	private volatile float alpha = 1.0f;
	private float add = -0.02f;
	
	private BufferedImage carregarImagem(String image)
	{
		try {
			//Carrega a imagem do disco
			BufferedImage img = ImageIO.read(getClass().getResource(image));
			
			//Converte ela para o formato da tela. Isso aumenta muito as chances do seu desenho ser acelerado por hardware.
			//O processo de coversão é simples. Simplesmente criamos uma imagem com a configuração da tela, e desenhamos
			//a imagem carrega sobre esta.
			//Também já farei aqui o redimensionamento para o tamanho da tela, evitando gastar tempo com isso na hora de 
			//desenhar na tela.
			BufferedImage imagem = GraphicsEnvironment
				.getLocalGraphicsEnvironment()
				.getDefaultScreenDevice()
				.getDefaultConfiguration()
				.createCompatibleImage(getWidth(), getHeight(), Transparency.TRANSLUCENT);
			
			Graphics2D g2d = imagem.createGraphics();
			g2d.drawImage(img, 0, 0, imagem.getWidth(), imagem.getHeight(), 0, 0, img.getWidth(), img.getHeight(), null);
			g2d.dispose();
			
			//Retornamos a imagem redimensionada e otimizada
			return imagem;
		} catch (IOException e) {
			throw new RuntimeException("Não foi possível carregar a imagem");
		}
	}
	
	public ExemploAlphaComposite()
	{
		super("Exemplo de alpha composite");
		setSize(800, 600);
		setResizable(false);
		setLocationRelativeTo(null);
		setIgnoreRepaint(true);
		img1 = carregarImagem("/demo/imagens/mario.jpg");
		img2 = carregarImagem("/demo/imagens/sonic.jpg");
		setVisible(true);
		
		//Iniciamos a thread que fará a imagem se repintar várias vezes
		//Isso dá o efeito de animação.
		Thread t = new Thread(new DemoThread(), "Thread de demonstração");
		t.setDaemon(true);
		t.start();
	}
	
	@Override
	public void paint(Graphics g) {		
		BufferedImage buffer = new BufferedImage(img1.getWidth(), img1.getHeight(), BufferedImage.TYPE_INT_ARGB);
		Graphics2D g2d = buffer.createGraphics();
		//Desenhamos a imagem 1
		g2d.drawImage(img1, 0, 0, null);
						
		//Nesta linha, alteramos a transparência de tudo que será desenhado 
		//sobre o graphics.		
		g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));		
		//E então desenhamos a imagem 2, sobre a imagem 1. 
		g2d.drawImage(img2, 0,0, null);
		
		//Variamos o alpha
		alpha += add;
		
		if (alpha &lt; 0.02) {
			add = 0.02f;
		} else if (alpha &gt; 0.98) {
			add = -0.02f;
		}
			
		g2d.dispose();
		g.drawImage(buffer, 0,0,null);
	}
	
	public class DemoThread implements Runnable {
		@Override
		public void run() {
			try {
				//Para fazer a animação, simplesmente chamamos o repaint várias vezes
				//Essa é uma forma bem rudimentar de animar. O Ponto V! descreve mecanismos 
				//melhores.
				while (true) {					
					repaint();
					Thread.sleep(1000 / 15); //15 fps
				}
			} catch (InterruptedException e) {				
			}
		}
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				new ExemploAlphaComposite().setVisible(true);
			}
		});
	}
}

Ele varia duas imagens, gradualmente, na tela.
Como sou fã de jogos, escolhi dois clássicos: Uma do Mário, outra do Sonic.

Aproveitei aqui e também demonstrei como carregar as imagens de modo a otimizar o processo de pintura.

Em anexo, está o .jar com o programa compilado e funcionando.
Usei um controle rudimentar de loop, então não estranhe se a tela piscar um pouco.

M

Opa! Valeu, Vini! ^^"

Vou dar uma olhada e ver se consigo fazer/entender/aprender xD

PS: Esse método paint() é @Override… não tem como ele fazer isso sem ter que reescrever nada? Como um método comum?

V

Não.
Só é possível usar o java 2D sobrescrevendo o método paint de um JFrame, ou o paintComponent de um JComponent. E como vc quer fazer animado, precisa chamar repaint várias vezes, para que esse método seja chamado várias vezes.

Quer dizer, até existe outra forma, que é usando o BufferStrategy do JFrame, mas ainda é bem longe de só definir uma propriedade como setEffect(Effects.FADE_OUT), e também vai exigir uma outra thread em loop.

M

E da pra usar esse @Override em um JXImagePanel? Pq pelo que eu entendi ele vai chamar o repaint() pro frame inteiro, e ficaria melhor se ele chamasse só pro JXImagePanel não?

V

Dá sim.

O @Override é só para indicar que eu estou sobrescrevendo o método paint da classe JFrame (que é pai do exemplo que te passei).

Você pode fazer o mesmo para o método paintComponent do JXImagePanel.

Isso é usado para evitar erros de digitação. Se vc escrever “paintConponent”, por exemplo, ele dá erro dizendo que o método não existe na classe pai, ao invés de simplesmente achar que esse é outro método e não funcionar.

M

Legal ^^

Vou tentar fazer o @Override pro JXImagePanel aqui…

Obrigada, Vini! :smiley:

V

O ideal seria evitar esse pisca-pisca (aqui no meu trabalho ficou realmente horrível).
Provavelmente para isso tem que usar double-buffering, coisa que vc vai ter que fazer se quiser ter uma aparência garantida e profissional. Mas isso o seu professor aí já deve saber fazer.

M

Eu troquei o @Override pro JXImagePanel (e adicionei a um JFrame) do jeito que eu falei e ele já parou de piscar, ficou bonitinho as imagens mudando ^^

Agora só preciso descobrir como fazer elas mudarem do jeito certo… xD (aparece, fica, desaparece, e assim vai xD)

M

Tem como fazer a Thread parar no meio e depois continuar de onde parou? o.O (isso é meio off-topic né? =x)

V

Não tente fazer isso mexendo na Thread…

Basta criar uma variavel algumas variáveis de controle no próprio código que te enviei:

bool parado; double tempoQueDeveFicarParado; double tempoParado;

E controlar isso toda vez que o add “vira”.

M

Ops… =X sério? Eu mexi na thread e não deu problema… Ele mudou certinho…

Aparece, Aguarda alguns segundos, some enquanto a outra aparece, desaparece…etc

Só deu problema quando eu fui tentar mudar pra ele fazer com mais de uma imagem… Pq ao invés de mudar direto, ele faz aparecer a imagem 1, dai começa a transição pra 2, pisca a 3, e termina a transição (algo assim, tá meio confuso… o.O), mas a thread em si não deu problema. o.o

V

Bom, ok. Acho que o tema está resolvido, não?
Agora é se quebrar para arrumar os detalhes.

Se alguma coisa pegar novamente, é só entrar em contato. :slight_smile:

M

Esse sim! XD

Obrigada pela ajuda, Vini! ^^"

Posso te pedir ajuda de novo? >.o (Fiz outro tópico já que são coisas relativamente diferentes…)

V

Ressuscitei o tópico para avisar que atualizei o exemplo da página 1, incluindo agora um buffer para as imagens:
http://www.guj.com.br/java/128713-jframe-com-imagem-em-fade#1165351

Isso deve evitar o flickering que o programa estava tendo. :slight_smile:

J

Olá Professor,

Muito Boa Tarde meu amigo!

É um grande prazer poder participar deste forum tendo o senhor como colaborador, meu mestre!

Preciso de sua ajuda, sou novato em Programação Utilizando Java, eu utilizei o seu exemplo (perfeito e fantástico) “AlphaComposite”, entretanto, gostaria de poder usá-lo em uma combinação de abertura de um JFrame que ao invés de monstrar uma imagem (alternando-as), inicialmente gostaria de apresentar o Próprio formulário. Deixa-me ver se consigo ser mais claro:

Queria que ao abrir um formulário (JFrame), ele fosse inicialmente posicionado ao centro da tela e quase que transparente e bem pequeno (32 x 32), depois utilizando o efeito do seu exemplo, gostaria de ir deixando-o mais aparente e ao mesmo tempo ir aumentando o seu tamanho, até que chegasse ao tamanho final (original) e com 100% de visibilidade (Removendo completamente o Efeito Alpha).

Bom acho que consegui passar para o senhor meu amigo o que eu estou pretendendo fazer…

Agradeço imensamente sua preciosa atenção e se possível, peço por gentileza um exemplo prático de como construir essa classe para utilizar este efeito.

Um forte abraço e Fique com Deus!

Criado 3 de junho de 2009
Ultima resposta 28 de mai. de 2013
Respostas 22
Participantes 4