java - 如何在JPanel中让3张图片淡入淡出?

标签 java swing jpanel fade

我的问题是如何使第一张图像消失,然后第二张图像消失,然后第三张图像出现。我尝试到处改变,但没有任何效果。一切立刻就出来了。有人可以告诉我我应该改变哪一部分吗?

  import java.awt.AlphaComposite;
  import java.awt.Graphics;
  import java.awt.Graphics2D;
  import java.awt.Image;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import javax.swing.ImageIcon;
  import javax.swing.JFrame;
  import javax.swing.JPanel;
  import javax.swing.Timer;

  public class FadeOutImage2 extends JPanel implements ActionListener{

  Image myImage = new ImageIcon("C:\\Users\\NUR\\Pictures\\FLOWER1.jpg").getImage();
  Image myImage2 = new ImageIcon("C:\\Users\\NUR\\Pictures\\FLOWER2.jpg").getImage();
  Image myImage3 = new ImageIcon("C:\\Users\\NUR\\Pictures\\FLOWER3.jpg").getImage();

  Timer timer = new Timer (50, this); //setting time to fade
  private float alpha = 1f; //alpha value on channel

  public FadeOutImage2(){
     timer.start();
  }

  public void paint(Graphics g){
     super.paint(g);

     Graphics2D g2d = (Graphics2D)g;
     Graphics2D g2d2 = (Graphics2D)g;
     Graphics2D g2d3 = (Graphics2D)g;


g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,alpha));  
g2d2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,alpha));
g2d3.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,alpha));

g2d.drawImage(myImage, 10,10, null); //coordinate
g2d2.drawImage(myImage2, 10,10, null);
g2d3.drawImage(myImage3, 10,10, null);
   }

  public void actionPerformed(ActionEvent e){
      alpha += -0.01f;
      if(alpha<=0){
         alpha=0;
         timer.stop();}

      repaint();
  }

public static void main(String[] args){
     JFrame frame = new JFrame("Fade Out");
     frame.add(new FadeOutImage2());

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     frame.setSize(1500,1500);
     frame.setVisible(true);
 }
 }

最佳答案

理论...

好的,根据您的要求,我的第一个建议是专注于单个图像的淡入和淡出。如果您能理解如何做到这一点,那么将三个图像淡入淡出(一个接一个)就会简单得多。

动画是随时间变化的幻觉。因此,您首先需要以某种方式更改 alpha 的状态经过一段时间。由于 Swing 既是单线程的又不是线程安全的,因此您只有一个基本选择:Swing Timer .

这会定期生成更新,这些更新是在事件调度线程的上下文中触发的,从而可以安全地与 Swing 一起使用并从内部更新 UI。

由于硬件(和操作系统)的差异,我会避免固定速率衰减(也就是说,您将固定的 delta 应用于 alpha 并重复直到达到 target )。这种方法可能会在不同的系统上产生不良结果。

根据我的经验,基于时间的解决方案通常会产生更一致的结果。基于时间的方法规定动画将在 Timer 的每个刻度上运行指定的时间段。 ,我们计算进度量并将其应用于我们的状态(我们知道我们需要从 0-1 来淡入图像,因此很容易根据进度计算状态)

基础实现...

这一切听起来都在实践中找到,但我们如何实际应用它。因为解决方案并不总是简单,所以我会专注于创建一个专用的类来执行该操作。

public class FadePane extends JPanel {
    
    private BufferedImage source;
    private Timer timer;
    
    private float alpha = 1.0f;
    
    private int duration = 2000; // 2 seconds
    private Long startTime;
    
    private boolean fadeOut = false;
    
    private FadeListener fadeListener;
    
    public FadePane(BufferedImage source) {
        this.source = source;
        timer = new Timer(5, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (startTime == null) {
                    startTime = System.currentTimeMillis();
                    fadeStarted();
                }
                long diff = System.currentTimeMillis() - startTime;
                alpha = (float)diff / (float)duration;
                if (alpha > 1.0) {
                    timer.stop();
                    alpha = 1.0f;
                    fadeCompleted();
                }
                if (fadeOut) {
                    alpha = 1.0f - alpha;
                }
                repaint();
            }
        });
    }
    
    public void setFadeListener(FadeListener listener) {
        fadeListener = listener;
    }

    public boolean isFadeOut() {
        return fadeOut;
    }
    
    protected void fadeStarted() {
        if (fadeListener != null) {
            fadeListener.fadeStarted(this);
        }
    }

    protected void fadeCompleted() {
        if (fadeListener != null) {
            fadeListener.fadeCompleted(this);
        }
    }
    
    public void setSource(BufferedImage img) {
        source = img;
    }
    
    public void reset() {
        timer.stop();
        alpha = 0;
        startTime = null;
    }
    
    public void fadeIn() {
        reset();
        fadeOut = false;
        timer.start();
    }
    
    public void fadeOut() {
        reset();
        fadeOut = true;
        timer.start();
    }
    
    @Override
    public Dimension getPreferredSize() {
        return source == null ? new Dimension(200, 200) : new Dimension(source.getWidth(), source.getHeight());
    }
    
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
        int x = (getWidth() - source.getWidth()) / 2;
        int y = (getHeight() - source.getHeight()) / 2;
        g2d.drawImage(source, x, y, this);
        g2d.dispose();
    }
    
}

