GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

JFrame com imagem em Fade

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:

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

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.

Opa… Malz xD

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

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.

[quote=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:

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

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:

[code]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[/code]

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

Vou elaborar um exemplo para você.

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

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

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(&quot;serial&quot;)
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(&quot;Não foi possível carregar a imagem&quot;);
		}
	}
	
	public ExemploAlphaComposite()
	{
		super(&quot;Exemplo de alpha composite&quot;);
		setSize(800, 600);
		setResizable(false);
		setLocationRelativeTo(null);
		setIgnoreRepaint(true);
		img1 = carregarImagem(&quot;/demo/imagens/mario.jpg&quot;);
		img2 = carregarImagem(&quot;/demo/imagens/sonic.jpg&quot;);
		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(), &quot;Thread de demonstração&quot;);
		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.

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?

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.

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?

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.

Legal ^^

Vou tentar fazer o @Override pro JXImagePanel aqui…

Obrigada, Vini! :smiley:

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.

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)

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

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”.

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

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:

//