2012-03-08 24 views
5

Tôi đang viết một ứng dụng có JLayeredPane (gọi nó là lớp) chứa hai JPanels ở các lớp khác nhau. Tôi ghi đè lên phương pháp paintComponent của JPanel ở phía dưới (gọi nó là grid_panel) để nó vẽ một lưới, và phương thức paintComponent của một ở đầu (gọi nó là circuit_panel) để nó vẽ một mạch.JLayeredPane và vẽ

Dưới đây là một bản tóm tắt của cấu trúc:

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

Tôi muốn grid_panel ở lại tĩnh, tức là, không phải làm bất cứ repaint (trừ ban đầu một) vì nó không thay đổi.

Sự cố là, bất cứ khi nào tôi gọi circuit_panel.repaint(), grid_panel cũng được sơn lại! Đây chắc chắn là không hiệu quả.

Tôi nghĩ điều này là do hành vi sơn mong muốn của JLayeredPane. Có cách nào để tắt tính năng này trong JLayeredPane không?

Trong trường hợp bạn đang quan tâm để xem hiệu ứng trên, tôi đã viết một chương trình giới thiệu nhỏ:

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

Tôi khá chắc chắn rằng bạn sẽ không thể làm được việc này ngoài việc có thể tăng gấp đôi đệm lớp của bạn nếu tốn kém để vẽ. Tất cả đi xuống để RepaintManager mà theo dõi các khu vực "bẩn", bởi vì các lớp chia sẻ cùng một không gian màn hình một repaint của một sẽ kích hoạt một repaint khác ... Chúc may mắn. – Adam

+0

Vì vậy, có cách nào để JPanel lưu vào bộ nhớ cache những gì nó nên vẽ (tất nhiên những gì được vẽ nên tĩnh), và để vẽ lại() để vẽ bộ nhớ cache, thay vì thực hiện tất cả các phép tính đó lặp đi lặp lại? – stackoverflower

+0

hehehe về thay đổi kích thước quá, với khủng khiếp nhấp nháy +1, phải có một vấn đề khác, nhưng bạn có thể sử dụng [JLayer (kể từ Java7)] (http://stackoverflow.com/a/9272534/714968) hoặc 'JXLayer (cho Java6) ' – mKorbel

Trả lời

7

Như bạn thấy, một BufferedImage là một cách hiệu quả để bộ nhớ cache nội dung phức tạp cho dựng hình hiệu quả; CellTest là một ví dụ. Trình kết xuất đồ họa thừa, được hiển thị here, là một cách tiếp cận khác. Cuối cùng, tôi đã tái xác minh ví dụ hướng dẫn của bạn theo cách có thể làm cho thử nghiệm dễ dàng hơn.

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); 
      } 
     }); 
    } 
} 
Các vấn đề liên quan