如何在JPanel中使3张图像淡入淡出?

时间:2017-12-02 16:39:20

标签: 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);
 }
 }

1 个答案:

答案 0 :(得分:1)

理论...

好的,基于您的要求,我的第一个建议是专注于淡入淡出单个图像。如果你能理解如何做到这一点,那么将三个图像逐渐淡出(一个接一个)就更简单了。

动画是随时间变化的幻觉。所以,你首先需要在一段时间内改变alpha的状态。因为Swing既是单线程的又不是线程安全的,所以这给你一个基本的选择,一个Swing Timer

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

由于硬件(和操作系统)的差异,我会避免固定费率淡入淡出(即,您将固定delta应用于alpha并重复直至达到target {1}})。这种方法会在不同的系统上产生不良结果。

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

基础实施......

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

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();
        }

    }

}