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).
添加回答
举报