2012-03-08 4 views
5

J'écris une application qui a un JLayeredPane (appelez-le couches) contenant deux JPanels dans différentes couches. Je remplace la méthode paintComponent du JPanel en bas (appelez-le grid_panel) donc il peint une grille, et la méthode paintComponent de celle en haut (appelez-la circuit_panel) afin qu'elle dessine un circuit.JLayeredPane et la peinture

Voici un résumé de la structure:

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

Je veux que le grid_panel de rester statique, à savoir, ne pas faire de repeindre (sauf celui initial) car elle ne change pas.

Le problème est, chaque fois que j'appelle circuit_panel.repaint(), grid_panel est également repeint! Ceci est certainement pas efficace.

Je pense que cela est dû au comportement de peinture impatient de JLayeredPane. Est-il possible de désactiver cette fonctionnalité dans JLayeredPane?

Si vous êtes intéressé à voir l'effet ci-dessus, j'ai écrit un petit programme de démonstration:

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

Je suis sûr que vous ne serez pas en mesure de contourner ce part peut-être le double buffering vos couches si cher à dessiner. Tout se résume à RepaintManager qui garde la trace des régions "sales", parce que les couches partagent le même espace à l'écran une peinture de l'une déclenchera le repeindre d'une autre ... Bonne chance. – Adam

+0

Y at-il un moyen pour JPanel de mettre en cache ce qu'il doit peindre (bien sûr, ce qui est peint doit être statique), et laisser repaint() de peindre le cache, au lieu de faire tous ces calculs encore et encore? – stackoverflower

+0

hehehe sur redimensionner aussi, avec un scintillement terrible +1, il doit y avoir un autre problème, mais êtes-vous capable d'utiliser [JLayer (depuis Java7)] (http://stackoverflow.com/a/9272534/714968) ou 'JXLayer (pour Java6) ' – mKorbel

Répondre

7

Comme vous l'avez trouvé, un BufferedImage est un moyen efficace de mettre en cache le contenu complexe pour un rendu efficace; CellTest est un exemple. Un moteur de rendu mouche, illustré here, est une autre approche. Enfin, j'ai ré-factorisé votre exemple instructif de manière à faciliter l'expérimentation.

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