我想要做的事:
創建一個JPanel
的子類,在包含的組件頂部繪製一個簡單的覆蓋圖。當JMenu存在時,JPanel#paintChildren(圖形)的行爲不正確?
爲什麼我不使用JLayeredPane
?
請參閱JComponent#isOptimizedDrawingEnabled()
。
當JMenu
存在於JFrame
,加入JPanel
與重寫paintChildren(Graphics)
方法,一個不正確的座標出發點是在通過圖形提供的對象,與此代碼示例觀察:
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public final class Sscce {
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
// a normal frame
JFrame f = new JFrame();
// set up a simple menu
JMenuBar mb = new JMenuBar();
JMenu m = new JMenu("Test");
JMenuItem mi = new JMenu("Whatever");
m.add(mi);
mb.add(m);
f.setJMenuBar(mb);
// a panel with a simple text overlay over components.
// works much faster than JLayeredPane, which doesn't have
// isOptimizedDrawingEnabled()
JPanel p = new JPanel() {
@Override
public void paint(Graphics g) {
// I'm not so stupid to draw stuff here
super.paint(g);
// JavaDoc: delegates to paintComponent, paintBorder, paintChildren
// in that order
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// it is common knowledge that children are painted after parent
Graphics tmp = g.create();
try {
tmp.setColor(Color.MAGENTA);
tmp.fillRect(0, 0, getWidth(), getHeight());
} finally {
tmp.dispose();
}
}
@Override
protected void paintChildren(Graphics g) {
super.paintChildren(g);
// draw some text
FontMetrics fm = g.getFontMetrics();
// will be drawn outside panel; under menu
g.drawString("TEST TOP/LEFT", 0 + getX(), 0 + getY());
final String s = "TEST BOTTOM/RIGHT";
// will be drawn noticeably above the bottom
g.drawString(s,
getWidth() - fm.charsWidth(s.toCharArray(), 0, s.length()),
getHeight() - fm.getHeight());
}
};
// add something to the panel
p.add(new JTextArea(10, 15));
f.add(p);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
});
} catch (Throwable t) {
// this is a SSCCE
}
}
}
的第一個字符串是在JPanel之外(在JMenu下)繪製的,儘管兩個座標都是非負的。
第二個字符串不在右下角繪製。它被JMenu的高度推高。
即使:
當AWT調用此方法,該圖形對象的參數是預先配置有適當的狀態該特定組件上繪製:
- Graphics對象的顏色設置爲組件的前景 屬性。
- Graphics對象的字體被設置爲組件的字體 屬性。
- 圖形對象的翻譯被設置爲使得座標(0,0)代表組件的左上角。
- Graphics對象的剪輯矩形設置爲需要重繪的 組件的區域。
程序必須使用此Graphics對象(或從它派生的)來呈現輸出。他們可以根據需要自由更改Graphics對象的狀態。
我在做什麼錯?
一個)看不到在所有的B在左上角的文本)的下角的文本是在相同的位置瓦特/輸出菜單欄c)中上述的文本textarea在打入該區域時被「塗滿」 - 總體上:簡單地不要在paintChildren中進行自定義繪畫;-)而是使用layeredPane,疊加布局或JLayer(jdk7)/ JXLayer(jdk6) – kleopatra 2012-08-13 08:19:23
@kleopatra右:左上角的字符串在原點處用基線繪製;只有下行可見,但沒有特定的字符串。我已經更新了我的答案。 – trashgod 2012-08-13 10:58:55