如何在Java中创建自定义文本组件?我需要提供getPreferredSize()
,我应该在其中测量我的文本结构。但是,如果没有先获得Graphics
,我就无法衡量文字指标。但是如果没有首先绘制组件,我就无法获得Graphics
。但是,如果不首先测量它,我就无法绘制成分。
如何打破这种恶性循环?
示例代码
public class Text_CustomTextual {
public static class JHelloWorld extends JComponent {
private final String content = "Hello world!";
private final Font font = new Font(Font.SERIF, Font.PLAIN, 12);
private Dimension dim = null;
private FontMetrics fm;
@Override
public Dimension getPreferredSize() {
// I can't measure control until I paint it once
if( dim == null ) {
return new Dimension(300,5);
}
// I can measure it only after it was painter at least once
else {
return dim;
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(font);
// this is branch for first paint where I can measure control
if( dim == null ) {
// why should I have Graphics to measure font???
fm = g.getFontMetrics();
// why should I feed Graphics to getStringBound method???
// did FontMetrics already forgot one I constructed it with???
Rectangle2D rect = fm.getStringBounds(content, g);
dim = new Dimension((int)rect.getWidth(),(int)rect.getHeight());
// how to cause control size to be reevaluated?
// repaint() does not help, control remains 300x5
repaint();
}
else {
g.setColor(getForeground());
g.drawString(content, 0, fm.getAscent());
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final JHelloWorld h = new JHelloWorld();
final JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(h);
f.pack();
f.setTitle(String.format("%dx%d", h.getWidth(), h.getHeight()));
h.addComponentListener(new ComponentListener() {
@Override
public void componentShown(ComponentEvent e) {
}
@Override
public void componentResized(ComponentEvent e) {
f.setTitle(String.format("%dx%d", h.getWidth(), h.getHeight()));
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentHidden(ComponentEvent e) {
}
});
f.setVisible(true);
}
});
}
}
答案 0 :(得分:0)
通常,首选大小不是动态设置的。 但是,作为提示使用的首选尺寸:
String text = "Hello world!";
Font font = new Font(Font.SERIF, Font.PLAIN, 12);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
BufferedImage bufferedImage = new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = ge.createGraphics(bufferedImage);
FontRenderContext frc = g2d.getFontRenderContext();
GlyphVector glyphVector = font.createGlyphVector(frc, text);
Rectangle2D rectangle2D = glyphVector.getLogicalBounds();
double w = rectangle2D.getWidth();
double h = rectangle2D.getHeight();
System.out.println("width = "+w+"\theight = "+h);