2012-03-08 3 views
5

다른 레이어에 두 개의 JPanel을 포함하는 JLayeredPane (레이어라고 함)이있는 응용 프로그램을 작성하고 있습니다. 아래쪽에있는 JPanel의 paintComponent 메소드 (grid_panel이라고 함)를 재정 의하여 그리드를 그릴 수 있고 그리드의 페인트 컴포넌트 (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

Layer Demo

난 당신이 그릴 비싼 경우 아마도 더블 레이어에 버퍼링에서 떨어져이 문제를 해결 얻을 수 없습니다 확신합니다. 레이어가 같은 스크린 공간을 공유하기 때문에 "더러운"영역을 추적하는 RepaintManager는 모두 하나의 페인트로 다시 칠하기 시작합니다. 행운을 빈다. – Adam

+0

그래서 JPanel은 칠해야 할 것을 캐쉬 할 수있는 방법이 있습니다. (그리는 것은 정적이어야합니다.) 모든 계산을 반복해서하는 대신 캐시를 페인트하기 위해 repaint()를 사용 하시겠습니까? – stackoverflower

+0

도 크기를 조정할 수 있습니다. 끔찍한 깜박임 +1을 사용하면 다른 문제가 발생하지만 [JLayer (Java7 이후)] (http://stackoverflow.com/a/9272534/714968) 또는 'JXLayer (for Java6)' – mKorbel

답변

7

찾은 것처럼, BufferedImage 효율적인 렌더링을위한 복잡한 내용을 캐시 할 수있는 효과적인 방법이다; CellTest이 그 예입니다. here으로 표시된 플라이급 렌더러가 또 다른 접근법입니다. 마지막으로, 나는 실험을 더 쉽게 할 수있는 방법으로 당신의 유익한 예를 다시 생각해 봤습니다.

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