FadePane需要 source图像,并且根据您调用的方法,将在 2 秒内淡入或淡出图像。

您可以重复使用 FadePane只需更改 source图片来自setSource方法并使新图像淡入或淡出,具体取决于您想要的结果。

FadePane还提供了一个观察者,当淡入淡出操作开始和完成时会收到通知...

public interface FadeListener {
    public void fadeStarted(FadePane pane);
    public void fadeCompleted(FadePane pane);
}

这可用于更改 UI 的状态(禁用/启用功能)以及在需要时切换图像

可运行示例...

这个简单的示例允许用户淡入淡出相同的图像,但生成 List 并不难。通过 FadeListener 更改的图像的数量

Fade

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }

                    BufferedImage source = ImageIO.read(...);
                    FadePane fadePane = new FadePane(source);
                    JButton btn = new JButton("Fade");
                    btn.addActionListener(new ActionListener() {
                        private boolean fadeOut = true;
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            if (fadeOut) {
                                fadePane.fadeOut();
                            } else {
                                fadePane.fadeIn();
                            }
                            fadeOut = !fadeOut;
                        }
                    });

                    fadePane.setFadeListener(new FadeListener() {
                        @Override
                        public void fadeStarted(FadePane pane) {
                            btn.setEnabled(false);
                        }

                        @Override
                        public void fadeCompleted(FadePane pane) {
                            // Set next image and start the
                            // fade process again
                            btn.setEnabled(true);
                        }
                    });

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(fadePane);
                    frame.add(btn, BorderLayout.SOUTH);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public interface FadeListener {
        public void fadeStarted(FadePane pane);
        public void fadeCompleted(FadePane pane);
    }

    public class FadePane extends JPanel {

        private BufferedImage source;
        private Timer timer;

        private float alpha = 1.0f;

        private int duration = 2000; // 2 seconds
        private Long startTime;

        private boolean fadeOut = false;

        private FadeListener fadeListener;

        public FadePane(BufferedImage source) {
            this.source = source;
            timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (startTime == null) {
                        startTime = System.currentTimeMillis();
                        fadeStarted();
                    }
                    long diff = System.currentTimeMillis() - startTime;
                    alpha = (float)diff / (float)duration;
                    if (alpha > 1.0) {
                        timer.stop();
                        alpha = 1.0f;
                        fadeCompleted();
                    }
                    if (fadeOut) {
                        alpha = 1.0f - alpha;
                    }
                    repaint();
                }
            });
        }

        public void setFadeListener(FadeListener listener) {
            fadeListener = listener;
        }

        protected void fadeStarted() {
            if (fadeListener != null) {
                fadeListener.fadeStarted(this);
            }
        }

        protected void fadeCompleted() {
            if (fadeListener != null) {
                fadeListener.fadeCompleted(this);
            }
        }

        public void setSource(BufferedImage img) {
            source = img;
        }

        public void reset() {
            timer.stop();
            alpha = 0;
            startTime = null;
        }

        public boolean isFadeOut() {
            return fadeOut;
        }

        public void fadeIn() {
            reset();
            fadeOut = false;
            timer.start();
        }

        public void fadeOut() {
            reset();
            fadeOut = true;
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return source == null ? new Dimension(200, 200) : new Dimension(source.getWidth(), source.getHeight());
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
            int x = (getWidth() - source.getWidth()) / 2;
            int y = (getHeight() - source.getHeight()) / 2;
            g2d.drawImage(source, x, y, this);
            g2d.dispose();
        }

    }

}

关于java - 如何在JPanel中让3张图片淡入淡出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47610086/

相关文章:

java - eclipse 上 tomcat 8 的问题

java - 带有 log4j 的 Jersey LoggingFilter

java - maven 使用 --add-exports 运行和构建

java - Java中让JPanel填满GridBagLayout中的整个空间

java - 添加到其他 JPanel 时 JPanel 不呈现

java - 我可以在不同项目之间共享 IntelliJ Idea 的设置吗?

java - 在 JList 中写一些东西

java - 使用进度条

java - 使用没有分组字符(千位分隔符)的数字过滤 JTable

java - 如何禁用 JPanel 中的所有组件