java - 多个 JLabel 淡入效果(一次一个)

标签 java swing animation concurrency swingworker

我可以使单个 JLabel 淡入,但如何使多个标签相继淡入?这是我当前的代码。

public void fadeIn(final JLabel jLabel) {
    jLabelList.add(jLabel);
    jLabelBackPanel.add(jLabelList.get(jLabelList.size() - 1));
    new SwingWorker<Void, Void>() {
        @Override
        protected Void doInBackground() throws Exception {
            int c = 0;
            for(int i = 0; i < 255; i++) {
                Thread.sleep(1000);
                jLabel.setForeground(new Color(
                    jLabel.getForeground().getRed(),
                    jLabel.getForeground().getGreen(),
                    jLabel.getForeground().getBlue(),
                    c++));
            }
            return null;
        }
    }.execute();
}

上面的代码将一次淡入大约 9 个标签,然后再淡入 9 个,依此类推。我不知道如何让一个标签等到最后一个标签完成淡入为止。

最佳答案

现在,可能有几种方法可以做到这一点,但这基本上是我想出的......

首先,我创建了一个自定义标签,它使用 javax.swing.Timer 从起始 alpha 值进展到目标 alpha 值(即 0-1 淡入)。

对于这个标签,我添加了一个简单的 waitFor 方法,该方法会一直等到达到目标值。这是通过一个简单的对象监视器来实现的。非常重要,当您在事件调度线程上时,切勿调用此方法...

接下来,我创建了一系列这样的标签,其中包含我想要显示的文本,并将每个标签添加到输出中。

然后,我启动了一个单独的线程并迭代列表,淡入每个标签并使用waitFor等待它显示...

Fading

import java.awt.AlphaComposite;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FadingLabels {

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

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

                final List<FadingLabel> labels = new ArrayList<>(25);
                labels.add(new FadingLabel("A "));
                labels.add(new FadingLabel("long "));
                labels.add(new FadingLabel("time "));
                labels.add(new FadingLabel("ago "));
                labels.add(new FadingLabel("in "));
                labels.add(new FadingLabel("a "));
                labels.add(new FadingLabel("galaxy "));
                labels.add(new FadingLabel("far, "));
                labels.add(new FadingLabel("far, "));
                labels.add(new FadingLabel("away"));
                labels.add(new FadingLabel("..."));

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());

                for (FadingLabel label : labels) {
                    frame.add(label);
                }

                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (FadingLabel label : labels) {
                            label.fadeIn();
                            label.waitFor();
                        }
                    }
                }).start();

            }
        });
    }

    public class FadingLabel extends JLabel {

        protected static final int TIME = 1000;
        protected final Object fadeLock = new Object();

        private float targetAlpha;
        private float alpha = 0;
        private Timer timer;
        private long startTime;
        private float fromAlpha;

        public FadingLabel() {
            init();
        }

        public FadingLabel(String text, Icon icon, int horizontalAlignment) {
            super(text, icon, horizontalAlignment);
            init();
        }

        public FadingLabel(String text, int horizontalAlignment) {
            super(text, horizontalAlignment);
            init();
        }

        public FadingLabel(String text) {
            super(text);
            init();
        }

        public FadingLabel(Icon image, int horizontalAlignment) {
            super(image, horizontalAlignment);
            init();
        }

        public FadingLabel(Icon image) {
            super(image);
            init();
        }

        protected void init() {

            timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (alpha < 1f) {
                        long now = System.currentTimeMillis();
                        long diff = now - startTime;
                        float progress = (float) diff / (float) TIME;

                        float distance = targetAlpha - fromAlpha;
                        alpha = (float) (distance * progress);
                        alpha += fromAlpha;

                        if (alpha > 1f) {
                            timer.stop();
                            alpha = 1f;
                        }

                    } else {
                        alpha = 1f;
                        timer.stop();
                    }
                    repaint();
                    if (!timer.isRunning()) {
                        synchronized (fadeLock) {
                            fadeLock.notifyAll();
                        }
                    }
                }
            });
            timer.setInitialDelay(0);

        }

        protected void fadeTo(float target) {
            Runnable run = new Runnable() {
                @Override
                public void run() {
                    timer.stop();
                    fromAlpha = alpha;
                    targetAlpha = target;
                    if (targetAlpha != alpha) {
                        startTime = System.currentTimeMillis();
                        timer.start();
                    } else {
                        repaint();
                    }
                }
            };
            if (EventQueue.isDispatchThread()) {
                run.run();
            } else {
                EventQueue.invokeLater(run);
            }
        }

        public void fadeIn() {
            fadeTo(1f);
        }

        public void fadeOut() {
            fadeTo(0f);
        }

        public void waitFor() {
            if (EventQueue.isDispatchThread()) {
                throw new IllegalStateException("Calling waitFor while within the EDT!");
            }
            synchronized (fadeLock) {
                try {
                    fadeLock.wait();
                } catch (InterruptedException ex) {
                }
            }
        }

        @Override
        public void paint(Graphics g) {
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
            super.paint(g2d);
            g2d.dispose();
        }

    }

}

动画部分使用固定的时间进度,而不是固定的增量。这使得动画可以根据操作系统可能发生的开销而变得更加可变。基本上这意味着动画每次都会在固定的时间内进行

关于java - 多个 JLabel 淡入效果(一次一个),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24159510/

相关文章:

Java 类加载器 - 在私有(private)类中调用静态方法

java - 如何使禁用的 JTabbedPane 选项卡的外观与 Activity 时的外观完全相同?

java - 未最大化时,线条绘制在错误的位置

css - 无法阻止动画循环

javascript - jQuery 鼠标悬停间隔

java - 如何每次单击按钮时添加新的 Textview

java - 编译期间 Int 初始化错误

java - 正则表达式 - 在第一个匹配后获取第二个单词

java - 在客户端计算机上部署 java(swing, oracle) 项目时出错... java.lang.ClassNotFoundException :oracle. jdbc.driver.oracleDriver

javascript - 试图让 svg 路径顺利流动