Java淡入淡出图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20346661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:13:30  来源:igfitidea点击:

Java fade in and out of images

javaimageswinganimationtransparency

提问by user2079828

I am trying to learn how to fade in and out images into another image or from another image. So, if I have 2 images, and 1 is being displayed at the moment, I want to display another image in the background and fade the first image out into the 2nd image. OR, I want to set the focus on the new image and slowly fade it in over the 1st image, then stop displaying the 1st one.

我正在尝试学习如何将图像淡入和淡出到另一个图像或从另一个图像中。因此,如果我有 2 张图像,并且目前正在显示 1 张图像,我想在背景中显示另一张图像并将第一张图像淡入第二张图像。或者,我想将焦点设置在新图像上并在第一个图像上慢慢淡入,然后停止显示第一个图像。

I'm not sure how:

我不确定如何:

  1. to set focus, if even needed.

  2. I can fade in if I change the alpha to 0 and increment up and only draw one image, however I cannot get it to fade out either with any variation of this code. (i.e. commenting out one image to draw).

  1. 设置焦点,如果甚至需要。

  2. 如果我将 alpha 更改为 0 并递增并且只绘制一张图像,我可以淡入,但是我无法使用此代码的任何变体使其淡出。(即注释掉一张要绘制的图像)。

Edit: Really, all I'm worried about is being able to have 2 images and make the image currently being displayed slowly disappear into the 2nd image. How that is accomplished doesn't need to be with this.

编辑:真的,我担心的是能够拥有 2 张图像并使当前显示的图像慢慢消失在第二张图像中。如何实现不需要与此有关。

Here is a code sample I'm messing with:

这是我弄乱的代码示例:

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 FadeIn extends JPanel implements ActionListener {

    private Image imagem;
    private Image image2;
    private Timer timer;
    private float alpha = 1f;

    public FadeIn() {
        imagem = (new ImageIcon(getClass().getResource(
             "/resources/1stImage.jpg"))).getImage();
        image2 = (new ImageIcon(getClass().getResource(
             "/resources/2ndImage.jpg"))).getImage();    
        timer = new Timer(20, this);
        timer.start();
    }
    // here you define alpha 0f to 1f

    public FadeIn(float alpha) {
        imagem = (new ImageIcon(getClass().getResource(
             "/resources/1stImage.jpg"))).getImage();
        this.alpha = alpha;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(imagem, 0, 0, 400, 300, null);
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                alpha));
        g2d.drawImage(image2, 0, 0, 400, 300, null);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Fade out");
        frame.add(new FadeIn());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(420, 330);
        // frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

采纳答案by MadProgrammer

Basically, what this does is use the same alpha value, fading in from 0-1 and then using the same alpha, going from 1-0, allowing the two images to cross fade over each other...

基本上,这样做是使用相同的 alpha 值,从 0-1 淡入,然后使用相同的 alpha,从 1-0 开始,允许两个图像相互淡入淡出......

Fading

衰退

The magic basically, happens in the paintComponent, where the image coming in using the alphavalue and the outgoing image uses 1f - alpha.

魔术基本上发生在 中paintComponent,其中使用alpha值传入的图像和传出图像使用1f - alpha.

Switching between the two images is actually a the same process, expect the inImageis swapped for the outImage

在两个图像之间切换实际上是一个相同的过程,期望inImage交换为outImage

The timing is little different. Instead of a straight move from 0-1using a standard delta (ie 0.01for example), this uses a time based algorithm.

时间略有不同。这不是直接0-1使用标准增量(即0.01例如),而是使用基于时间的算法。

That is, I use a timer which ticks every 40 milliseconds or so, it then does a calculation based on the amount of time the timer has being running and calculates the alphavalue accordingly...

也就是说,我使用一个计时器,它每 40 毫秒左右滴答一次,然后根据计时器运行的时间量进行计算并相应地计算alpha值...

This allows you to change the amount of time the animation will take, but also provides a slightly better algorithm that takes into account the passive nature of Swings rendering engine...

这允许您更改动画将花费的时间量,但也提供了一个稍微更好的算法,该算法考虑了 Swings 渲染引擎的被动性质......

import java.awt.AlphaComposite;
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.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FadeImage {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        public static final long RUNNING_TIME = 2000;

        private BufferedImage inImage;
        private BufferedImage outImage;

        private float alpha = 0f;
        private long startTime = -1;

        public TestPane() {
            try {
                inImage = ImageIO.read(new File("/path/to/inImage"));
                outImage = ImageIO.read(new File("/path/to/outImage"));
            } catch (IOException exp) {
                exp.printStackTrace();
            }

            final Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (startTime < 0) {
                        startTime = System.currentTimeMillis();
                    } else {

                        long time = System.currentTimeMillis();
                        long duration = time - startTime;
                        if (duration >= RUNNING_TIME) {
                            startTime = -1;
                            ((Timer) e.getSource()).stop();
                            alpha = 0f;
                        } else {
                            alpha = 1f - ((float) duration / (float) RUNNING_TIME);
                        }
                        repaint();
                    }
                }
            });
            addMouseListener(new MouseAdapter() {

                @Override
                public void mouseClicked(MouseEvent e) {
                    alpha = 0f;
                    BufferedImage tmp = inImage;
                    inImage = outImage;
                    outImage = tmp;
                    timer.start();
                }

            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(
                            Math.max(inImage.getWidth(), outImage.getWidth()), 
                            Math.max(inImage.getHeight(), outImage.getHeight()));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
            int x = (getWidth() - inImage.getWidth()) / 2;
            int y = (getHeight() - inImage.getHeight()) / 2;
            g2d.drawImage(inImage, x, y, this);

            g2d.setComposite(AlphaComposite.SrcOver.derive(1f - alpha));
            x = (getWidth() - outImage.getWidth()) / 2;
            y = (getHeight() - outImage.getHeight()) / 2;
            g2d.drawImage(outImage, x, y, this);
            g2d.dispose();
        }

    }

}