Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Вывод текста



Для вывода текста в область рисования текущим цветом и шрифтом, начиная с точки (х, у), в, классе Graphics есть несколько методов:

• drawstring (String s, int x, int y> — выводит строку s;

• drawBytes(byte[] b, int offset, int length, int x, int у) — выводит length элементов массива байтов, начиная с индекса offset;

• drawChars(chart] 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, как это сделано в листинге 8.3.

При выводе текста логическим именам шрифтов и стилям сопоставляются физические имена шрифтов (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 (см. рис. 6.2). Если у вас установлена русская локаль с международным кодом языка "ru", то для сопоставления будет выбран файл font.properties.ru. Если такой файл не найден, то применяется файл font.properties, не соответствующий никакой конкретной локали.

Поэтому можно оставить в системе только один файл font.properties, переписав в него содержимое нужного файла или создав файл заново. Для любой локали будет использоваться этот файл.

В листинге 9.1 показано сокращенное содержимое файла font.propeities.ru из JDK 1.3 для платформы MS Windows.

Листинг 9.1. Примерный файл font.properties.ru:

# %W% %E%

# Это просто комментарии

# AWT Font default Properties for Russian Windows

#

# Три сопоставления логическому имени "Dialog":

dialog.0=Arial,RUSSIAN_CHARSET

dialog.l=WingDings,SYMBOL_CHARSET,NEED_CONVERTED

dialog.2=Symbol,SYMBOL_CHARSET,NEED_CONVERTED

# По три сопоставления стилям ITALIC, BOLD, ITALIC+BOLD:

dialog.italic.0=Arial Italic,RUSSIAN_CHARSET

dialog.italic.l=WingDings,SYMBOL_CHARSET,NEED_CONVERTED

dialog.italic.2=Symbol,SYMBOL_CHARSET,NEED_CONVERTED

dialog.bold.0=Arial Bold,RUSSIAN_CHARSET

dialog.bold.l=WingDings,SYMBOL_CHARSET,NEED_CONVERTED

dialog.bold.2=Symbol,SYMBOL_CHARSET,NEED_CONVERTED

dialog.bolditalic.0=Arial Bold Italic,RUSSIAN_CHARSET

dialog.bolditalic.l=WingDings,SYMBOL_CHARSET,NEED_CONVERTED

dialog.bolditalic.2=Symbol,SYMBOL_CHARSET,NEED_CONVERTED

# По три сопоставления имени "Dialoglnput" и стилям:

dialoginput.0=Courier New,RUSSIAN_CHARSET

dialoginput.l=WingDings,SYMBOL_CHARSET,NEED_CONVERTED

dialoginput.2=Symbol,SYMBOL_CHARSET,NEED_CONVERTED

dialoginput.italic.0=Courier New Italic,RUSSIAN_CHARSET

# И так далее

#

# По три сопоставления имени "Serif" и стилям:

serif.0=Times New Roman,RUSSIAN_CHARSET

serif.l=WingDings,SYMBOL_CHARSET,NEED_CONVERTED

serif.2=Symbol,SYMBOL_CHARSET,NEED_CONVERTED

serif.italic.0=Times New Roman Italic,RUSSIAN_CHARSET

# И так далее

# Прочие логические имена

sansserif. CMArial,RUSSIAN_CHARSET

sansserif.l=WingDings,SVMBOL_CHARSET,NEED_CONVERTED

sansserif.2=Symbol,SYMBOL_CHARSET,NEED_CONVERTED

sansserif.italic. 0=Arial Italic,ROSSIAN_CHARSET

# И так далее

#

monospaced.0=Courier New,RUSSIAN_CHARSET

monospaced.l=WingDings,SYMBOL_CHARSET,NEED_CONVERTED

monospaced.2=Symbol,SYMBOL_CHARSET,NEED_CONVERTED

monospaced.italic.0=Courier New Italic,RUSSIAN_CHARSET

# И так далее

# Default font definition

#

default.char=2751

# for backword compatibility

# Старые логические имена версии JDK 1.0

timesroman.0=Times New Roman,RUSSIAN_CHARSET

helvetica.0=Arial,RUSSIAN_CHARSET

courier.0=Courier New,RUSSIAN_CHARSET

zapfdingbats.0=WingDings,SYMBOL_CHARSET

# font filenames for reduced initialization time

# Файлы со шрифтами

filename.Arial=ARIAL.TTF

filename.Arial_Bold=ARIALBD.TTF

filename.Arial_Italic=ARIALI.TTF

filename.Arial_Bold_Italic=ARIALBI.TTF

filename.Courier_New=COUR.TTF

filename.Courier_New_Bold=COURBD.TTF

filename.Courier_New_Italic=COURI.TTF

filename.Courier_New_Bold_Italic=COURBI.TTF

filename.Times_New_Roman=TIMES.TTF

filename.Times_New_Roman_Bold=TlMESBD.TTF

filename.Times_New_Roman_Italic=TIMES3.TTF

filename.Times_New_Roman_Bold Italic=TIMESBI.TTF

filename.WingDings=WINGDING.TTF

filename.Symbol=SYMBOl.TTF

# name aliases

# Псевдонимы логических имен закомментированы

# alias.timesroman=serif

# alias.helvetica=sansserif

# alias.courier=monospaced

# Static FontCharset info

#

# Классы преобразования символов в байты

fontcharset.dialog.0=sun.io.CharToByteCP1251

fontcharset.dialog.l=sun.awt.windows.CharToByteWingDings

fontcharset.dialog.2=sun.awt.CharToByteSymbol

fontcharset.dialoginput.0=sun.io.CharToByteCP1251

fontcharset.dialoginput.l=sun.awt.windows.CharToByteWingDings

fontcharset.dialoginput.2=sun.awt.CharToByteSymbol

fontcharset.serif.0=sun.io.CharToByteCP1251

fontcharset.serif.l=sun.awt.windows.CharToByteWingDings

fontcharset.serif.2=sun.awt.CharToByteSymbol

fontcharset.sansserif.0=sun.io.CharToByteCP1251

fontcharset.sansserif.l=sun.awt.windows.CharToByteWingDings

fontcharset.sansserif.2=sun.awt.CharToByteSymbol

fontcharset.monospaced.0=sun.io.CharToByteCP1251

fontcharset.monospaced.l=sun.awt.windows.CharToByteWingDings

fontcharset.monospaced.2=sun.awt.CharToByteSymbol

# Exclusion Range info

#

# He просматривать в этом шрифте указанные диапазоны

exclusion.dialog.0=0100-0400,0460-ffff

exclusion.dialoginput.0=0100-0400, 0460-ffff

exclusion.serif.0=0100-0400,04 60-ffff

exclusion.sansserif.0=0100-0400, 0460-ffff

exclusion.monospaced.0=0100-0400,0460-ffff

# charset for text input

#

# Вводимые байтовые символы кодируются в кириллический диапазон

# кодировки Unicode

inputtextcharset=RUSSIAN_CHARSET

Большая часть этого файла занята сопоставлениями логических и физических имен. Вы видите, что под номером 0:

• логическому имени "Dialog" сопоставлено имя семейства Arial;

• логическому имени "Dialoginput" сопоставлено имя семейства Courier New;

• логическому имени "Serif" сопоставлено имя семейства Times New Roman;

• логическому имени "Sansserif" сопоставлено имя семейства Arial;

• логическому имени "Monospaced" сопоставлено имя семейства Courier New.

Там, где указан стиль: dialog.italic, dialog.bold и т.д., подставлен соответствующий физический шрифт.

В строках листинга 9.1, начинающихся со слова filename, указаны файлы с соответствующими физическими шрифтами, например:

filename.Arial=ARIAL.TTF

Эти строки необязательны, но они ускоряют поиск файлов со шрифтами. Теперь посмотрите на последние строки листинга 9.1. Строка

exclusion.dialog.0=0100-0400, 0460-ffff

означает, что в шрифте, сопоставленном логическому имени "Dialog" под номером 0, а именно, Arial, не станут отыскиваться начертания (glyphs) символов с кодами в диапазонах '\u0100' —'\u0400' и '\u0460' —'\uFFFF'. Они будут взяты из шрифта, сопоставленного этому имени под номером 1, а именно, WingDings.

То же самое будет происходить, если нужные начертания не найдены в шрифте, сопоставленному логическому имени под номером 0. Не все файлы со шрифтами Unicode содержат начертания (glyphs) всех символов.

Если нужные начертания не найдены и в сопоставлении 1 (в данном примере в шрифте WingDings), они будут отыскиваться в сопоставлении 2 (т. е. в шрифте Symbol) и т. д. Подобных сопоставлений можно написать сколько угодно.

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

Все сопоставления под номерами 0, 1, 2, 3, 4 следует повторить для всех стилей: bold, italic, bolditalic.

Если в графической системе используются шрифты Unicode, как, например, в MS Windows NT/2000, то больше ни о чем беспокоиться не надо.

Если же графическая система использует байтовые ASCII-шрифты как, например, MS Windows 95/98/ME, то следует позаботиться об их правильной перекодировке в Unicode и обратно.

Для этого на платформе MS Windows используются константы Win32 API RUSSIAN_CHARSET, SYMBOL_CHARSET, ANSI_CHARSET, OEM_CHARSET И др., показывающие, какую кодовую таблицу использовать при перекодировке, так же, как это отмечалось в главе 5 при создании строки из массива байтов.

Если логическим именам сопоставлены байтовые ASCII-шрифты (в примере это шрифты WingDings и Symbol), то необходимость перекодировки отмечается константой NEED_CONVERTED.

Перекодировкой занимаются методы специальных классов charToByteCP1251, TiarToByteWingDings, CharToByteSyrnbol. Они указываются для каждого сопоставления имен в строках, начинающихся со слова fontcharset. Эти строки обязательны для всех шрифтов, помеченных константой NEED_CONVERTED.

В последней строке файла указана кодовая страница для перекодировки в Unicode символов, вводимых в поля ввода:

inputtextcharset = RUSSIAN_CHARSET

Эта запись задает кодовую таблицу СР1251.

Итак, собираясь выводить строку str в графический контекст методом drawstring о, мы создаем текущий шрифт конструктором класса Font, указывая в нем логическое имя шрифта, например, "Serif". Исполняющая система Java отыскивает в файле font.properties, соответствующем локальному языку, сопоставленный этому логическому имени физический шрифт операционной системы, например, Times New Roman. Если это Unicode-шрифт, то из него извлекаются начертания символов строки str по их кодировке Unicode и отображаются в графический контекст. Если это байтовый ASCII-шрифт, то строка str предварительно перекодируется в массив байтов методами класса, указанного в одной из строк fontcharset, например, CharToByteCP1251.

Хорошие примеры файлов font.properties.ru собраны на странице Сергея Астахова, указанной во введении.

Обсуждение этих вопросов и примеры файлов font.properties для X Window System даны в документации SUN J2SDK в файле docs/guide/intl /fontprop.html.

Завершая обсуждение логических и физических имен шрифтов, следует сказать, что в JDK 1.0 использовались логические имена "Helvetica", "TimesRoman", "Courier", замененные В JDK 1.1 НЗ "SansSerif", "Serif", "Monospaced", соответственно, из лицензионных соображений. Старые имена остались в файлах font.properties для совместимости.

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

В Java 2D класс FontMetrics заменен классом TextLayout. Его мы рассмотрим в конце этой главы, а сейчас выясним, какую пользу можно извлечь из методов класса FontMetrics.

Класс FontMetrics

Класс FontMetrics является абстрактным, поэтому нельзя воспользоваться его конструктором. Для получения объекта класса FontMetrics, содержащего набор метрических характеристик шрифта f, надо обратиться к методу getFontMetrics (f) класса Graphics или класса Component.

Подробно с характеристиками компьютерных шрифтов можно познакомиться по книге.

Класс FontMetri.cs позволяет узнать ширину отдельного символа ch в пикселах методом charwidth(ch), общую ширину всех символов массива или под-массива символов или байтов методами getchars() и getBytes(), ширину целой строки str в пикселах методом stringwidth(str).

Несколько методов возвращают в пикселах вертикальные размеры шрифта.

Интерлиньяж (leading) — расстояние между нижней точкой свисающих элементов таких букв, как р, у и верхней точкой выступающих элементов таких букв, как б, и, в следующей строке — возвращает метод getLeading ().

Среднее расстояние от базовой линии шрифта до верхней точки прописных букв и выступающих элементов той же строки (ascent) возвращает метод getAscent (}, а максимальное — метод getMaxAscent ().

Среднее расстояние свисающих элементов от базовой линии той же строки (descent) возвращает метод getDescent (), а максимальное — метод getMaxDescent().

Наконец, высоту шрифта (height) — сумму ascent + descent + leading — возвращает метод getHeight (). Высота шрифта равна расстоянию между базовыми линиями соседних строк.

Эти элементы показаны на рис. 9.1.

Рис. 9.1. Элементы шрифта

Дополнительные характеристики шрифта можно определить методами класса LineMetrics из пакета java.awt.font. Объект этого класса можно получить несколькими методами getLineMetrics () класса FontMetrics.

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

Листинг 9.2. Использование графических примитивов и шрифтов

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(si)) 12,

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

}

});

}

}

