2012-03-08 40 views
5

我正在寫一個應用程序,它有一個包含兩個JPanel的JLayeredPane(稱爲圖層),它位於不同的圖層中。我覆蓋底部JPanel的paintComponent方法(稱爲grid_panel),以便繪製網格,並在頂部繪製paintComponent方法(稱爲circuit_panel),以繪製電路。JLayeredPane和繪畫

這裏的結構的總結:

layers - 
     |-circuit_panel (on top) 
     |-grid_panel (at bottom) 

我想grid_panel留靜態的,即,不要做任何重繪(除了最初的一個),因爲它不會改變。

問題是,每當我打電話給circuit_panel.repaint()時,,grid_panel也會被重新繪製!這絕對沒有效率。

我認爲這是由於JLayeredPane渴望的繪畫行爲。有沒有辦法在JLayeredPane中禁用此功能?

在你有興趣看到上面的效果的情況下,我寫了一個小的演示程序:

public class Test2 extends JFrame { 

    public Test2() { 
     JLayeredPane layers = new JLayeredPane(); 
     layers.setPreferredSize(new Dimension(600, 400)); 

     MyPanel1 myPanel1 = new MyPanel1(); 
     MyPanel2 myPanel2 = new MyPanel2(); 
     myPanel1.setSize(600, 400); 
     myPanel2.setSize(600, 400); 
     myPanel1.setOpaque(false); 
     myPanel2.setOpaque(false); 
     myPanel2.addMouseListener(new MyMouseListener(myPanel2)); 

     layers.add(myPanel1, new Integer(100)); // At bottom 
     layers.add(myPanel2, new Integer(101)); // On top 

     this.getContentPane().add(layers, BorderLayout.CENTER); 
     this.setSize(600, 400); 
    } 

    class MyPanel1 extends JPanel { 

     Color getRandomColor() { 
      int r = (int) (256 * Math.random()); 
      int g = (int) (256 * Math.random()); 
      int b = (int) (256 * Math.random()); 
      return new Color(r, g, b); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g; 
      g2d.setColor(getRandomColor()); 
      g2d.fillRoundRect(30, 30, 60, 60, 5, 5); 
     } 
    } 

    class MyPanel2 extends JPanel { 

     Color getRandomColor() { 
      int r = (int) (256 * Math.random()); 
      int g = (int) (256 * Math.random()); 
      int b = (int) (256 * Math.random()); 
      return new Color(r, g, b); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g; 
      g2d.setColor(getRandomColor()); 
      g2d.fillRoundRect(45, 45, 75, 75, 5, 5); 
     } 
    } 

    class MyMouseListener extends MouseAdapter { 

     JPanel panel; 

     MyMouseListener(JPanel panel) { 
      this.panel = panel; 
     } 

     @Override 
     public void mouseClicked(MouseEvent e) { 
      panel.repaint(); 
     } 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       (new Test2()).setVisible(true); 
      } 
     }); 
    } 
} 
+0

我敢肯定,你將無法從昂貴,如果繪製也許雙緩衝你的層次解決這個問題分開。這一切都歸結於RepaintManager,它跟蹤「髒」區域,因爲這些圖層共享相同的屏幕空間,重新繪製一個會觸發重新繪製另一個...祝您好運。 – Adam 2012-03-08 21:51:43

+0

所以有一種方法讓JPanel緩存它應該繪製的內容(當然,繪製的內容應該是靜態的),並讓repaint()只繪製緩存,而不是一次又一次地進行所有這些計算? – stackoverflower 2012-03-08 22:00:01

+0

hehehe在調整太大,太可怕的閃爍+1時,必須有另一個問題,但你能夠使用[JLayer(自Java7)](http://stackoverflow.com/a/9272534/714968)或'JXLayer對於Java6)' – mKorbel 2012-03-08 22:07:11

回答

7

當你發現一個BufferedImage是緩存高效渲染複雜內容的有效途徑; CellTest就是一個例子。顯示here的flyweight渲染器是另一種方法。最後,我以一種可能使實驗更容易的方式重新考慮了您的指導性示例。

Layer Demo

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.Random; 
import javax.swing.JFrame; 
import javax.swing.JLayeredPane; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

/** @see https://stackoverflow.com/q/9625495/230513 */ 
public class LayerDemo extends JFrame { 

    private static final Dimension d = new Dimension(320, 240); 

    public LayerDemo() { 
     JLayeredPane layers = new JLayeredPane(); 
     layers.setPreferredSize(d); 

     layers.add(new LayerPanel(1 * d.height/8), 100); 
     layers.add(new LayerPanel(2 * d.height/8), 101); 
     layers.add(new LayerPanel(3 * d.height/8), 102); 

     this.add(layers, BorderLayout.CENTER); 
     this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     this.pack(); 
     this.setLocationByPlatform(true); 
    } 

    private static class LayerPanel extends JPanel { 

     private static final Random r = new Random(); 
     private int n; 
     private Color color = new Color(r.nextInt()); 

     public LayerPanel(int n) { 
      this.n = n; 
      this.setOpaque(false); 
      this.setBounds(n, n, d.width/2, d.height/2); 
      this.addMouseListener(new MouseHandler(this)); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g; 
      g2d.setRenderingHint(
       RenderingHints.KEY_ANTIALIASING, 
       RenderingHints.VALUE_ANTIALIAS_ON); 
      g2d.setColor(color); 
      g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 16, 16); 
      g2d.setColor(Color.black); 
      g2d.drawString(String.valueOf(n), 5, getHeight() - 5); 
     } 

     private void update() { 
      color = new Color(r.nextInt()); 
      repaint(); 
     } 
    } 

    private static class MouseHandler extends MouseAdapter { 

     LayerPanel panel; 

     MouseHandler(LayerPanel panel) { 
      this.panel = panel; 
     } 

     @Override 
     public void mouseClicked(MouseEvent e) { 
      panel.update(); 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       (new LayerDemo()).setVisible(true); 
      } 
     }); 
    } 
}