やりたいこと:のサブクラスを
作成してJPanel
、含まれているコンポーネントの上に単純なオーバーレイを描画します。
なぜ私は使用しないのJLayeredPane
ですか?
を参照してくださいJComponent#isOptimizedDrawingEnabled()
。
JMenu
が に存在する場合、オーバーライドされたメソッドでJFrame
を追加すると、次のコード サンプルで見られるように、渡された Graphics オブジェクトで誤った座標の開始点が提供されます。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 の下) に描画されます。
2 番目の文字列は右下隅に描画されません。JMenu の高さによって押し上げられます。
それでも:
AWT がこのメソッドを呼び出すと、Graphics オブジェクト パラメーターは、この特定のコンポーネントで描画するための適切な状態で事前構成されます。
- Graphics オブジェクトの色は、コンポーネントの foreground プロパティに設定されます。
- Graphics オブジェクトのフォントは、コンポーネントの font プロパティに設定されます。
- Graphics オブジェクトの平行移動は、座標 (0,0) がコンポーネントの左上隅を表すように設定されます。
- Graphics オブジェクトのクリップ四角形は、再描画が必要なコンポーネントの領域に設定されます。
プログラムは、この Graphics オブジェクト (またはその派生オブジェクト) を使用して出力をレンダリングする必要があります。必要に応じて Graphics オブジェクトの状態を自由に変更できます。
私は何を間違っていますか?