获取字体度量信息导致 StackOverflowError

5
运行以下代码:
import java.awt.Font;
import java.awt.FontMetrics;

public class MetricsTest {

    public static void main(String[] args) {
                Font myFontTest=new Font("Arial", Font.PLAIN, 11);
                FontMetrics metrics  = new FontMetrics(myFontTest) {};
                int characterWidth=metrics.charWidth('A');
                System.out.println(characterWidth);
    }
}

产生了这个错误:

Exception in thread "main" java.lang.StackOverflowError

在java.awt.FontMetrics.getWidths(FontMetrics.java:430)处

在java.awt.FontMetrics.charWidth(FontMetrics.java:333)处

在java.awt.FontMetrics.getWidths(FontMetrics.java:430)处

在java.awt.FontMetrics.charWidth(FontMetrics.java:333)处

在java.awt.FontMetrics.getWidths(FontMetrics.java:430)处

以此类推...

为什么会这样呢?


1
你不能只是创建一个 new FontMetrics,你需要从 某个地方 获取它。你没有在 EDT 中运行,也没有任何 Swing 组件 - 字体没有被渲染,那么它怎么能有宽度呢? - Boris the Spider
谢谢。它帮助我找到了解决方案。 - geo
3个回答

3

来自官方文档

提示给子类:由于这些方法中的许多形成了封闭的相互递归循环,所以您必须注意,在每个这样的循环中至少实现一个方法,以防止在使用您的子类时出现无限递归。特别是以下是建议的最小一组需要重写的方法,以确保正确性并防止无限递归(尽管其他子集同样可行):

意思是对于这篇文档提到的问题,为了避免无限递归,子类应该至少实现上述建议的方法之一。需要注意的是这些方法之间存在相互调用的情况。

FontMetrics metrics  = new FontMetrics(myFontTest) {};

定义了一个子类,但没有覆盖任何方法,因此您看到的是这种行为。


2
这里有一个解决方案:
(请参见用户Boris the Spider在我的原始帖子中的评论)
import java.awt.Canvas;
import java.awt.Font;
import java.awt.FontMetrics;

public class MetricsTest {

    public static void main(String[] args) {
                Font myFontTest=new Font("Arial", Font.PLAIN, 11);
                Canvas c = new Canvas();
                FontMetrics fm = c.getFontMetrics(myFontTest);
                int characterWidth=fm.charWidth('A');
                System.out.println(characterWidth);

    }

}

我的声誉还不够大,现在无法做这件事。我必须等到明天。 - geo

1
将你的代码重写为以下形式:
try {
    Font myFontTest=new Font("Arial", Font.PLAIN, 11);
    Frame f = new Frame();
    //FontMetrics metrics = f.getToolkit().getFontMetrics(myFontTest);      
    FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(myFontTest);

    int characterWidth=metrics.charWidth('A');
    System.out.println(characterWidth);
} catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

使用框架比使用画布更好吗?(请参见我的答案) - geo
根据文档,getToolkit().getFontMetrics(myFontTest)是一个已弃用的方法。但是,如果可用的话,我认为最好还是使用它。请参考canvas.getFontMetrics方法的文档。 - Visruth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接