我想做的事:
创建一个JPanel子类,在包含的组件之上绘制一个简单的叠加层.
我为什么不用JLayeredPane?
见JComponent#isOptimizedDrawingEnabled().
当a JMenu中存在a时JFrame,JPanel使用重写paintChildren(Graphics)方法添加a 时,在传递的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
}
}
}
Run Code Online (Sandbox Code Playgroud)
第一个字符串是在JPanel外部(在JMenu下)绘制的,即使两个坐标都是非负的.
第二个字符串未在右下角绘制.它被JMenu的高度推高了.
即使:
当AWT调用此方法时,Graphics对象参数已预先配置为在此特定组件上绘制的适当状态:
程序必须使用此Graphics对象(或从其派生的对象)来呈现输出.他们可以根据需要随意更改Graphics对象的状态.
我究竟做错了什么?
第一个字符串是在
JPanel(在JMenu)下面绘制的,即使两个坐标都是非负的.第二个字符串未在右下角绘制.它被推高了JMenu.
在这两种情况下,请注意,drawString()预计坐标来表示基线的String.在这种情况下,字体的上升和下降很有用.这可能是巧合,mb.getHeight()并且fm.getHeight()具有可比性.

@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, fm.getAscent());
final String s = "TEST BOTTOM/RIGHT";
// will be drawn noticeably above the bottom
g.drawString(s, getWidth() - fm.stringWidth(s),
getHeight() - fm.getDescent());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1128 次 |
| 最近记录: |