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?!皟灮L圖”意味著在某些情況下可能無法渲染某些子項。正如文檔所說:
如果此組件平鋪其子級,即,如果它可以保證子級不會重疊,則返回 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).
添加回答
舉報