Java Swing 的圆形进度条不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11846589/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 06:37:32  来源:igfitidea点击:

Circular Progress Bar for Java Swing not working

javaswingjava-7paintcomponentjlayer

提问by Deviling Master

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

我从 Oracle 站点发现了这个测试项目,因为我想在我的项目中添加一个圆形进度条。

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

我正在用 Netbeans 开发应用程序,当我启动应用程序时,圆圈应该在的 JPanel ......消失了。

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.

如果您“按原样”运行此代码,您应该遇到与我相同的问题,未显示 JPanel。

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

但是我发现如果我删除与布局相关的行(27~36),进度条就会开始工作。

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.

因为布局行是由 Netbeans 自动生成的,所以我试图了解如何解决这个问题,因为 Netbeans 编辑器阻止了这些特定的代码行进行编辑。

回答by mKorbel

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

我已经失去了一天,但它仍然无法正常工作....我将在 JLabel 上使用动画 gif.. 故事结束!

@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

@Robin 有重要的信息,而且好像你受限于 GuiBulder 的使用......,那么我不想评论什么,结果是

enter image description here

在此处输入图片说明

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 JPanelhas implemented FlowLayout, that pretty accepting PreferredSizecame from its childs,

  • 必须添加两个JButtons,一个用于开始,第二个用于停止(显示和隐藏动画演出)

  • 不要忘记JPanel已经实施了FlowLayout,那个漂亮的接受PreferredSize来自它的孩子,

回答by Deviling Master

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

使用SwingLabs 的Swing Components Extension 找到了一个更好的简单(和有效)解决方案

JXBusyLabel

JX忙标签

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

它的编辑器有一个与 NetBeans 完全集成的插件,因此使用起来非常简单

回答by David Kroukamp

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

从您的问题和评论看来,您JLayer在 Netbeans 中实施时遇到了问题,我建议CardLayout您选择一个可以让您在普通JPanel和带有spinner 的之间切换。

Here is a simple tutorial: CardLayout With Netbeans

这是一个简单的教程:CardLayout With Netbeans