【问题标题】:Missing JPanel in JLayeredPaneJLayeredPane 中缺少 JPanel
【发布时间】:2017-04-04 11:06:39
【问题描述】:

我正在为JPanel 制作叠加层,但我有一个小问题,叠加层的透明度直接看到JFrame

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class GUI extends JFrame {
    private GUI() {
        super("Recorder Part");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        setLayout(new BorderLayout());
        JLayeredPane layers = new Overlay();
        add(layers);

        pack();

        getContentPane().setBackground(Color.GREEN);
        setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new GUI());
    }

    private class Overlay extends JLayeredPane {
        JPanel base;
        JPanel overlay;

        private Overlay() {
            setPreferredSize(new Dimension(800, 100));

            createBase();
            createOverlay();

            add(base, new Integer(0));
            add(overlay, new Integer(1));
        }


        private void createBase() {
            base = new JPanel();
            base.setPreferredSize(new Dimension(800, 100));
            base.setBounds(0, 0, 800, 100);
            base.setBackground(Color.BLUE);
            base.setOpaque(true);

            base.add(new JLabel("Hello"));
        }

        private void createOverlay() {
            overlay = new JPanel();
            overlay.setPreferredSize(new Dimension(800, 100));
            overlay.setBounds(0, 0, 800, 100);
            overlay.setBackground(new Color(255, 0, 0, 0));
        }
    }
}

我该如何解决这个问题,以便当名为overlayJPanel 透明时,可以看到名为baseJpanel 而不是JFrame


编辑

我发现只有当覆盖面板的一个尺寸大于或等于基础面板的尺寸时才会出现此问题。这可以通过在这个例子中调整框架的大小来看到。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class GUI extends JFrame {
    private GUI() {
        super("Recorder Part");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        setLayout(new BorderLayout());
        JLayeredPane layers = new Overlay();
        add(layers);

        pack();

        getContentPane().setBackground(Color.GREEN);
        setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new GUI());
    }

    private class Overlay extends JLayeredPane {
        JPanel base;
        JPanel overlay;

        private Overlay() {
            addComponentListener(new Resize());
            setPreferredSize(new Dimension(800, 100));

            createBase();
            createOverlay();

            add(base, new Integer(0));
            add(overlay, new Integer(1));
        }


        private void createBase() {
            base = new JPanel();
            base.setLocation(0, 0);
            base.setBackground(Color.BLUE);
            base.setOpaque(true);

            base.add(new JLabel("Hello"));
        }

        private void createOverlay() {
            overlay = new JPanel();
            overlay.setLocation(0, 0);
            overlay.setSize(new Dimension(800, 100));
            overlay.setBackground(new Color(255, 0, 0, 128));
        }

        private class Resize extends ComponentAdapter {
            @Override
            public void componentResized(ComponentEvent e) {
                System.out.println("Resized");
                base.setSize(new Dimension(getParent().getWidth(), getParent().getHeight()));
            }
        }
    }
}

这是不可取的,因为覆盖面板需要与基本面板的尺寸完全相同。我将不胜感激。

【问题讨论】:

  • 你快了一分钟...

标签: java swing jpanel jlayeredpane


【解决方案1】:

我感觉这是一个错误。更改边界,使其不完全与基础重叠,看看会发生什么:

overlay.setBounds(0, 0, 799, 100); // or (1, 0, 800, 100)

可能是某种优化,比如如果一个组件被另一个组件完全遮挡,则忽略它,但不考虑优化中的透明度 [:-|

编辑

这绝对是问题所在 - JComponent 的paintChildren 会根据孩子完全被其他孩子遮挡的情况进行某种优化。

我找到了两种解决方案,第一种可能是正确的——将叠加层设置为不透明:

overlay.setOpaque(false);

它的缺点是根本没有使用背景颜色。

第二个更多的是一种解决方法 - 使 JLayeredPane 为 optimizeDrawingEnabled 返回 true,这将阻止 JComponent 执行此操作:

private class Overlay extends JLayeredPane {

    /// ...

    @Override
    public boolean isOptimizedDrawingEnabled() {
        return true;
    }
}

但不确定这样做可能会停止工作,所以我更喜欢第一个解决方案!

【讨论】:

  • 我自己也注意到了这一点。我在我的编辑中注意到了它。我目前正在使用它,但希望有人能解决它
  • 感谢您的帮助。我使用了第二个,因为它仍然可以让我拥有透明的背景颜色。这很棒:)
猜你喜欢
  • 1970-01-01
  • 2012-07-07
  • 2016-12-15
  • 2010-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多