2016-05-26 19 views
1

Я пишу приложение, которое имеет слои (я использовал JLayeredPane), содержащий два основных слоя (JPanel s). Я переопределяю paintComponent метод Panel внизу (назовите его Карта), чтобы он рисовал карту, и метод paintComponent того, что находится наверху (назовите его selectionPanel), чтобы он рисовал выделение элемента.Как перекрасить только один слой слоев JLayeredPane?

Вот краткое описание структуры:

слои - | -selectionPanel (сверху) | -Map (в нижней части)

Я хочу Карта остаться статичным, т.е. не делать любая перекраска (кроме первоначальной), так как она не изменяется.

Проблема в том, что когда я вызываю selectionPanel.repaint(), Map также перекрашивается! Это определенно неэффективно.

Я думаю, что это связано с нетерпением окраски JLayeredPane. Есть ли способ отключить эту функцию в JLayeredPane?

В случае, если вы заинтересованы, чтобы увидеть выше эффект, я изменил этот example:

import java.awt.AlphaComposite; 
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); 
      color = new Color(r.nextInt()); 
      Graphics2D g2d = (Graphics2D) g; 
      g2d.setRenderingHint(
       RenderingHints.KEY_ANTIALIASING, 
       RenderingHints.VALUE_ANTIALIAS_ON); 
      g2d.setColor(color); 
      g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, ((float) 20)/100)); 
      g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 16, 16); 
      g2d.setColor(Color.black); 
      g2d.drawString(String.valueOf(n), 5, getHeight() - 5); 
     } 

    } 

    private static class MouseHandler extends MouseAdapter { 

     LayerPanel panel; 

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

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

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

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

Попробуйте [tag: jmapviewer]; также не удаляйте [атрибуция] (http://stackexchange.com/legal) из кода, который вы копируете. – trashgod

ответ

1

Есть ли способ отключить эту функцию в JLayeredPane?

Если это не функция JLayeredPane. Это качели.

this.setOpaque(false); 

Когда вы делаете компонент непрозрачной, то свинг нужно перекрашивать родительский компонент, чтобы убедиться, что фон окрашен должным образом.

В вашем случае похоже, что вы используете прозрачность, поэтому вам определенно понадобится перерисовать фон.

всякий раз, когда я называю selectionPanel.repaint(), карта получает перекрасили, а

Если вы только рисуя определенную область детской панели, то вы можете использовать:

selectionPanel.repaint(Rectangle) 

чтобы свести к минимуму площадь, которая была перекрашена.

color = new Color(r.nextInt()); 

Не изменяйте цвет в методе paintComponent(). Это должно быть сделано в MouseListener, так что это влияет только на панель, на которую вы нажимаете. Поэтому, даже если другие панели будут перекрашены, их цвета не будут изменяться случайным образом.