Главная > Java сниппеты > Изменение размера текста с использованием FontMetrics

Тема Зацепин
268

Java-разработчик 🧩
406
1 минуту

Изменение размера текста с использованием FontMetrics

1 Введение 2 Пример получения размеров шрифта 3 Результат работы 4 Рамка вокруг строки 5 Ссылки

Добавлено : 29 Mar 2009, 10:31

Содержание

Введение

Предположим, что вы используете объект Graphics в Swing для вывода какого-либо текста. Ваша программа должна вывести две строки текста. Программа вызывает метод Graphics.drawString для вывода первой строки и вызывает его снова для вывода второй. Метод drawString требует указания координат X,Y начальной позиции текста. Для второй строки вы предположили, что добавление 8 к Y достаточно для выполнения работы. То есть, вы предположили, что высота символов равна примерно 8. Например, первая строка начинается с 100,100, вторая - с 100,108. Код программы выглядит примерно так:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class FmDemo1 {
public static void main(String args[]) {
JFrame frame = new JFrame("FmDemo1");

// обработать закрытие окна

frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
})
;

final JPanel panel = new JPanel();

// создать кнопку и добавить к ней
// перехватчик действий

JButton button = new JButton("Draw Text");
button.addActionListener
(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Graphics g = panel.getGraphics();

// вывести две строки текста

int BASE1 = 100;
int OFFSET1 = 8;
g.drawString
("LINE 1", 100, BASE1);
g.drawString
("LINE 2", 100, BASE1 + OFFSET1);

// вывести две строки текста,
// используя метрику шрифта

FontMetrics fm = g.getFontMetrics();
int BASE2 = 150;
int OFFSET2 = fm.getHeight();
g.drawString
("LINE 1", 100, BASE2);
g.drawString
("LINE 2", 100, BASE2 + OFFSET2);
}
})
;

panel.add
(button);

frame.getContentPane
().add(panel);
frame.setSize
(250, 250);
frame.setLocation
(300, 200);
frame.setVisible
(true);
}
}

Эта программа работает. Выберите кнопку Draw Text и вы увидите две строки текста, следующие после других двух строк. Обратите внимание, что первые две строки отображаются почти рядом. Проблема может быть решена изменением значения 8 на большее число, например, 18. Но такой подход упускает один момент. Если вы отображаете текст как часть набора графических операций, в вашей программе необходимо учитывать различные размеры шрифта. Другими словами, программа должна автоматически подстраивать себя в зависимости от размеров шрифтов, с которыми она имеет дело. Вы можете решить проблему изменением значения с 8 на 18 в примере FmDemo1, но вдруг вы будете работать с действительно большими шрифтами? В этом случае значения высоты 18 может быть недостаточно.

Пример получения размеров шрифта

Лучший подход продемонстрирован во второй группе операторов drawString в FmDemo1, которая отображает нижние две строки текста. Программа получает объект FontMetrics. Затем она вызывает метод getHeight обекта для получения значения высоты шрифта. Оно затем используется вместо фиксированных значений, таких как 8 или 18.

Чтобы увидеть, какая информация доступна, рассмотрим другой пример:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class FmDemo2 {
public static void main(String args[]) {
JFrame frame = new JFrame("FmDemo2");

// обработать закрытие окна

frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
})
;

// создать панель и установить ее шрифт

final JPanel panel = new JPanel();
Font f =
new Font("Monospaced", Font.ITALIC, 48);
panel.setFont
(f);

// создать кнопку и перехватчик
// действий для нее

JButton button = new JButton("Draw Text");
button.addActionListener
(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int XBASE = 50;
int YBASE = 100;
String test_string =
"hqQWpy`/\'|i\\,{_!^";

Graphics g = panel.getGraphics
();
FontMetrics fm = g.getFontMetrics
();

int ascent = fm.getAscent();
int descent = fm.getDescent();
int width = fm.stringWidth(test_string);

// отобразить текстовую строку

g.drawString(test_string, XBASE, YBASE);

// отобразить верхнюю линию

g.setColor(Color.red);
g
.drawLine
(XBASE, YBASE - ascent, XBASE + width, YBASE
- ascent
);

// отобразить основную линию

g.setColor(Color.green);
g.drawLine
(XBASE, YBASE, XBASE + width, YBASE);

// отобразить нижнюю линию

g.setColor(Color.blue);
g.drawLine
(XBASE, YBASE + descent, XBASE + width, YBASE
+ descent
);
}
})
;

