2010-04-23 55 views
3

我有一个有两层的窗口:一个静态背景和一个包含移动对象的前景。我的想法是只绘制一次背景(因为它不会改变),所以我将变化的面板变为透明并将其添加到静态背景的顶部。下面是该代码:有多个图层的JFrame

public static void main(String[] args) { 
    JPanel changingPanel = new JPanel() { 

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      g.setColor(Color.RED); 
      g.fillRect(100, 100, 100, 100); 
     } 
    }; 
    changingPanel.setOpaque(false); 

    JPanel staticPanel = new JPanel(); 
    staticPanel.setBackground(Color.BLUE); 
    staticPanel.setLayout(new BorderLayout()); 
    staticPanel.add(changingPanel); 

    JFrame frame = new JFrame(); 
    frame.add(staticPanel); 
    frame.setSize(800, 600); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setVisible(true); 
} 

这段代码给了我正确的图像我想,但我每次重绘changingPanel时间,staticPanel被重新粉刷,以及(这显然是对画静态的整体思路面板只有一次)。有人可以告诉我什么是错的吗?

仅供参考我使用javax.swing.Timer重新计算并每隔24次重新绘制更改的面板。

回答

7

当您将透明组件重新绘制到另一个之上时,仍会使较低组件“脏”,导致它被重新绘制。如果您没有重新绘制较低层,则会在图像上留下拖影效果。

此处唯一可用的优化不是重新生成较低级别上使用的图像。每当上面的图层发生变化时,仍然需要将光栅绘制到图形缓冲区。

+0

是的我同意,所以不适合我 – phunehehe 2010-04-24 07:01:03

3

这正是绘画的工作方式。 Swing必须搜索具有不透明背景的第一个组件。然后绘制该组件和孩子以确保所有绘画都正确完成。

即使您有移动组件,SWing仍然需要“清除”组件的最后位置,这意味着它必须至少重新绘制背景面板的该区域,然后重新绘制移动的组件。

为了使绘画效率更高,子面板应该是不透明的。我不知道你为什么改变了默认设置。

+0

他可能设置为不透明为假,因为他想在组件后面绘制非矩形形状... – Nate 2010-04-23 11:44:23

2

一个非常简单的方法是使用jxlayer。实施AbstractLayerUI并将其添加到您的组件中。请参阅here开始。

+0

感谢您告诉我关于jxlayer的问题,但是当我尝试更低层每次都会重新绘制:( – phunehehe 2010-04-24 07:00:34

+0

没有什么可以做的,JPanel.paintComponent()被调用eveytime调整框架的大小,或者像在JScrollPane中一样滚动。您可以通过让paintComponent()一个backbuffer在你的paintComponents()中只绘制backbufer而没有其他东西。 – 2010-04-24 07:21:06