【问题标题】:Really slow obtaining font metrics获取字体指标真的很慢
【发布时间】:2011-01-28 03:05:13
【问题描述】:

所以我遇到的问题是我通过显示一个简单的菜单来启动我的应用程序。要正确调整和对齐文本的大小,我需要获取字体指标,但我找不到快速完成的方法。我测试了我的程序,它看起来像我用来获取字体度量的任何方法,第一次调用需要超过 500 毫秒!?因此,启动我的应用程序所需的时间比必要的要长得多。

我不知道它是否特定于平台,但以防万一,我在 MacBook Pro 上使用 Mac OS 10.6.2(这里硬件不是问题)。

如果您知道更快获取字体指标的方法,请提供帮助。

我尝试了这三种获取字体度量的方法,但无论我选择哪种方法,第一次调用总是很慢。

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;

import javax.swing.JFrame;

public class FontMetricsTest extends JFrame {
 public FontMetricsTest() {
  setVisible(true);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 }

 @Override
 public void paint(Graphics g) {
  Graphics2D g2 = (Graphics2D) g;

  Font font = new Font("Dialog", Font.BOLD, 10);
  long start = System.currentTimeMillis();

  FontMetrics fontMetrics = g2.getFontMetrics(font);
//  LineMetrics fontMetrics1 =
//     font.getLineMetrics("X", new FontRenderContext(null, false, false));
//  FontMetrics fontMetrics2 = g.getFontMetrics();

  long end = System.currentTimeMillis();
  System.out.println(end - start);
  g2.setFont(font);
 }

 public static void main(String[] args) {
  new FontMetricsTest();
 }
}

【问题讨论】:

  • 程序第一次运行有 0.6 秒,下次运行有大约 20 毫秒(WinXP、JDK 1.6.0_18)。那么可能与磁盘缓存中的字体文件有关?
  • 可能是与连接字体服务器有关的问题? (我听说有一个小程序会杀死运行字体服务器的机器(两台 Solaris 机器),但那是十多年前的事了。)我放入缓存以彻底清除问题,尽管我猜这不会发生如果图形对象可能应用了变换,那么效果会很好。
  • (哦,还有一个用于Font 的缓存。您可以在API 文档中看到他们有finalize 但没有dispose...)

标签: java performance swing font-size


【解决方案1】:

没有真正的线索为什么它这么慢,但是对于方法 3,你不应该先调用 'setFont' 吗?

public void paint(Graphics g) {
    g.setFont(font);
    FontMetrics fm = g.getFontMetrics();
}

但在速度方面并没有什么不同:-(

此外,每次调用 paint() 时创建一个新的 Font 有点不经济(这种情况经常发生),您可以将其移至构造函数。但这不是问题所在,因为您只有在创建字体后才开始测量时间。

【讨论】:

    【解决方案2】:

    虽然我无法告诉您如何解决问题本身,但您可以使用此方法来确定何时启动它:

    new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY).createGraphics().getFontMetrics();
    

    这很有用,因为您可以将其放在任何地方 - 例如,您可以在显示加载屏幕或其他内容时执行此操作。如果您在paint() 期间使用Graphics 对象,那么您只能在渲染时进行初始化。

    编辑:

    其实这可以简化为:

    FontUtilities.getFont2D(new Font("Dialog", 0, 12));
    

    (慢的部分是getFont2D 调用,而不是Font 构造函数。)

    编辑 2:

    最后,这可以简化为:

    sun.font.FontManagerFactory.getInstance();
    

    问题是这个单例类需要很长时间才能启动,因为它枚举了所有的系统字体。

    编辑 3:

    如果您想使用标准图形系统,则没有解决此问题的好方法。

    【讨论】:

    • 这对我有用,但我必须使用getFont2D:我在FontManagerFactory.getInstance 上测试了90ms,然后在getFont2D 我的特定字体上测试了2700ms(系统中缺少该字体)。
    猜你喜欢
    • 2014-10-14
    • 1970-01-01
    • 1970-01-01
    • 2017-11-10
    • 2010-12-28
    • 2013-01-25
    • 1970-01-01
    • 2012-01-30
    • 1970-01-01
    相关资源
    最近更新 更多