Circular Progress Bar for Java Swing not working

╄→гoц情女王★ 提交于 2019-11-30 08:42:45

问题


i've discovered this test project from Oracle site because i want to add a circular progress bar in my project.

I'm developing the application with Netbeans, and when i start the application, the JPanel where the circle should be.... disappaer.

I've removed all the code that is not useful to solve this problem and i've got this code:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import javax.swing.plaf.LayerUI;


public class Loading_Test extends javax.swing.JFrame
{
    static final WaitLayerUI layerUI = new WaitLayerUI();
    public Loading_Test()
    {

        JPanel panel = new JPanel();
        JLayer<JPanel> jlayer = new JLayer<>(panel, layerUI);
        add(jlayer);

        initComponents();
    }

    @SuppressWarnings("unchecked")
    private void initComponents() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        pack();
    }

    public static void main(String args[])
    {
        java.awt.EventQueue.invokeLater(new Runnable()
        {

            @Override
            public void run()
            {                
                JFrame frame = new Loading_Test();
                frame.setVisible(true);
                layerUI.start();
            }
        });
    }
}
class WaitLayerUI extends LayerUI<JPanel> implements ActionListener
{

    private boolean mIsRunning;
    private boolean mIsFadingOut;
    private Timer mTimer;
    private int mAngle;
    private int mFadeCount;
    private int mFadeLimit = 15;

    @Override
    public void paint(Graphics g, JComponent c)
    {
        int w = c.getWidth();
        int h = c.getHeight();

        // Paint the view.
        super.paint(g, c);

        if (!mIsRunning)
        {
            return;
        }

        Graphics2D g2 = (Graphics2D) g.create();

        float fade = (float) mFadeCount / (float) mFadeLimit;
        // Gray it out.
        Composite urComposite = g2.getComposite();
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f * fade));
        g2.fillRect(0, 0, w, h);
        g2.setComposite(urComposite);

        // Paint the wait indicator.
        int s = Math.min(w, h) / 5;
        int cx = w / 2;
        int cy = h / 2;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setStroke(new BasicStroke(s / 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g2.setPaint(Color.white);
        g2.rotate(Math.PI * mAngle / 180, cx, cy);
        for (int i = 0; i < 12; i++)
        {
            float scale = (11.0f - (float) i) / 11.0f;
            g2.drawLine(cx + s, cy, cx + s * 2, cy);
            g2.rotate(-Math.PI / 6, cx, cy);
            g2.setComposite(AlphaComposite.getInstance(
                    AlphaComposite.SRC_OVER, scale * fade));
        }

        g2.dispose();
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        if (mIsRunning)
        {
            firePropertyChange("tick", 0, 1);
            mAngle += 3;
            if (mAngle >= 360)
            {
                mAngle = 0;
            }
            if (mIsFadingOut)
            {
                if (--mFadeCount == 0)
                {
                    mIsRunning = false;
                    mTimer.stop();
                }
            }
            else if (mFadeCount < mFadeLimit)
            {
                mFadeCount++;
            }
        }
    }

    public void start()
    {
        if (mIsRunning)
        {
            return;
        }

        // Run a thread for animation.
        mIsRunning = true;
        mIsFadingOut = false;
        mFadeCount = 0;
        int fps = 24;
        int tick = 1000 / fps;
        mTimer = new Timer(tick, this);
        mTimer.start();
    }

    public void stop()
    {
        mIsFadingOut = true;
    }

    @Override
    public void applyPropertyChange(PropertyChangeEvent pce, JLayer l)
    {
        if ("tick".equals(pce.getPropertyName()))
        {
            l.repaint();
        }
    }
}

If you run this code "as is", you should have the same my problem, the JPanel is not shown.

But i've discovered that if i remove the layout-related lines (27~36) the progress bar starts to work.

You also have to set manually the windows size adding

setSize(300, 300);

after

pack();

Because the layout-lines are automatically generated by Netbeans, i'm trying to understand how to solve this problem, because this particular lines of code are blocked for editing by Netbeans Editor.


