47615 (597347), страница 2
Текст из файла (страница 2)
Вернемся к методам класса Graphics. Несколько методов вычерчивают фигуры, залитые текущим цветом: fillRect(), fill3DRect(), fillArc(), fillOval(), fillPolygon(), fillRoundRect(). У них такие же аргументы, как и у соответствующих методов, вычерчивающих незаполненные фигуры.
Например, если вы хотите изменить цвет фона области рисования, то установите новый текущий цвет и начертите им заполненный прямоугольник величиной во всю область:
public void paint(Graphics g)(
Color initColor = g.getColor(); // Сохраняем исходный цвет
g.setColor(new Color(0, 0, 255)); // Устанавливаем цвет фона
// Заливаем область рисования
g.fillRect(0, 0, getSize().width-1, getSize().height-1);
g.setColor(initColor); // Восстанавливаем исходный цвет
// Дальнейшие действия
}
Как видно, в классе Graphics собраны только самые необходимые средства рисования. Нет даже метода, задающего цвет фона (хотя можно задать цвет фона компонента методом setBackground() класса Сomponent). Средства рисования, вывода текста в область рисования и вывода изображений значительно дополнены и расширены в подклассе Graphics2D, входящем в систему Java 2D. Например, в нем есть метод задания цвета фона setBackground(Color с).
Перед тем как обратиться к классу Graphics2D, рассмотрим средства класса Graphics для вывода текста.
Как вывести текст
Для вывода текста в область рисования текущим цветом и шрифтом, начиная с точки (х, у), в, классе Graphics есть несколько методов:
-
drawString (String s, int x, int y) — выводит строку s;
-
drawBytes(byte[] b, int offset, int length, int x, int у) — выводит length элементов массива байтов b, начиная с индекса offset;
-
drawChars(char[] ch, int offset, int length, int x, int у) — выводит length элементов массива символов ch, начиная с индекса offset.
Четвертый метод выводит текст, занесенный в объект класса, реализующего интерфейс AttributedCharacterIterator. Это позволяет задавать свой шрифт для каждого выводимого симвбла:
-
drawString(AttributedCharacterIterator iter, int x, int y).Точка (х, у) — это левая нижняя точка первой буквы текста на базовой линии (baseline) вывода шрифта.
Как установить шрифт
Метод setFont(Font newFont) класса Graphics устанавливает текущий шрифт для вывода текста.
Метод getFont () возвращает текущий шрифт.
Как и все в языке Java, шрифт — это объект класса Font. Посмотрим, какие возможности предоставляет этот класс.
Как задать шрифт
Объекты класса Font хранят начертания (glyphs) символов, образующие шрифт. Их можно создать двумя конструкторами:
-
Font (Map attributes) — задает шрифт с заданными аргументом attributes атрибутами. Ключи атрибутов и некоторые их значения задаются константами класса TextAttnbute из пакета java.awt.font. Этот конструктор характерен для Java 2D и будет рассмотрен далее.
-
Font (String name, int style, int size) — задает шрифт по имени name, со стилем style и размером size типографских пунктов. Этот конструктор характерен для JDK 1.1, но широко используется и в Java 2D в силу своей простоты.
Типографский пункт в России и некоторых европейских странах равен 0,376 мм, Точнее, 1/72 части французского дюйма. В англо-американской системе мер пункт равен 1/72 части английского дюйма, 0,351 мм. Этот-то пункт и применяется в компьютерной графике.
Имя шрифта name может быть строкой с физическим именем шрифта, например, "Courier New", или одна из строк "Dialog", "Dialoglnput",' "Monospaced", "Serif", "SansSerif", "Symbol". Это так называемые логические имена шрифтов (logical font names). Если name == null, то задается шрифт по умолчанию.
Стиль шрифта style — это одна из констант класса Font:
-
BOLD — полужирный;
-
ITALIC — курсив;
-
PLAIN — обычный.
Полужирный курсив (bolditalic) можно задать операцией побитового сложения, Font. BOLD | Font. ITALIC.
При выводе текста логическим именам шрифтов и стилям сопоставляются физические имена шрифтов (font face name) или имена семейств шрифтов (font name). Это имена реальных шрифтов, имеющихся в графической подсистеме операционной системы.
Например, логическому имени "Serif" может быть сопоставлено имя семейства (family) шрифтов Times New Roman, а в сочетании со стилями — конкретные физические имена Times New Roman Bold, Times New Roman Italic. Эти шрифты должны находиться в составе шрифтов графической системы той машины, на которой выполняется приложение.
Список имен доступных шрифтов можно просмотреть следующими операторами:
Font[] fnt = Toolkit.getGraphicsEnvironment.getAHFonts();
for (int i = 0; i< fnt.length; i++)
System.out.println(fnt[i].getFontName());
В состав SUN J2SDK входит семейство шрифтов Lucida. Установив SDK, вы можете быть уверены, что эти шрифты есть в вашей системе.
Таблицы сопоставления логических и физических имен шрифтов находятся в файлах с именами
-
font.properties;
-
font.properties.ar;
-
font.properties.ja;
-
font.properties.ru.
и т. д. Эти файлы должны быть расположены в JDK в каталоге jdkl.3\jre\lib или каком-либо Другом подкаталоге lib корневого каталога JDK той машины, на которой выполняется приложение.
Нужный файл выбирается виртуальной машиной Java по окончании имени файла. Это окончание совпадает с международным кодом языка, установленного в локали или в системном свойстве user.language. Если у вас установлена русская локаль с международным кодом языка "ru", то для сопоставления будет выбран файл font.properties.ru. Если такой файл не найден, то применяется файл font.properties, не соответствующий никакой конкретной локали.
Итак, собираясь выводить строку str в графический контекст методом drawString(), мы создаем текущий шрифт конструктором класса Font, указывая в нем логическое имя шрифта, например, "Serif". Исполняющая система Java отыскивает в файле font.properties, соответствующем локальному языку, сопоставленный этому логическому имени физический шрифт операционной системы, например, Times New Roman. Если это Unicode-шрифт, то из него извлекаются начертания символов строки str по их кодировке Unicode и отображаются в графический контекст.
При выводе строки в окно приложения очень часто возникает необходимость расположить ее определенным образом относительно других элементов изображения: центрировать, вывести над или под другим графическим объектом. Для этого надо знать метрику строки: ее высоту и ширину. Для измерения размеров отдельных символов и строки в целом разработан класс FontMetrics.
В Java 2D класс FontMetrics заменен классом TextLayout. Его мы рассмотрим в конце этого приложения, а сейчас выясним, какую пользу можно извлечь из методов класса FontMetrics.
Класс FontMetrics
Класс FontMetrics является абстрактным, поэтому нельзя воспользоваться его конструктором. Для получения объекта класса FontMetrics, содержащего набор метрических характеристик шрифта f, надо обратиться к методу getFontMetrics (f) класса Graphics или класса Component.
Класс FontMetrics позволяет узнать ширину отдельного символа ch в пикселах методом charWidth(ch), общую ширину всех символов массива или полмассива символов или байтов методами getChars() и getBytes(), ширину целой строки str в пикселах методом stringWidth(str).
Несколько методов возвращают в пикселах вертикальные размеры шрифта.
Интерлиньяж (leading) — расстояние между нижней точкой свисающих элементов таких букв, как р, у и верхней точкой выступающих элементов таких букв, как б, в следующей строке — возвращает метод getLeading().
Среднее расстояние от базовой линии шрифта до верхней точки прописных букв и выступающих элементов той же строки (ascent) возвращает метод getAscent(), а максимальное — метод getMaxAscent().
Среднее расстояние свисающих элементов от базовой линии той же строки (descent) возвращает метод getDescent(), а максимальное — метод getMaxDescent().
Наконец, высоту шрифта (height) — сумму ascent + descent + leading — возвращает метод getHeight(). Высота шрифта равна расстоянию между базовыми линиями соседних строк.
Эти элементы показаны на рис. 1.
Рис. 1. Элементы шрифта
Дополнительные характеристики шрифта можно определить методами класса LineMetrics из пакета java.awt.font. Объект этого класса можно получить несколькими методами getLineMetrics () класса FontMetrics.
Пример 1 показывает применение графических примитивов и шрифтов, а рис. 2 — результат выполнения программы из этого примера.
Пример 1. Использование графических примитивов и шрифтов
import java.awt.*;
import j ava.awt.event.*;
class GraphTest extends Frame{
GraphTest(String s) {
super(s);
setBounds(0, 0, 500, 300);
setVisible(true);
}
public void paint(Graphics g){
Dimension d = getSize();
int dx=d.width/20, dy=d.height/20;
g.drawRect(dx, dy+20, d.width-2*dx, d.height-2*dy-20);
g.drawRoundRect(2*dx, 2*dy+20, d.width-4*dx, d.height-4*dy-20, dx, dy);
g.fillArctd.width (2-dx, d.height-2*dy+1, 2*dx, dy-1, 0, 360);
g.drawArctd.width (2-3*dx, d.height-3*dy/2-5, dx, dy/2, 0, 360);
g.drawArctd.width (2+2*dx, d.height-3*dy/2 - 5, dx, dy/2, 0, 360);
Font fl = new Font("Serif", Font.BOLD(Font.ITALIC, 2*dy);
Font f2 = new Font ("Serif", Font.BOLD, 5*dy/2);
FontMetrics fml = getFontMetrics(fl);
FontMetrics fm2 = getFontMetrics(f2);
String s1 = "Всякая последняя ошибка";
String s2 = "является предпоследней.";
String s3 = "Закон отладки";
int firstLine = d.height/3;
int nextLine = fml.getHeight();
int secondLine = firstLine+nextLine/2;
g.setFont(f2);
g.drawstring(s3, (d.width-fm2.stringWidth(s3))/2, firstLine);
g.drawLine(d.width/4, secondLine-2, 3*d.width/4, secondLine-2);
g.drawLine(d.width/4, secondLine—1, 3*d.width/4, secondLine-1);
g.drawLine(d.width/4, secondLine, 3*d.width/4, secondLine);
g.setFont(fl);
g.drawstring(s1,(d.width-fml.stringWidth(s1))/2, firstLine+2*nextLine);
g.drawString(s2,(d.width-fml.stringWidth(s2))/2, firstLine+3*nextLine);
}
public static void main(String[] args){
GraphTest f = new GraphTest("Пример рисования");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev){
System.exit(0);
}
});
}
}
В примере 1 использован простой класс Dimension, главная задача которого — хранить ширину и высоту прямоугольного объекта в своих полях width и height. Метод getSize() класса component возвращает размеры компонента в виде объекта класса Dimension. В программе 1 размеры компонента f типа GrapTest установлены в конструкторе методом setBounds() равными 500x300 пикселов.
Еще одна особенность примера 1 — для вычерчивания толстой линии, отделяющей заголовок от текста, пришлось провести три параллельные прямые на расстоянии один пиксел друг от друга.
Рис. 2. Пример использования класса Graphics
Как вы увидели из обзора класса Graphics и сопутствующих ему классов, средства рисования и вывода текста в этом классе весьма ограничены. Линии можно проводить только сплошные и только толщиной в один пиксел, текст выводится только горизонтально и слева направо, не учитываются особенности устройства вывода, например, разрешение экрана.
Эти ограничения можно обойти разными хитростями: чертить несколько параллельных линий, прижатых друг к другу, как в примере 1, или узкий заполненный прямоугольник, выводить текст по одной букве, получить разрешение экрана методом getScreenSize() класса Java.awt.Toolkit и использовать его в дальнейшем. Но все это затрудняет программирование, лишает его стройности и естественности.
В Java 2 класс Graphics, в рамках системы Java 2D, значительно расширен классом Graphics2D.
Возможности Java 2D
В систему пакетов и классов Java 2D, основа которой— класс Graphics2D пакета java.awt, внесено несколько принципиально новых положений:
-
Кроме координатной системы, принятой в классе Graphics и названной координатным пространством пользователя (User Space), введена еще система координат устройства вывода (Device Space): экрана монитора, принтера. Методы класса Graphics2D автоматически переводят (transform) систему координат пользователя в систему координат устройства при выводе графики.
-
Преобразование координат пользователя в координаты устройства можно задать "вручную", причем преобразованием способно служить любое аффинное преобразование плоскости, в частности, поворот на любой угол и/или сжатие/растяжение. Оно определяется как объект класса AffineTransform. Его можно установить как преобразование по умолчанию методом setTransform(). Возможно выполнять преобразование "на лету" методами transform() и translate() и делать композицию преобразований методом concatenate().
-
Поскольку аффинное преобразование вещественно, координаты задаются вещественными, а не целыми числами.
-
Графические примитивы: прямоугольник, овал, дуга и др., реализуют теперь новый интерфейс shape пакета java.awt. Для их вычерчивания можно использовать новый единый для всех фигур метод draw(), аргументом которого способен служить любой объект, реализовавший интерфейс shape. Введен метод fill(), заполняющий фигуры— объекты класса, реализовавшего интерфейс shape.
-
Для вычерчивания (Stroke) линий введено понятие пера (реn). Свойства пера описывает интерфейс Stroke. Класс BasicStroke реализует этот интерфейс. Перо обладает четырьмя характеристиками:
-
оно имеет толщину (width) в один (по умолчанию) или несколько пикселов;
-
оно может закончить линию (end cap) закруглением — статическая константа CAP_ROUND, прямым обрезом — CAP_SQUARE (по умолчанию), или не фиксировать определенный способ окончания — CAP_BUTT;
-
оно может сопрягать линии (line joins) закруглением — статическая константа JOIN_ROOND, отрезком прямой — JOIN_BEVEL, или просто состыковывать — JOIN_MITER (по умолчанию);
-
оно может чертить линию различными пунктирами (dash) и штрих-пунктирами, длины штрихов и промежутков задаются в массиве, элементы массива с четными индексами задают длину штриха, с нечетными индексами — длину промежутка между штрихами.
-
Методы заполнения фигур описаны в интерфейсе Paint. Три класса реализуют этот интерфейс. Класс Color реализует его сплошной (solid) заливкой, класс GradientPaint — градиентным (gradient) заполнением, при котором цвет плавно меняется от одной заданной точки к другой заданной точке, класс TexturePaint — заполнением по предварительно заданному образцу (pattern fill).
Буквы текста понимаются как фигуры, т. е. объекты, реализующие интерфейс shape, и могут вычерчиваться методом draw() с использованием всех возможностей этого метода. При их вычерчивании применяется перо, все методы заполнения и преобразования.
Кроме имени, стиля и размера, шрифт получил много дополнительных атрибутов, например, преобразование координат, подчеркивание или перечеркивание текста, вывод текста справа налево. Цвет текста и его фона являются теперь атрибутами самого текста, а не графического контекста. Можно задать разную ширину символов шрифта, надстрочные и подстрочные индексы. Атрибуты устанавливаются константами класса TextAttribute.
Процесс визуализации (rendering) регулируется правилами (hints), определенными константами класса RenderingHints.
С такими возможностями Java 2D стала полноценной системой рисования, вывода текста и изображений. Посмотрим, как реализованы эти возможности, и как ими можно воспользоваться.
Преобразование координат
Правило преобразования координат пользователя в координаты графического устройства (transform) задается автоматически при создании графического контекста так же, как цвет и шрифт. В дальнейшем его можно изменить методом setTransform() так же, как меняется цвет или шрифт. Аргументом этого метода служит объект класса AffineTransform из пакета java.awt.geom, подобно объектам класса Сolor или Font при задании цвета или шрифта.















