【问题标题】:JProgressBar duplicatingJProgressBar 复制
【发布时间】:2015-05-29 21:33:21
【问题描述】:

在我将 JFrame GlassPane 设置为可见之前,我的 JProgressBar 运行良好。然后它随机决定在屏幕上拍摄并复制。

这是一个显示错误的动画 GIF。无论我的代码是什么,都会发生这种情况——即使是非常基本的 GUI

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

只有当我这样做时才会发生这种情况 this.getGlassPane().setVisible(true);

代码如下:

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

}

感谢阅读

【问题讨论】:

  • 为了尽快获得更好的帮助,请发布MCVE(最小完整可验证示例)或SSCCE(简短、独立、正确示例)。
  • 您正在为 glassPane 使用 cusomt 组件,它覆盖了 paintpaintComponent 方法,但不首先将其称为超级方法
  • MadProgrammer - 看起来你是完全正确的。唯一的问题是我要覆盖它,因为如果我调用 super 它会破坏我的淡入淡出动画
  • 考虑提供一个runnable example 来证明您的问题。这不是代码转储,而是您正在做的事情的一个示例,它突出了您遇到的问题。这将导致更少的混乱和更好的响应
  • "这里是代码:" 不可编译的代码 sn-p 不是 MCVE 或可运行的示例,因为在 cmets 中已经为您链接了两次。尝试点击链接并阅读文档..

标签: java swing jprogressbar


【解决方案1】:

制作 Graphics 对象的副本,在 that 上设置合成并用它进行绘制。然后丢弃它。

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 是共享资源。通常,框架绘制的任何 Swing 组件都使用相同的Graphics 上下文。 paintComponent 的工作之一是准备 Graphics 用于绘画的上下文,通常通过填充当前背景颜色。

因为Graphics 是共享资源,所以您对它所做的任何更改都会影响在它之后绘制的任何其他组件。您应该将Graphics 上下文恢复到paintComponent 存在之前的状态。这很容易通过使用Graphics#create 来实现,它将创建Graphics 上下文属性的快照,但不会影响原始文件。然后,您应该确保在完成后在您的副本上调用Graphics#dispose

您的玻璃板也应该是透明的,允许在其下方涂漆。

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

    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 2011-11-07
    • 1970-01-01
    相关资源
    最近更新 更多