2010-04-23 62 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