为什么swing会简单地绘制两次?

时间:2012-08-15 09:32:32

标签: java swing graphics awt paintcomponent

这是绘制椭圆形的简单示例。

public class SwingPainter extends JFrame{
    public SwingPainter() {
        super("Swing Painter");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        getContentPane().add(new MySwingComponent());

        setSize(200, 200);
        setVisible(true);
    }

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

    class MySwingComponent extends JComponent {

         public void paintComponent(Graphics g) {
            System.out.println("paintComponent");
            super.paintComponent(g);
            g.setColor(Color.red);
            g.fillOval(10, 10, 50, 50);
        }

        @Override
        protected void paintBorder(Graphics g) {
            System.out.println("Paint border");
            super.paintBorder(g);
        }

        @Override
        protected void paintChildren(Graphics g) {
            System.out.println("Paint children");
            super.paintChildren(g);
        }
    }
}

但是在调试模式或在绘制之前向控制台添加一些信息(如示例中),您可以看到swing绘制两次组件。

  

的paintComponent

     

绘制边框

     

画儿童

     

的paintComponent

     

绘制边框

     

画儿童

我无法理解为什么会这样,但我认为它可能会影响困难的GUI中的性能。

3 个答案:

答案 0 :(得分:9)

文章Painting in AWT and Swing: Additional Paint Properties: Opacity提出了原因:“不透明属性允许Swing的绘图系统检测特定组件上的重绘请求是否需要额外重新绘制基础祖先。”因为您扩展JComponent,所以opaque属性默认为false,并且无法进行优化。设置属性true以查看差异,以及不尊重属性的工件。可以找到相关示例herehere

答案 1 :(得分:2)

我同意Konstantin,您需要记住的是,重绘管理器在应用程序启动时响应任意数量的请求,这通常包括显示窗口和调整大小时的初始绘制请求(有两个)。

试试这个。等到应用程序运行并调整窗口大小。我相信你会得到更多的重复请求;)

答案 2 :(得分:2)

这对我来说很好。实际上,即使在调试模式下,输出也是:

paintComponent
Paint border
Paint children

请记住,在AWT和Swing组件中,只要GUI引擎找到合适的方法,就会有很多方法(paint,paintBorder,paintChildren,paintComponent,repaint和其他方法)通过回调调用。这可能因JVM到JVM或甚至不同的执行会话而异。它们也可以通过与程序的交互来触发(例如,如果最小化/最大化)。或者他们可能根本没有。