gpt4 book ai didi

java - 存在 JMenu 时 JPanel#paintChildren(Graphics) 的行为不正确?

转载 作者:搜寻专家 更新时间:2023-11-01 01:55:08 25 4
gpt4 key购买 nike

我想做的事:
创建一个 JPanel 的子类以在包含的组件之上绘制一个简单的覆盖层。

为什么我不用JLayeredPane
参见 JComponent#isOptimizedDrawingEnabled()

JMenu 出现在 JFrame 中时,添加一个带有覆盖的 paintChildren(Graphics)JPanel方法中,在传递的 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 的高度向上推。

Image

虽然:

当 AWT 调用这个方法时,Graphics 对象参数被预先配置为在这个特定组件上绘制的适当状态:

  • Graphics 对象的颜色设置为组件的前景属性(property)。
  • Graphics 对象的字体设置为组件的字体属性(property)。
  • Graphics 对象的翻译设置为坐标(0,0)表示组件的左上角。
  • Graphics 对象的剪辑矩形设置为需要重新绘制的组件。

程序必须使用此 Graphics 对象(或派生自它的对象)来呈现输出。他们可以根据需要自由更改 Graphics 对象的状态。

我做错了什么?

最佳答案

The first string is drawn outside of JPanel (under the JMenu), even though both coordinates are non-negative. The second string is NOT drawn at the bottom right corner. It is pushed up by the height of the JMenu.

在这两种情况下,请注意 drawString() 期望坐标表示 baseline 字符串。字体的上升和下降在这种情况下很有用。 mb.getHeight()fm.getHeight() 的大小相当可能是巧合。

enter image description here

@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());
}

关于java - 存在 JMenu 时 JPanel#paintChildren(Graphics) 的行为不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11922771/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com