java - 如何只重绘 JLayeredPane 图层中的一层?

标签 java swing jlayeredpane

我正在编写一个具有层(我使用JLayeredPane)的应用程序,其中包含两个主要层(JPanel)。我重写了底部 PanelpaintComponent 方法(称之为 Map),这样它就绘制了一个 Map,并且重写了 PanelpaintComponent 方法。一个位于顶部(称为选择面板),因此它绘制元素的选择。

以下是结构摘要:

层 - |-选择面板(顶部) |- map (底部)

我希望 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);
            }
        });
    }
}

最佳答案

Is there a way to disable this feature in JLayeredPane?

如果不是 JLayeredPane 功能。这是 Swing 绘画功能。

this.setOpaque(false);

当您将组件设置为非透明时,Swing 需要重新绘制父组件以确保正确绘制背景。

在您的情况下,您似乎正在使用透明度,因此您肯定需要重新绘制背景。

whenever I call selectionPanel.repaint(), Map gets repainted as well

如果您只绘制子面板的特定区域,那么您可以使用:

selectionPanel.repaint(Rectangle)

最小化重新绘制的区域。

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

不要在paintComponent()方法中更改颜色。这应该在 MouseListener 中完成,这样它只会影响您单击的面板。因此,即使其他面板将被重新绘制,它们的颜色也不会随机改变。

关于java - 如何只重绘 JLayeredPane 图层中的一层?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37458486/

相关文章:

java -++(new Integer(100));//错误

java - Android - 如何区分第一个指针和第二个指针在onTouchEvent中移动

java - java swing 中未找到列错误消息

java - 将 JLayeredPane 引入现有 JFrame

java - 使用JavaScript替代Java进行签名加密(DESede/CBC/PKCS5Padding)

java - Java如何通过编程将图片编码成视频文件?

java - JFrame 在小屏幕上显示不正确

java - 更改 Jframe 形状

java - Swing JLayeredPane 停止重新绘制所有图层

java - 组件分层 Java Swing,悬停时显示层