简体   繁体   English

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

[英]JLayeredPane not painting low component if both components are same size and full screen

JLayeredPane not painting low component if both components are same size and full screen如果两个组件大小相同且全屏,则JLayeredPane不会绘制低组件

How software works:软件工作原理:

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

  • My software is full screen software.我的软件是全屏软件。
  • APanel is BorderLayout component. APanel 是 BorderLayout 组件。
  • JLayeredPane is BorderLayout.CENTER in APanel 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);

When I make like this, only Panel2 is displayed.当我这样做时,只显示Panel2 Panel1 's paintComponent() looks like this (Just draw image): Panel1paintComponent()看起来像这样(只需绘制图像):

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

Panel2 contains a lot of buttons and labels. Panel2包含很多按钮和标签。 This method fixes the problem.这个方法解决了这个问题。

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

But this method causes problem again:但是这种方法又引起了问题:

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

Please add a comment if you need some more info such as codes.如果您需要更多信息(例如代码),请添加评论。

When an opaque component overlaps another, it is intentional to skip painting completely obscured components.当一个不透明组件与另一个组件重叠时,有意跳过绘制完全模糊的组件。 This can only become a problem, when component wrongly declared to be opaque.当组件被错误地声明为不透明时,这只会成为一个问题。 So when you implement your own components painting a transparent image, they should implement the isOpaque() method returning false .因此,当您实现自己的组件绘制透明图像时,它们应该实现返回falseisOpaque()方法。

Interestingly, I still could reproduce a repainting problem with transparent components using the following code:有趣的是,我仍然可以使用以下代码重现透明组件的重绘问题:

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

Here, the text “Overlay” may or may not appear initially, but as soon as one of the button's properties change (eg receiving the focus or getting clicked), the text will disappear.在这里,文本“Overlay”最初可能会也可能不会出现,但是一旦按钮的属性之一发生变化(例如接收焦点或被点击),文本就会消失。

The problem lies in the following property:问题在于以下属性:

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

will print true .将打印true And “optimized drawing” means that some of the children might not get rendered in certain situations. “优化绘图”意味着在某些情况下可能无法渲染某些子项。 As the documentation says:正如文档所说:

Returns true if this component tiles its children -- that is, if it can guarantee that the children will not overlap.如果此组件平铺其子组件,则返回 true - 也就是说,如果它可以保证子组件不会重叠。

Of course, JLayeredPane will never tile the children, but stack them on top of each other and can never guaranty that they won't overlap.当然, JLayeredPane永远不会平铺子项,而是将它们堆叠在一起,并且永远不能保证它们不会重叠。 Still, for some reason, the Swing developers decided to implement the following logic:尽管如此,出于某种原因,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;
}

So whenever the components are not JComponent instances or don't have the LAYER_PROPERTY property, which is always the case when using the default layer like the above example, the pane decides that optimized paint was possible, despite nothing in the actual layout logic changed.因此,每当组件不是JComponent实例或没有LAYER_PROPERTY属性时(在使用上述示例中的默认图层时总是如此),尽管实际布局逻辑中没有任何更改,窗格LAYER_PROPERTY决定优化绘制是可能的。

So when we change所以当我们改变

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

to

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

the problem will disappear, as System.out.println(pane.isOptimizedDrawingEnabled());问题会消失,因为System.out.println(pane.isOptimizedDrawingEnabled()); will print false now.现在将打印false

Beware of the autoboxing.小心自动装箱。 When you are using pane.add(l, JLayeredPane.DEFAULT_LAYER+1);当您使用pane.add(l, JLayeredPane.DEFAULT_LAYER+1); or just pane.add(l, 1);或只是pane.add(l, 1); , it would call add(Component comp, int index) instead of the desired add(Component comp, Object constraints) . ,它将调用add(Component comp, int index)而不是所需的add(Component comp, Object constraints)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM