【问题标题】:Multiple JLabel Fade In Effect (one at a time)多个 JLabel 淡入效果(一次一个)
【发布时间】:2014-06-11 09:37:33
【问题描述】:

我可以让单个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 个,等等。我不知道如何让一个标签等到最后一个标签淡入完成。

【问题讨论】:

  • 标签是否在一个容器中?为了尽快获得更好的帮助,请发布MCVE(最小完整且可验证的示例)。
  • 1. 8毫秒是很短的时间,在Native OS中处于延迟状态,2.永远不要使用Thread.sleep(8);在 Java 和 Swing 中,阻塞 EDT,3. 使用 Swing Timer,4. Swing Worker 是关于 Worker 线程的桥梁,不要用于 Swing 中的动画,而是使用 Swing Timer
  • 对于example
  • @AndrewThompson 是的,我将 JLabels 放置在带有 Y 轴 BoxLayout 的 JPanel 中,以便它们堆叠。效果很像一个滚动的文本区域,但我可以更方便地操作 JLabels 而不是文本区域文档。
  • 您不应该从除事件调度线程之外的任何线程修改 UI 组件的状态

标签: java swing animation concurrency swingworker


【解决方案1】:

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

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

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

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

然后我开始一个单独的Thread 并迭代列表,淡入每个标签并使用waitFor 等待它显示...

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

    }

}

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

【讨论】:

  • @MadProgrammer +1 只是为了展示动画!它看起来和我想做的完全一样。我将尝试您的示例代码,看看它是否适用于我的程序。
猜你喜欢
  • 1970-01-01
  • 2014-06-06
  • 1970-01-01
  • 2013-12-03
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多