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

时间:2014-06-11 09:37:33

标签: 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个以上等等。我无法弄清楚如何让一个标签等到最后一个标签完成淡入。

1 个答案:

答案 0 :(得分:3)

现在,可能有几种方法可以做到,但这基本上就是我提出来的......

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

对于这个标签,我添加了一个简单的waitFor方法,该方法一直等到达到目标值。这是通过简单的对象监视器实现的。非常重要的是,永远不要在事件调度线程...

上调用此方法

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

然后我开始单独Thread并重复列表,淡化每个标签并使用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();
        }

    }

}

动画部分使用固定的时间进度,而不是固定的增量。这允许动画更加可变,这取决于OS可能发生的过头。基本上这意味着动画每次都会在固定的时间段内进展