回答1:


I've lost one day and it still not working.... I'll use an animated gif on JLabel.... End of story!

@Robin has important info, and seems like as you limited by usage of GuiBulder..., then I'm don't want to comment something, result is

from little bit modified code

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import javax.swing.plaf.LayerUI;

public class Loading_Test {

    static final WaitLayerUI layerUI = new WaitLayerUI();
    JFrame frame = new JFrame("JLayer With Animated Gif");

    public Loading_Test() {
        JPanel panel = new JPanel() {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 300);
            }
        };
        JLayer<JPanel> jlayer = new JLayer<>(panel, layerUI);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(jlayer);
        frame.pack();
        frame.setVisible(true);
        layerUI.start();
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                Loading_Test loading_Test = new Loading_Test();

            }
        });
    }
}

class WaitLayerUI extends LayerUI<JPanel> implements ActionListener {

    private boolean mIsRunning;
    private boolean mIsFadingOut;
    private Timer mTimer;
    private int mAngle;
    private int mFadeCount;
    private int mFadeLimit = 15;

    @Override
    public void paint(Graphics g, JComponent c) {
        int w = c.getWidth();
        int h = c.getHeight();
        super.paint(g, c); // Paint the view.
        if (!mIsRunning) {
            return;
        }
        Graphics2D g2 = (Graphics2D) g.create();
        float fade = (float) mFadeCount / (float) mFadeLimit;
        Composite urComposite = g2.getComposite(); // Gray it out.
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f * fade));
        g2.fillRect(0, 0, w, h);
        g2.setComposite(urComposite);
        int s = Math.min(w, h) / 5;// Paint the wait indicator.
        int cx = w / 2;
        int cy = h / 2;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setStroke(new BasicStroke(s / 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g2.setPaint(Color.white);
        g2.rotate(Math.PI * mAngle / 180, cx, cy);
        for (int i = 0; i < 12; i++) {
            float scale = (11.0f - (float) i) / 11.0f;
            g2.drawLine(cx + s, cy, cx + s * 2, cy);
            g2.rotate(-Math.PI / 6, cx, cy);
            g2.setComposite(AlphaComposite.getInstance(
                    AlphaComposite.SRC_OVER, scale * fade));
        }
        g2.dispose();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (mIsRunning) {
            firePropertyChange("tick", 0, 1);
            mAngle += 3;
            if (mAngle >= 360) {
                mAngle = 0;
            }
            if (mIsFadingOut) {
                if (--mFadeCount == 0) {
                    mIsRunning = false;
                    mTimer.stop();
                }
            } else if (mFadeCount < mFadeLimit) {
                mFadeCount++;
            }
        }
    }

    public void start() {
        if (mIsRunning) {
            return;
        }
        mIsRunning = true;// Run a thread for animation.
        mIsFadingOut = false;
        mFadeCount = 0;
        int fps = 24;
        int tick = 1000 / fps;
        mTimer = new Timer(tick, this);
        mTimer.start();
    }

    public void stop() {
        mIsFadingOut = true;
    }

    @Override
    public void applyPropertyChange(PropertyChangeEvent pce, JLayer l) {
        if ("tick".equals(pce.getPropertyName())) {
            l.repaint();
        }
    }
}
  • have to add two JButtons, one for start and second for stop (show and hide animated Gig)

  • don't forger that JPanel has implemented FlowLayout, that pretty accepting PreferredSize came from its childs,




回答2:


Found a better simple (and working) solution with Swing Components Extension by SwingLabs

JXBusyLabel

There is a fully integrating plugin with NetBeans for its editor, so is very simple to use




回答3:


It seems from your question and comments you are having problems implementing the JLayer in Netbeans, I'd suggest then rather going for a CardLayout which will allow you to switch between your normal JPanel and the one with the spinner.

Here is a simple tutorial: CardLayout With Netbeans



来源:https://stackoverflow.com/questions/11846589/circular-progress-bar-for-java-swing-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!