panel.add
(button);

frame.getContentPane
().add(panel);
frame.setSize
(600, 250);
frame.setLocation
(250, 200);
frame.setVisible
(true);
}
}

Результат работы

Запустите эту программу и выберите кнопку Draw Text. Вы увидите строку текста с тремя цветными линиями над ней, внутри нее и под ней. Зеленая линия в середине является базовой линией. Это начальная точка для вычислений различных размеров шрифта. Когда Abstract Window Toolkit (AWT) рисует символ, точка отсчета X,Y для него расположена на левой границе символа и на базовой линии.

Красная линия сверху называется подъемом. Это расстояние от базовой линии к верхней границе большинства символов. Синяя линия называется спуском. Это расстояние от базовой линии к нижней границе большинства символов. Возможно, что некоторые символы будут иметь больший подъем или спуск. FontMetrics предоставляет методы getMaxAscent и getMaxDescent для получения максимальных значений для шрифта. Существует также свойство, называемое интерлиньяж, представляющее размер зарезервированного пустого места между спуском одной строки текста и подъемом следующей.

Программа FmDemo2 показывает также использование метода stringWidth, который вычисляет графическую ширину строки. Каждый символ шрифта имеет так называемую ширину опережения. Это позиция, с которой AWT должен разместить следующий символ после вывода текущего символа. Ширина опережения строки не обязательно равна сумме ширин ее символов, измеренных по отдельности, потому что ширины некоторых символов могут меняться в зависимости от контекста.

Рамка вокруг строки

Рассмотрим последний пример, показывающий как нарисовать ограничивающую рамку вокруг строки:

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;

public class FmDemo3 {
public static void main(String args[]) {
JFrame frame = new JFrame("FmDemo3");

// обработать закрытие окна

frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
})
;

// создать панель и установить для нее шрифт

final JPanel panel = new JPanel();
Font f =
new Font("Monospaced", Font.ITALIC, 48);
panel.setFont
(f);

JButton button =
new JButton("Draw Text");
button.addActionListener
(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int XBASE = 50;
int YBASE = 100;
String test_string =
"hqQWpy`/\'|i\\,{_!^";

Graphics g = panel.getGraphics
();
FontMetrics fm = g.getFontMetrics
();

// отобразить текстовую строку

g.drawString(test_string, XBASE, YBASE);

// нарисовать вокруг нее ограничивающую рамку

RectangularShape rs = fm.getStringBounds(test_string, g);
Rectangle r = rs.getBounds
();
g.setColor
(Color.red);
g.drawRect
(XBASE + r.x, YBASE + r.y, r.width, r.height);
}
})
;

panel.add
(button);

frame.getContentPane
().add(panel);
frame.setSize
(600, 250);
frame.setLocation
(250, 200);
frame.setVisible
(true);
}
}

В программе FmDemo3 используется метод getStringBounds для получения объекта RectangularShape. Затем программа вызывает getBounds для получения ограничивающей рамки, которая рисуется вокруг текста. Это полезно в тех случаях, когда вы пытаетесь расположить текст и графику вместе и хотите знать, сколько пространства занимает текст.

Ссылки

