JProgressBar duplicating

笑着哭i 提交于 2019-12-13 22:08:50

问题


My JProgressBar is worked perfectly up until i set my JFrame GlassPane visible. It then randomly decides to shoot across the screen and duplicate.

Here is an animated GIF displaying the bug. This happens no matter what my code is - even with an extremely basic GUI

http://i.gyazo.com/bd70df610a3cad6bfff258b80f21c78a.gif

This ONLY happens when i do this.getGlassPane().setVisible(true);

Here is the code:

    public void setProgress(final int percent) {
            pb.setValue(percent);

            if (percent == 100) {

                    SwingUtilities.invokeLater(new Runnable() {
                            public void run() {
                                    FadingMirror glassPane = new FadingMirror();
                                    instance.setGlassPane(glassPane);

                                    ((FadingMirror)instance.getGlassPane()).startAnimation();
                                    ((FadingMirror)instance.getGlassPane()).setVisible(true);
                            }
                    });
            }
    }

    @Override
    public void addText(String text) {
            System.out.println(text);
    }

    public static class FadingMirror extends JPanel implements ActionListener {

            /**
             *
             */
            private static final long serialVersionUID = 7341931028635559650L;
            private float opacity = 0f;
            private Timer fadeTimer;

            public void startAnimation() {
                    fadeTimer = new javax.swing.Timer(75, this);
                    fadeTimer.setInitialDelay(0);
                    fadeTimer.start();

            }

            public void actionPerformed(ActionEvent e) {
                    opacity += .03;
                    if(opacity > 1) {
                            opacity = 1;
                            fadeTimer.stop();
                            fadeTimer = null;
                    }
                    repaint();
            }

            public void paintComponent(Graphics g) {
                    //super.paintComponent(g); //Cannot do this before setting composite without destroying the animation
                    ((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity));
                    g.setColor(getBackground());
                    g.fillRect(0,0,getWidth(),getHeight());
            }
    }

}

Thanks for reading


回答1:


Make a copy of the Graphics object, set the composite on that and draw with that. Then dispose of it.

public void paintComponent(Graphics g) {
    super.paintComponent(g); 
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity));
    g2.setColor(getBackground());
    g2.fillRect(0,0,getWidth(),getHeight());
    g2.dispose();
}



回答2:


Graphics is a shared resource. Generally, any Swing component painted by the frame uses the same Graphics context. One of the jobs of paintComponent is to prepare the Graphics context for painting, typically by filling it the current background color.

Because Graphics is a shared resource, any changes you make to it will affect any other components that are painted after it. You should be restoring the Graphics context to it's previous state before paintComponent exists. This is most easily achieved by using Graphics#create which will create a snap-shot the properties of the Graphics context, but won't affect the original. You should then ensure that you call Graphics#dispose on your copy when you're done.

Your glass pane should also be transparent, allowing what ever is below it to be painted.

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 javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class Test {

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

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

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

    public class FadePane extends JPanel {

        private float alpha = 0;
        private Timer timer;

        public FadePane() {
            timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    alpha += 0.1f;
                    if (alpha > 1.0) {
                        alpha = 1f;
                        timer.stop();
                    }
                    repaint();
                }
            });
            setOpaque(false);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
            g2d.setColor(getBackground());
            g2d.fillRect(0, 0, getWidth(), getHeight());
            g2d.dispose();
        }

        public void fadeAway() {
            setVisible(true);
            timer.stop();
            alpha = 0f;
            timer.start();
        }

    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            setBorder(new EmptyBorder(50, 50, 50, 50));

            JButton btn = new JButton("It's better to burn out then fade away");
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JRootPane rootPane = (JRootPane) SwingUtilities.getAncestorOfClass(JRootPane.class, TestPane.this);
                    FadePane fadePane = (FadePane) rootPane.getGlassPane();
                    fadePane.fadeAway();
                }
            });
            add(btn);
        }

    }

}


来源:https://stackoverflow.com/questions/29268783/jprogressbar-duplicating

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