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

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

Java-разработчик 🧩
577
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 Ссылки

Еще по теме

Гибкое журналирование с помощью log4j

Log4j – это инструмент для журналирования с открытым исходным кодом, разработанный под эгидой глобального проекта Jakarta Apache. Он представляет собой набор API с помощью которых, разработчики могут вставлять в свой код выражения, которые выводят некоторую информацию (отладочную, информационную, сообщения об ошибках и т.д.), и конфигурировать этот вывод с помощью внешний конфигурационных файлов. В этой статье рассматриваются основные идеи, положенные в данный инструмент, а также будут затронуты некоторые интересные моменты, касающиеся написания демонстрационного web-приложения.

Аннотации в Java (java annotation types). Пример 1

Продолжаю серию статей о нововведениях в Java (начиная с версии 1.5). На этот раз разговор пойдет об аннотациях (annotation type).

Указатели и виртуальные функции в Java

В настоящее время в Интернете можно найти множество статей как о перспективности платформы Java, так и об её ограниченности. Многих программистов, только присматривающихся к Яве, могут отпугнуть частые заявления, типа: «низкое быстродействие», «отсутствие указателей» и т.д.

Блокировки

Одной из популярных функциональных возможностей библиотек J2SE 5.0 является добавление средств обеспечения параллельной работы. Предоставленные как часть JSR 166 эти средства обеспечивают развитые возможности программирования параллельных процессов, устраняющие необходимость использования разработчиками ключевого слова synchronized и связанных с ним блокировок. Среди предлагаемых ими функциональных возможностей присутствуют: поддержка блокировочных таймаутов, множественные переменные условия для одной блокировки, блокировки чтения/записи и способность прерывать поток, ожидающий снятия блокировки. Более подробную информацию по дополнительной поддержке блокировок можно найти в документации по пакету java.util.concurrent.locks.