java - 如果两个组件大小相同且全屏,JLayeredPane 不会绘制低组件

标签 java swing

JLayeredPane 如果两个组件大小相同且全屏,则不会绘制低组件

软件的工作原理:

JFrame <- APanel <- JLayeredPane <-(分层子组件)

  • 我的软件是全屏软件。
  • APanel 是 BorderLayout 组件。
  • JLayeredPane 是 APanel 中的 BorderLayout.CENTER
Panel1 gp = new Panel1(); //Panel1 extends JPanel
gp.setSize(jlp.getSize());
jlp.add(gp);
gp.initializeDisplay(); //starts repaint() loop
jlp.setLayer(gp, 90);

Panel2 lp = new Panel2(); //Panel2 extends JPanel
lp.setSize(jlp.getSize());
lp.initializeDisplay();  //starts repaint() loop
lp.initializeComponents(); //Adds and moves components
jlp.add(lp);
jlp.setLayer(lp, 110);

当我这样做时,只显示Panel2Panel1paintComponent() 看起来像这样(只需绘制图像):

g.drawImage(myImage, 0, 0, getWidth(), getHeight(), null);

Panel2 包含很多按钮和标签。 此方法解决了问题。

Panel1 gp = new Panel1();
gp.setSize(jlp.getSize());
jlp.add(gp);
gp.initializeDisplay();
jlp.setLayer(gp, 90);

Panel2 lp = new Panel2();
lp.setSize(jlp.getWidth() - 1, jlp.getHeight() - 1); //Changed here
lp.initializeDisplay();
lp.initializeComponents();
jlp.add(lp);
jlp.setLayer(lp, 110);

但是这个方法又会出现问题:

Dimension cs = new Dimension(jlp.getWidth() - 1, jlp.getHeight() - 1);
GrassPane gp = new GrassPane();
gp.setSize(cs);
jlp.add(gp);
gp.initializeDisplay();
jlp.setLayer(gp, 90);

LobbyPane lp = new LobbyPane(this);
lp.setSize(cs);
lp.initializeDisplay();
lp.initializeComponents();
jlp.add(lp);
jlp.setLayer(lp, 110);

如果您需要更多信息(例如代码),请添加评论。

最佳答案

当一个不透明组件与另一个组件重叠时,有意跳过绘制完全模糊的组件。当组件被错误地声明为不透明时,这只会成为一个问题。因此,当您实现自己的组件绘制透明图像时,它们应该实现返回 falseisOpaque() 方法。

有趣的是,我仍然可以使用以下代码重现透明组件的重绘问题:

JFrame f = new JFrame("Test");
JLayeredPane pane = f.getLayeredPane();
JButton b = new JButton("Normal Text");
b.setHorizontalTextPosition(SwingConstants.LEFT);
b.setBounds(20, 20, 300, 100);
JLabel l = new JLabel("Overlay");
l.setHorizontalTextPosition(SwingConstants.RIGHT);
l.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
l.setBounds(20, 20, 300, 100);
l.setOpaque(false);
pane.add(l);
pane.add(b);
f.setSize(350, 200);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);

这里,文本“Overlay”最初可能会出现,也可能不会出现,但是一旦按钮的其中一个属性发生变化(例如接收焦点或被点击),文本就会消失。

问题在于以下属性:

System.out.println(pane.isOptimizedDrawingEnabled());

将打印true。 “优化绘图”意味着某些子项在某些情况下可能无法渲染。如the documentation说:

Returns true if this component tiles its children -- that is, if it can guarantee that the children will not overlap.

当然,JLayeredPane永远不会平铺子级,而是将它们堆叠在一起,并且永远不能保证它们不会重叠。尽管如此,出于某种原因,Swing 开发人员决定实现以下逻辑:

private void validateOptimizedDrawing() {
    boolean layeredComponentFound = false;
    synchronized(getTreeLock()) {
        Integer layer;

        for (Component c : getComponents()) {
            layer = null;

            if(SunToolkit.isInstanceOf(c, "javax.swing.JInternalFrame") ||
                   (c instanceof JComponent &&
                    (layer = (Integer)((JComponent)c).
                                 getClientProperty(LAYER_PROPERTY)) != null))
            {
                if(layer != null && layer.equals(FRAME_CONTENT_LAYER))
                    continue;
                layeredComponentFound = true;
                break;
            }
        }
    }

    if(layeredComponentFound)
        optimizedDrawingPossible = false;
    else
        optimizedDrawingPossible = true;
}

因此,只要组件不是 JComponent 实例或没有 LAYER_PROPERTY 属性(在使用默认层(如上面的示例)时总是出现这种情况),尽管实际布局逻辑没有任何变化,但 Pane 决定优化绘制是可能的。

所以当我们改变时

pane.add(l);
pane.add(b);

Object myLayer = JLayeredPane.DEFAULT_LAYER+1;
pane.add(l, myLayer);
pane.add(b, myLayer);

问题将会消失,因为 System.out.println(pane.isOptimizedDrawingEnabled()); 现在将打印 false

小心自动装箱。当您使用 pane.add(l, JLayeredPane.DEFAULT_LAYER+1); 或只是 pane.add(l, 1); 时,它会调用 add (Component comp, int index) 而不是所需的 add(Component comp, Object Constraints)

关于java - 如果两个组件大小相同且全屏,JLayeredPane 不会绘制低组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53005928/

相关文章:

java - sendSimpeMessage 返回 500

java - 欧拉项目#10,java

java - 动态更改字体会导致某些组件出现问题

Java限制KeyListener更新

java - 运行我的模块化程序时,ModuleLayer 找不到我的资源,但它可以找到我的模块化 jar

java - Apache Commons 电子邮件和 UTF-8

基于 Java 的配置,带参数的 Autowiring bean

java - 制作带有菜单的弹出窗口

java - 由于 setOpaque(false) 方法,JPanel 不断被重新绘制

java - Android 点击按钮不改变背景颜色