Действительно медленное получение метрик шрифта - PullRequest
4 голосов
/ 16 марта 2010

Итак, проблема в том, что я запускаю свое приложение, отображая простое меню. Для правильного определения размера и выравнивания текста мне нужно получить метрики шрифта, и я не могу найти способ сделать это быстро. Я протестировал свою программу, и похоже, что любой метод, который я использую для получения метрики шрифта, первый вызов занимает более 500 миллисекунд !? Из-за этого время запуска моего приложения намного больше, чем необходимо.

Я не знаю, зависит это от платформы или нет, но на всякий случай я использую Mac OS 10.6.2 на MacBook Pro (здесь не проблема с оборудованием).

Если вы знаете способ получения метрик шрифта быстрее, пожалуйста, помогите.

Я попробовал эти 3 метода для получения метрик шрифта, и первый вызов всегда очень медленный, независимо от того, какой метод я выбрал.

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

Ответы [ 2 ]

2 голосов
/ 01 ноября 2015

Хотя я не могу рассказать вам, как обойти саму проблему, вы можете использовать этот метод, чтобы точно решить, когда ее инициировать:

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

Это полезно, потому что вы можете поместить его в любом месте - так, например, вы можете сделать это, пока вы отображаете экран загрузки или что-то еще. Если вы используете Graphics объект во время paint(), то вы можете только инициализировать во время рендеринга.

EDIT:

Фактически это может быть уменьшено до:

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

(Медленная часть - это вызов getFont2D, а не конструктор Font.)

РЕДАКТИРОВАТЬ 2:

И, наконец, это можно уменьшить до:

sun.font.FontManagerFactory.getInstance();

Проблема в том, что этому одноэлементному классу требуется много времени для запуска, поскольку он перечисляет всех системных шрифтов.

РЕДАКТИРОВАТЬ 3:

Нет хорошего способа обойти эту проблему, если вы хотите использовать стандартную графическую систему.

1 голос
/ 16 марта 2010

Никакой реальной подсказки о том, почему это так медленно, но для метода 3, вы не должны сначала вызывать 'setFont'?

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

Скорость не имеет значения, хотя: - (

Кроме того, немного неэкономично создавать новый Font каждый раз, когда вызывается paint() (что часто случается), вы можете перенести это в свой конструктор. Но это не может быть проблемой, поскольку вы начинаете измерять время только после того, как шрифт создан.

...