Дополнительная информация о измерении размеров текста с помощью FontMetrics находится в разделе "Font и FontMetrics" главы 4 книги "Графика в Java: освоение JFC, 3-е издание, том 1, AWT" David Geary (http://www.sun.com/books/catalog/Geary3/index.html).

Теги: fontswing

Еще от автора

Применение WeakHashmap для списков слушателей

В статье от 11мая 1999 года Reference Objects были описаны основные идеи применения ссылочных объектов, но не приводилось детального описания. Данная статья позволит вам получить больше сведений, касающихся данной темы. В основном ссылочные объекты применяются для косвенных ссылок на память необходимую объектам. Ссылочные объекты хранятся в очереди (класс ReferenceQueue), в которой отслеживается доступность ссылочных объектов. Исходя из типа ссылочного объекта, сборщик мусора может освобождать память даже тогда, когда обычные ссылки не могут быть освобождены.

Заставки в Mustang

Согласно определению, данному в Wikipedia, заставка - это компьютерный термин, обозначающий рисунок, появляющийся во время загрузки программы или операционной системы. Заставка для пользователя является визуальным отображением инициализации программы. До выхода версии Java SE 6 (кодовое название Mustang) единственной возможностью применения заставки было создание окна, во время запуска метода main, и размещение в нем картинки. Хотя данный способ и работал, но он требовал полной инициализации исполняемой Java среды до появления окна заставки. При инициализации загружались библиотеки AWT и Swing, таким образом, появление заставки задерживалось. В Mustang появился новый аргумент командной строки, значительно облегчающий использование заставок. Этот способ позволяет выводить заставку значительно быстрее до запуска исполняемой Java среды. Окончательное добавление данной функциональности находится на рассмотрении в JCP.

Совмещение изображений

1 Введение 2 Правила визуализации и пример 3 Совмещение изображений в оперативной памяти 4 Постепенное исчезновение изображения 5 Ссылки и дополнительная информация

Еще по теме

Применение WeakHashmap для списков слушателей

В статье от 11мая 1999 года Reference Objects были описаны основные идеи применения ссылочных объектов, но не приводилось детального описания. Данная статья позволит вам получить больше сведений, касающихся данной темы. В основном ссылочные объекты применяются для косвенных ссылок на память необходимую объектам. Ссылочные объекты хранятся в очереди (класс ReferenceQueue), в которой отслеживается доступность ссылочных объектов. Исходя из типа ссылочного объекта, сборщик мусора может освобождать память даже тогда, когда обычные ссылки не могут быть освобождены.

Заставки в Mustang

Согласно определению, данному в Wikipedia, заставка - это компьютерный термин, обозначающий рисунок, появляющийся во время загрузки программы или операционной системы. Заставка для пользователя является визуальным отображением инициализации программы. До выхода версии Java SE 6 (кодовое название Mustang) единственной возможностью применения заставки было создание окна, во время запуска метода main, и размещение в нем картинки. Хотя данный способ и работал, но он требовал полной инициализации исполняемой Java среды до появления окна заставки. При инициализации загружались библиотеки AWT и Swing, таким образом, появление заставки задерживалось. В Mustang появился новый аргумент командной строки, значительно облегчающий использование заставок. Этот способ позволяет выводить заставку значительно быстрее до запуска исполняемой Java среды. Окончательное добавление данной функциональности находится на рассмотрении в JCP.

Использование потоков

1 Введение 2 Работа с выражениями типа Boolean 3 Класс JoptionPane 4 Приложение-счетчик 5 Ссылки

Перехват необрабатываемых исключений

В статье от 16 марта 2004 года Best Practices in Exception Handling были описаны приемы обработки исключений. В данной статье вы изучите новый способ обработки исключений при помощи класса UncaughtExceptionHandler добавленного в J2SE 5.0.

Использование класса LinkedHashMap

1 Введение 2 Сортировка хэш-таблицы 3 Копирование таблицы 4 Сохранение порядка доступа к элементам 5 Ссылки

Сказ про кодировки и java

С кодировками в java плохо. Т.е., наоборот, все идеально хорошо: внутреннее представление строк – Utf16-BE (и поддержка Unicode была с самых первых дней). Все возможные функции умеют преобразовывать строку из маленького регистра в большой, проверять является ли данный символ буквой или цифрой, выполнять поиск в строке (в том числе с регулярными выражениями) и прочее и прочее. Для этих операций не нужно использовать какие-то посторонние библиотеки вроде привычных для php mbstring или iconv. Как говорится, поддержка многоязычных тестов “есть в коробке”. Так откуда берутся проблемы? Проблемы возникают, как только строки текста пытаются “выбраться” из jvm (операции вывода текста различным потребителям) или наоборот пытаются в эту самую jvm “залезть” (операция чтения данных от некоторого поставщика).