Java:制作漂亮的JProgressBar

时间:2013-11-22 03:27:53

标签: java swing animation java-2d jprogressbar

我在java中使用JProgressBars的时间不长,而且我看到的将其设置为漂亮的每个资源都不起作用。我想要的是应用程序,您将看到整个进度条从上到下填充,当值增加时,动画随着大小的增加而播放。我目前拥有的是JProgressBar,当它增加值时,它没有动画,当它有一个偏移到右上角时,如下所示:

enter image description here

如你所见,这很难看。如何才能看到JProgressBar的完整边框,整个填充和动画?

1 个答案:

答案 0 :(得分:5)

关于以任何有意义的方式修改JProgressBar的唯一方法是设计自己的UI委托......

Animate progress bar

这基本上是基于我很久以前做过的一些工作的例子。

该示例以25为增量更新进度条,但进度条“尝试”以小增量从其当前位置填充到目标值。

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.LinearGradientPaint;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.BoundedRangeModel;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.basic.BasicProgressBarUI;

public class TestMediaProgressBar {

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

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

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

    public class TestPane extends JPanel {

        private MediaProgressBar pb;
        private int value = 0;
        private int delta = 25;

        public TestPane() {
            setBackground(Color.BLACK);
            setLayout(new GridBagLayout());
            pb = new MediaProgressBar();
            add(pb);

            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (value + delta > 100) {
                        delta *= -1;
                        value = 100;
                    } else if (value + delta < 0) {
                        delta *= -1;
                        value = 0;
                    }
                    value += delta;
                    pb.setValue(value);
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    }

    public class MediaProgressBar extends JProgressBar {

        public MediaProgressBar() {
            setUI(new MediaProgressBarUI());
        }

        @Override
        public Dimension getPreferredSize() {

            return new Dimension(128, 24);

        }

    }

    public class MediaProgressBarUI extends BasicProgressBarUI {

        private Handler handler;
        private double renderProgress = 0;
        private double targetProgress = 0;
        private double progressDelta = 0.04;
        private Timer repaintTimer;
        private Timer paintTimer;

        public MediaProgressBarUI() {
            repaintTimer = new Timer(25, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    progressBar.repaint();
                }
            });
            repaintTimer.setRepeats(false);
            repaintTimer.setCoalesce(true);

            paintTimer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (progressDelta < 0) {

                        if (renderProgress + progressDelta < targetProgress) {
                            ((Timer) e.getSource()).stop();
                            renderProgress = targetProgress + progressDelta;
                        }

                    } else {

                        if (renderProgress + progressDelta > targetProgress) {
                            ((Timer) e.getSource()).stop();
                            renderProgress = targetProgress - progressDelta;
                        }

                    }
                    renderProgress += progressDelta;
                    requestRepaint();
                }
            });
        }

        protected void requestRepaint() {
            repaintTimer.restart();
        }

        @Override
        protected void installDefaults() {
            super.installDefaults();
            progressBar.setOpaque(false);
            progressBar.setBorder(null);
        }

        public void setRenderProgress(double value) {
            if (value != targetProgress) {
                paintTimer.stop();

                targetProgress = value;
                if (targetProgress < renderProgress && progressDelta > 0) {
                    progressDelta *= -1;
                } else if (targetProgress > renderProgress && progressDelta < 0) {
                    progressDelta *= -1;
                }
                System.out.println(progressDelta);

                paintTimer.start();
            }
        }

        public double getRenderProgress() {
            return renderProgress;
        }

        @Override
        public void paint(Graphics g, JComponent c) {
            Graphics2D g2d = (Graphics2D) g.create();

            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            int iStrokWidth = 3;
            g2d.setStroke(new BasicStroke(iStrokWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2d.setColor(c.getBackground());
            g2d.setBackground(c.getBackground());

            int width = c.getWidth();
            int height = c.getHeight();

            RoundRectangle2D outline = new RoundRectangle2D.Double((iStrokWidth / 2), (iStrokWidth / 2),
                    width - iStrokWidth, height - iStrokWidth,
                    height, height);

            g2d.draw(outline);

            int iInnerHeight = height - (iStrokWidth * 4);
            int iInnerWidth = width - (iStrokWidth * 4);

            iInnerWidth = (int) Math.round(iInnerWidth * renderProgress);

            int x = iStrokWidth * 2;
            int y = iStrokWidth * 2;

            Point2D start = new Point2D.Double(x, y);
            Point2D end = new Point2D.Double(x, y + iInnerHeight);

            float[] dist = {0.0f, 0.25f, 1.0f};
            Color[] colors = {c.getBackground(), c.getBackground().brighter(), c.getBackground().darker()};
            LinearGradientPaint p = new LinearGradientPaint(start, end, dist, colors);

            g2d.setPaint(p);

            RoundRectangle2D fill = new RoundRectangle2D.Double(iStrokWidth * 2, iStrokWidth * 2,
                    iInnerWidth, iInnerHeight, iInnerHeight, iInnerHeight);

            g2d.fill(fill);

            g2d.dispose();
        }

        @Override
        protected void installListeners() {
            super.installListeners();
            progressBar.addChangeListener(getChangeHandler());
        }

        protected ChangeListener getChangeHandler() {

            return getHandler();

        }

        protected Handler getHandler() {

            if (handler == null) {
                handler = new Handler();
            }

            return handler;

        }

        protected class Handler implements ChangeListener {

            @Override
            public void stateChanged(ChangeEvent e) {

                BoundedRangeModel model = progressBar.getModel();
                int newRange = model.getMaximum() - model.getMinimum();
                double dProgress = (double) (model.getValue() / (double) newRange);

                if (dProgress < 0) {
                    dProgress = 0;
                } else if (dProgress > 1) {
                    dProgress = 1;
                }

                setRenderProgress(dProgress);

            }

        }

    }

}