Как я могу перекрасить только один слой слоев JLayeredPane?

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

Вот краткое изложение структуры:

слои - |-selectionPanel (вверху) |-Map (внизу)

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

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

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

Если вам интересно увидеть описанный выше эффект, я изменил этот пример:

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

person Aguid    schedule 26.05.2016    source источник
comment
Попробуйте jmapviewer; также не удаляйте атрибуцию из кода, который вы копируете.   -  person trashgod    schedule 26.05.2016


Ответы (1)


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

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

this.setOpaque(false);

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

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

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

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

selectionPanel.repaint(Rectangle)

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

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

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

person camickr    schedule 26.05.2016