为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

蛊毒传说 2021-12-10 10:07:36
JLayeredPane 如果两个组件大小相同且全屏,则不绘制低组件软件工作原理:JFrame <- APanel <- JLayeredPane <-(分层子组件)我的软件是全屏软件。APanel 是 BorderLayout 组件。JLayeredPane 是 APanel 中的 BorderLayout.CENTERPanel1 gp = new Panel1(); //Panel1 extends JPanelgp.setSize(jlp.getSize());jlp.add(gp);gp.initializeDisplay(); //starts repaint() loopjlp.setLayer(gp, 90);Panel2 lp = new Panel2(); //Panel2 extends JPanellp.setSize(jlp.getSize());lp.initializeDisplay();  //starts repaint() looplp.initializeComponents(); //Adds and moves componentsjlp.add(lp);jlp.setLayer(lp, 110);当我这样制作时,只Panel2显示。Panel1的paintComponent()这个样子的(只需绘制图像):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 herelp.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);如果您需要更多信息(例如代码),请添加评论。
查看完整描述

1 回答

?
交互式爱情

TA贡献1712条经验 获得超3个赞

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


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


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。“优化绘图”意味着在某些情况下可能无法渲染某些子项。正如文档所说:


如果此组件平铺其子级,即,如果它可以保证子级不会重叠,则返回 true。


当然,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.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);or just 时pane.add(l, 1);,它会调用add(Component comp, int index)而不是所需的add(Component comp, Object constraints).


查看完整回答
反对 回复 2021-12-10
  • 1 回答
  • 0 关注
  • 135 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信