В листинге 9.2 использован простой класс Dimension, главная задача которого — хранить ширину и высоту прямоугольного объекта в своих полях width и height. Метод getsize () класса component возвращает размеры компонента в виде объекта класса Dimension. В листинге 9.2 размеры компонента f типа GrapMest установлены в конструкторе методом setBounds() равными 500x300 пикселов.

Еще одна особенность листинга 9.2 — для вычерчивания толстой линии, отделяющей заголовок от текста, пришлось провести три параллельные прямые на расстоянии один пиксел друг от друга.

Как вы увидели из обзора класса Graphics и сопутствующих ему классов, средства рисования и вывода текста в этом классе весьма ограничены. Линии можно проводить только сплошные и только толщиной в один пиксел, текст выводится только горизонтально и слева направо, не учитываются особенности устройства вывода, например, разрешение экрана.

Эти ограничения можно обойти разными хитростями: чертить несколько параллельных линий, прижатых друг к другу, как в листинге 9.2, или узкий заполненный прямоугольник, выводить текст по одной букве, получить разрешение экрана методом getScreenSize() класса Java.awt.Toolkit и использовать его в дальнейшем. Но все это затрудняет программирование, лишает его стройности и естественности, нарушает принцип KISS.

В Java 2 класс Graphics, в рамках системы Java 2D, значительно расширен классом Graphics2D.

Рис. 9.2. Пример использования класса Graphics





Дата публикования: 2015-07-22; Прочитано: 216 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.03 с)...