You are on page 1of 13

3. Програмування графіки.

В наші програми до цих пір дані вводилися з клавіатури, виводились на консоль.


Сучасні програми працюють з графічним інтерфейсом (GUI). Розглянемо питання
створення GUI, зокрема, як можна змінити розміри і розташування вікон на екрані,
відобразити у вікні текст, набраний різними шрифтами, вивести малюнок і т.д..
Загальні відомості про бібліотеку Swing
В першу версію Java входила бібліотека класів Abstract Window Toolkit (AWT),
що надає основні засоби програмування GUI. Створення елементів GUI на
конкретній платформі (Windows, Solaris, Macintosh і т.д.) бібліотека AWT доручала
інструментальним засобам конкретної платформи. Теоретично створені таким
чином програми повинні були працювати на будь-яких платформах, маючи
зовнішній вигляд, характерний для цільової платформи, - відповідно до фірмового
девізом компанії Sun Microsystems: "Написано один раз, працює скрізь".
Методика з використанні базових засобів конкретних платформ відмінно підходила
для простих додатків. Але з її допомогою вкрай важко створювати високоякісні
переносні графічні бібліотеки, що залежать від інтерфейсних елементів конкретної
платформи. Елементи інтерфейсу, наприклад, меню, панелі прокрутки і текстові
поля, на різних платформах можуть вести себе по-різному. Крім того, деякі
графічні середовища (наприклад, Xll/Motif) не мають такого багатого набору
компонентів інтерфейсу, як операційні системи Windows і Macintosh. В результаті
графічні додатки, створені за допомогою бібліотеки AWT, виглядали в порівнянні з
прикладними програмами для Windows або Macintosh не так привабливо і не мали
таких функціональних можливостей.
Гірше того, в бібліотеці AWT на різних платформах виявлялися різні помилки.
Розробникам доводилося тестувати кожен додаток на кожній платформі, що на
практиці означало: "Написано один раз, налагоджували всюди".
Компанії Sun Microsystems і Netscape об'єднали свої зусилля і створили бібліотеку
Swing - набір інструментальних засобів для створення машинно-незалежного
інтерфейсу користувача. У цій бібліотеці елементи інтерфейсу (меню, кнопки і т.п.)
відтворюються в порожньому вікні. А від віконної системи конкретної платформи
потрібно лише відображати вікно і малювати в ньому графіку. Таким чином,
елементи GUI, створені за допомогою бібліотеки, виглядають і поводяться
однаково незалежно від платформи, на якій запускається програма.
Swing є частиною бібліотеки класів Java Foundation Classes (JFC).
До складу JFC входять не тільки компоненти Swing, а й прикладні програмні
інтерфейси API для спеціальних можливостей, двомірної графіки і перетягування.
Елементи призначеного для користувача інтерфейсу з бібліотеки Swing
з'являються на екрані трохи повільніше аналогічних компонент з бібліотеки AWT,
але на сучасних комп'ютерах цього практично непомітно. З іншого боку, у
бібліотеки Swing є ряд дуже істотних переваг.
• Містить багатший і зручний набір елементів для інтерфейсу користувача.
• Набагато менше залежить від платформи, на якій повинна виконуватися
програма. Отже, вона менше схильна до помилок, характерним для конкретної
платформи.
• Забезпечує однакове сприйняття кінцевими користувачами додатків з GUI на
різних платформах.
Деякі користувачі вважають за краще, щоб їх програми на Java виглядали і
поводилися так, як прийнято на цій платформі, Розробники на Swing можуть
надати своїй програмі зовнішній вигляд в потрібному візуальному стилі і навіть
можуть надати користувачам можливість вибору стилю.
3.1. Створення фрейму
Вікно верхнього рівня (вікно, яке не
міститься всередині іншого вікна) в Java
називається фреймом. В бібліотеці AWT
для такого вікна передбачений клас
Frame. А в бібліотеці Swing його
аналогом є клас JFrame. Клас JFrame
розширює клас Frame.
Класи бібліотеки Swing знаходяться в
пакеті javax.swing.
Розглянемо найпоширеніші прийоми роботи з класом JFrame. Наведемо і
проаналізуємо код простої програми, що відображає на екрані порожній фрейм.
package simpleFrame;
import java.awt.*;
import javax.swing.*;
public class SimpleFrameTest {
public static void main(String[] args) {
EventQueue.invokeLater( () -> {
SimpleFrame frame = new SimpleFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true); });
}
}
class SimpleFrame extends JFrame {
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 200;
public SimpleFrame() {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
}
За замовчуванням фрейм має розміри: 0x0 пікселів. У прикладі визначається
підклас SimpleFrame, в конструкторі якого встановлюються розміри фрейма
300x200 пікселів. Це єдина відмінність підкласу SimpleFrame від класу JFrame. У
методі main() з класу SimpleFrameTest створюється об'єкт типу SimpleFrame, який
робиться видимим.
Є технічні труднощі, які доводиться долати кожній Swing-програмі. Перш за все,
компоненти Swing повинні бути налаштовані в потоці диспетчеризації подій.
Потік диспетчеризації подій - потік управління, який передає компонентам GUI
події на зразок клацань кнопками миші і натискань клавіш. У наступному фрагменті
коду оператори виконуються в потоці диспетчеризації подій:
EventQueue.invokeLater(new Runnable() {
public void run() {
оператори
}
});
НА ЗАМІТКУ! Раніше в Swing-програмах ініціалізацію призначеного для користувача
інтерфейсу допускалося виконувати в головному потоці виконання. У зв'язку з
ускладненням компонентів Swing розробники JDK не змогли більше гарантувати безпеку
такого підходу, хоча ймовірність помилки надзвичайно низька. Але краще зробити все
правильно, навіть якщо код здасться спочатку загадковим і не зовсім зрозумілим.
Далі в прикладі визначається, що саме має статися, якщо користувач закриє вікно
програми - програма повинна завершити свою роботу. Для цього служить
наступний рядок коду:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
За замовчуванням закритий фрейм зникає з екрану, а програма продовжує свою
роботу.
На початку свого існування всі фрейми невидимі. Це дає можливість додавати у
фрейм компоненти ще до того, як він вперше з'явиться на екрані. Для
відображення фрейму на екрані в методі main () викликається метод setVisible ().
Після диспетчеризації операторів ініціалізації відбувається вихід з методу main ().
Це не призводить до припинення роботи програми, завершується лише її
основний потік. Потік диспетчеризації подій продовжує діяти до тих пір, поки вона
не завершиться закриттям фрейму або викликом методу System.exit().
У вікні програми такі елементи, як рядок заголовка і піктограми для зміни розмірів
вікна, відображаються операційною системою, а не компонентами бібліотеки
Swing. При запуску цієї програми в середовищах Windows, GTK або Mac OS вікно
буде виглядати по-різному. Все, що знаходиться у фреймі, відображається
засобами Swing. У даній програмі фрейм просто заповнюється фоновим кольором
за замовчуванням.
НА ЗАМІТКУ! Рядки заголовка та інші елементи оформлення фреймів можна
відключити, зробивши виклик frame.setUndecorated (true).
3.2. Розташування фрейму
Використовуючи методи класу JFrame і його суперкласів можна задавати розміри і
розташування фрейма і змінювати його зовнішній вигляд. До найбільш важливим з
них відносяться наступні методи.
• setLocation () і setBounds(), що встановлюють положення фрейма.
• dispose(), що закриває вікно і звільняє всі системні ресурси, використані при його
створенні.
• setIconImage(), повідомляє віконній системі, яка саме піктограма повинна
відображатися в рядку заголовка, вікні перемикача завдань і т.п.
• setTitle(), що дозволяє змінити текст в рядку заголовка.
• setResizable() одержує в якості параметра логічне значення і визначає, чи має
користувач право змінювати розміри фрейма.
Методи для зміни розмірів і форми фреймів слід шукати в класі Component, який є
попередником всіх об'єктів GUI, а також в класі Window, який є суперкласом для
класу Frame.

Можна надати віконній системі можливість самій керувати розташуванням вікон


якщо перед відображенням вікна зробити виклик:
setLoationByPlatform(true);
Віконна система сама вибере розташування (але не розміри) вікна - як правило, з
невеликим зсувом щодо попереднього вікна.
3.3. Властивості фрейму
Багато методів з класів компонентів об'єднані в пари для отримання і установки
відповідних властивостей, наприклад:
public String getTitle()
public void setTitle(String title)
Для властивостей типу boolean ім'я методу отримання починається зі слова is.
Приклад:
public boolean isLocationByPlatform()
public void setLocationByPlatform(boolean b)

3.4. Визначення підходящих розмірів фрейма


Якщо розміри не задані явно, то за замовчуванням всі фрейми мають розміри 0x0
пікселів. У прикладі розміри задані таким чином, щоб вікно нормально
відображалося на більшості моніторів. Але можна спочатку перевірити розмір
екрана монітора, а потім задати відповідні розміри фрейма.
Клас Toolkit містить багато методів, призначених для взаємодії з віконною
системою конкретної платформи.
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension screenSize = kit.getScreenSize();
int screenWidth = screenSize.width;
int screenHeight = screenSize.height;
Статичний метод getDefaultToolkit () повертає об'єкт типу Toolkit. Метод
getScreenSize () повертає розміри екрану у вигляді об'єкта типу Dimension. Цей
об'єкт містить ширину і висоту в відкритих (!) змінних width і height відповідно.
Далі можна встановити розміри фрейма, наприклад в половину розмірів монітора:
setSize(screenWidth / 2, screenHeight / 2);
setLocationByPlatform(true);.
Приклад створення фрейма, завдання його розміру і піктограми в книзі
«Хорстманн. Java. Бібліотека професіонала, том 1. Основи. 10-е видання »,
стор 494.
Фрейм можна розгорнути до максимуму, зробивши наступний виклик:
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
Якщо фрейм містить тільки стандартні компоненти на зразок кнопок і текстових
полів, виклик методу pack() встановлює мінімальні розміри фрейма, достатні для
розміщення всіх його компонентів.
3.5. Відображення даних в компоненті
Виведемо рядок "Not a Hello, World
program" у фреймі.
Рядок повідомлення можна вивести
прямо в фрейм, але на практиці так
не роблять. Фрейми призначені для
того, щоб служити контейнерами
для компонентів (меню або інших
елементів інтерфейсу користувача).
Як правило, малюнки, тексти
виводяться в іншому компоненті,
який додається у фрейм.
Структура класу JFrame досить складна. Клас JFrame складається з чотирьох
областей, кожна з яких є окремою панеллю. Коренева, багатошарова і прозора
панелі потрібні для оформлення меню і панелі вмісту в певному стилі.
Найцікавішою для застосування є панель вмісту.
При оформленні фрейму його компоненти додаються на панель так:
Container contentPane = frame.getContentPane();
Component c = ...
contentPane.add(c);
Починаючи з Java SE 1.5 можна не отримувати посилання на контент-панель:
frame.add(с);
Нам треба додати у фрейм компонент, де буде виводитися повідомлення. Щоб
відобразити компонент, слід спочатку визначити клас, який розширює клас
JComponent і перевизначити метод paintComponent() цього класу. Метод
paintComponent() отримує в якості параметра об'єкт типу Graphics, який містить
набір установок для відображення малюнків і тексту. У ньому, наприклад,
задається шрифт і колір тексту. Всі операції малювання графіки в Java
виконуються за допомогою об'єктів класу Graphics. В цьому класі передбачені
методи для малювання візерунків, графічних зображень і тексту.
class MyComponent extends JComponent {
public void paintComponent(Graphics g) {
код для рисования
}
}
Кожен раз, коли виникає потреба перерисувати вікно незалежності від конкретної
причини, обробник подій повідомляє про цей відповідний компонент. В результаті
метод paintComponent () виконується для всіх компонентів.
Метод paintComponent () не слід визивати вручну. Коли потрібно перерисовувати
вікна додатків, він автоматично викликається і втручатися в цей процес не
рекомендується.
Автоматична перерисовка потрібна, наприклад, при збільшенні або зменшенні
розмірів вікна. Якщо користувач відкриває нове вікно, перекривши ним уже
наявне вікно додатку, а потім закриває його, вікно, що залишається на екрані,
виявляється пошкодженим і повинно бути перерисовано. (Графічна система не
зберігає в пам'яті пікселів нижчого вікна.) Також, коли вікно виводиться на екран
вперше, слід виконати код, в якому вказано, як і де слід відображати його
елементи.
ПОРАДА. Якщо потрібно перерисовувати екран, замість методу paintComponent () слід
викликати метод repaint (). Цей метод, в свою чергу викликає метод paintComponent ()
кожного компонента і передає йому налаштований об'єкт типу Graphics.
Метод paintComponent () має один параметр типу Graphics. При виведенні на
екран, розміри, збережені в об'єкті типу Graphics, задаються у пікселях.
Координати (0,0) відповідають лівому верхньому куту компонента, на поверхні
якого виконується рисування. Вивід тексту на екран вважається особливим видом
рисування. Для цього в класі Graphics є метод drawString ():
g.drawstring(text, х, у)
Метод paintComponent () виглядає приблизно так,
class NotHelloWorldComponent extends JComponent {
public static final int MSG_X = 75;
public static final int MSG_Y = 100;

public void paintComponent(Graphics g) {
g.drawstring("Not a Hello, World program", MSG_X, MSG_Y);
}

}
Вивід першого символу з рядка починається з точки на 75 пікселів вправо від
лівого краю компонента та базова лінія рядку відступає на 100 пікселів вниз від
верхнього краю компонента.
Компонент повинен повідомити свого користувача про свій бажаний розм. Для
цього перевизначається метод getPreferredSize(), який повертає об'єкт класу
Dimension із бажаними розмірами (шириною та висотою):
class NotHelloWorldComponent extends JComponent {
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 200;

public Dimension getPreferredSize() {
return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}

}
Якщо при заповненні фрейма одним або декількома компонентами потрібно
скористатися їх бажаними розмірами, то у фреймі замість методу setSize ()
викликається метод pack():
class NotHelloWorldFrame extends JFrame {
public NotHelloWorldFrame() {
add(new NotHelloWorldComponent());
pack();
}
}
НА ЗАМІТКУ! Замість розширення класу JComponent деякі програмісти воліють
розширювати клас JPanel, призначений в якості контейнера для інших компонентів, хоча
малювати можна й в ньому самому. АЛЕ панель непрозора, а це означає, що вона
відповідає за малювання всіх пікселів в її межах. Щоб намалювати компоненти в цих
межах, найпростіше залити панель кольором фону, зробивши виклик
super.paintComponent () в методі paintComponen () підкласу панелі:
class NotHelloWorldPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
код для рисования
}
}
Приклад створення фрейма і компонента з написом в книзі «Хорстманн.
Java. Бібліотека професіонала, том 1. Основи. 10-е видання », стор 499.
3.6. Двовимірні форми
У версії Java 1.0 в класі Graphics існувала ціла низка методів з обмеженими
можливостями для малювання ліній, прямокутників, еліпсів та інших двовимірних
форм. Але в них, наприклад, не можна змінити товщину лінії і повернути
двовимірну форму на довільний кут.
У версії Java SE 1.2 була впроваджена бібліотека Java2D з більш ефективними
операціями малювання двовимірної графіки.
Щоб намалювати двовимірну форму засобами бібліотеки Java2D, потрібно
створити об'єкт класу Graphics2D. Це підклас, похідний від класу Graphics.
Починаючи з версії Java SE 2, такі методи, як paintComponent (), автоматично
отримують об'єкти класу Graphics2D. Потрібно лише зробити відповідне
приведення типів:
public void paintComponent (Graphics g) {
Graphics2D g2 = (Graphics2D)g;
...
}
При створенні геометричних форм в бібліотеці Java 2D застосовується об'єктно-
орієнтований підхід. Класи Line2D, Rectangle2D, Ellipse2D реалізують інтерфейс
Shape і призначені для малювання ліній, прямокутників і еліпсів.
НА ЗАМІТКУ! У бібліотеці Java 2D підтримується малювання і більш складних
двовимірних форм, в тому числі дуг, квадратичних і кубічних кривих, а також довільних
ліній.
Щоб намалювати двомірну форму, потрібно спочатку створити об'єкт необхідного
класу, а потім викликати метод draw() з класу Graphics2D:
Rectangle2D rect = ...;
g2.draw(rect);
У бібліотеці Java 2D використовуються координати, представлені числами з
плаваючою точкою (float). У багатьох випадках це дуже зручно, оскільки дає
можливість спочатку побудувати двомірну форму за координатами в природних
одиницях виміру (наприклад, в дюймах або міліметрах), а потім перевести їх в
пікселі. Внутрішні обчислення в бібліотеці Java 2D виконуються в форматі чисел з
плаваючою точкою і одинарної точністю.
АЛЕ! Параметри і значення, які повертаються методами з класу Rectangle2D,
відносяться до типу double. Наприклад, метод getWidth() повертає значення типу
double. (Це відноситься і до класів інших фігур). Якщо далі спробувати
привласнити це значення змінної або параметру функції, яка вимагає тип float,
потрібно явне перетворення типів.
Тому в бібліотеці Java 2D передбачено дві версії кожного класу для малювання
фігур: в першій версії все координати виражаються числовими значеннями типу
float (для дисциплінованих програмістів), а в другій - числовими значеннями типу
double (для ледачих, які не бажають робити явні перетворення з double у float).
Наприклад клас Rectangle2D є абстрактним. Він має два конкретних підкласу,
кожен з яких є внутрішнім і статичним:
Rectangle2D.Float
Rectangle2D.Double
При побудові об'єкта типу Rectangle2D.Float використовуються координати типу
float, а в об'єктах типу Rectangle2D.Double вони виражаються числовими
значеннями типу double.
Обидва класи розширюють один і той же клас Rectangle2D, а їх методи
однойменні методи з їх суперкласу, тому немає ніякої потреби запам'ятовувати
точний тип координат, що вказуються при створенні двомірних форм. Для
посилань на прямокутні об'єкти досить вказувати змінні типу Rectangle2D:
Rectangle2D floatRect =
new Rectangle2D.Float(10.0F, 25.0F, 22.5F, 20.0F);
Rectangle2D doubleRect =
new Rectangle2D.Double(10.0,25.0,22.5,20.0);
Звертатися до внутрішніх класів доводиться лише при побудові об'єктів, що
описують двомірні форми.
Об'єкти типу Rectangle2D і Ellipse2D створюються досить просто. Для цього
достатньо вказати наступні вхідні дані:
• координати х і у лівого верхнього кута;
• ширину і висоту двомірної форми.
Щоб намалювати лінію, слід задати її початкову і кінцеву точки у вигляді об'єктів
типу Point2D або у вигляді пар чисел
Line2D line = new Line2D.Double(start, end);
або
Line2D line = new Line2D.Double(startX, startY, endX, endY);
Приклад в книзі «Хорстманн. Java. Бібліотека професіонала, том 1.
Основи. 10-е видання », стор 506.
Малюється прямокутник, еліпс, вписаний в прямокутник, діагональ прямокутника, а
також коло, центр якої збігається з центром прямокутника.
У прикладі створюється основний фрейм
DrawFrame (спадкоємець JFrame), на нього
в конструкторі додається панель для
малювання DrawComponent (спадкоємець
JComponent).
Промальовування фігур проводиться в
методі компонента paintComponent ().
Зверніть увагу на перевизначення метод
getPreferredSize () компонента. Коли у
фреймі викликається метод pack() він
викликає метод getPreferredSize вкладених
компонент і вибирає розмір кадру.
3.7. Фарбування кольором
Метод setPaint () з класу Graphics2D дозволяє вибрати колір, який буде
застосовуватися при всіх подальших операціях малювання в графічному контексті.
Приклад застосування цього методу в коді.
g2.setPaint(Color.RED);
g2.drawString( "Warning!", 100, 100);
Можна фарбувати кольором внутрішні ділянки замкнутих геометричних форм на
кшталт прямокутників або еліпсів. Для цього замість методу draw() досить
викликати метод fill() у такий спосіб:
Rectangle2D rect = ...;
g2.setPaint(Color.RED);
g2.fill(rect); // заповнити прямокутник червоним кольором
Клас java.awt.Color містить константи, відповідні 13 стандартним кольорам:
BLACK (ЧОРНИЙ), BLUE (СИНІЙ), CYAN (БЛАКИТНИЙ), DARK_GRAY (ТЕМНО-
СІРИЙ), GRAY (СІРИЙ), GREEN (ЗЕЛЕНИЙ), LIGHT_GRAY (світло СІРИЙ),
MAGENTA (ПУРПУРНИЙ), ORANGE (ПОМАРАНЧЕВИЙ), PINK (РОЖЕВИЙ), RED
(ЧЕРВОНИЙ), WHITE (БІЛИЙ), YELLOW (ЖОВТИЙ).
Є можливість вказати довільний колір за його червоною, зеленою і синьою
складовим, створивши об'єкт класу Color. У конструкторі складові задаються
цілими значеннями від 0 до 255 (тобто одним байтом):
Color(int redness, int greenness, int blueness)
Приклад установки спеціального кольору.
g2.setPaint(new Color(0,128,128)); //нудний синьо-зелений колір
g2.drawstring("Welcome!", 75, 125);
Щоб встановити колір фону, слід викликати метод setBackground () з класу-
попередника Component:
MyComponent р = new MyComponent ();
р.setBackground (Color.PINK);
Метод setForeground () задає колір переднього плану, який використовується при
малюванні компонента.
ПОРАДА. Методи brighter () і darker () з класу Color дозволяють встановлювати більш
світлі або темні відтінки поточного кольору відповідно. Але одного виклику методу щоб
досягти помітного ефекту недостатньо, бажано викликати його тричі поспіль.
Константи в класі SystemColor визначають кольори, які використовуються для
забарвлення різних інтерфейсних елементів системи. Наприклад, для фону
фрейма вибирається колір, пропонований за замовчуванням для всіх вікон
користувацького інтерфейсу:
р.setBackground(SystemColor.window)
Фон заповнює вікно при кожному перемальовуванні. Користуватися кольорами,
заданими в класі SystemColor, зручно, якщо потрібно, щоб інтерфейс був
витриманий в тій же кольоровій гамі, що й робочий стіл операційної системи.
3.8. Спеціальне шрифтове оформлення тексту
Обговорювана вище програма для виведення рядка використовувала шрифт за
замовчуванням. Але нерідко потрібно, щоб текст відображався різними шрифтами.
Шрифти визначаються зображенням символів.
В бібліотеці AWT прийняті наступні п'ять логічних назв шрифтів:
SansSerif, Serif, Monospaced, Dialog, Dialoglnput.
Ці назви наводяться до шрифтів, фактично існуючим на машині. Наприклад, в
Windows шрифт Sanserif приводиться до шрифту Arial. Крім того, в комплект JDK
компанії Oracle завжди входять три гарнітури шрифтів: Lucida Sans, Lucida Bright
і Lucida Sans Typewriter.
Щоб відтворити букву заданим шрифтом, потрібно створити об'єкт класу Font з
вказаною назвою шрифту, стилем і розміром:
Font sansboldl4 = new Font("SansSerif", Font.BOLD, 14);
В якості третьої параметра в конструкторі класу Font задається розмір шрифту.
Розміру шрифту задається в пунктах. В одному дюймі міститься 72 пункта. У
конструкторі класу Font замість фактичного назви накреслення можна
використовувати логічну назву шрифту (перший параметр). Другий параметр -
стиль (простий, напівжирний, курсив або напівжирний курсив) задається
константами:
Font.PLAIN, Font.BOLD, Font.ITALIC, Font.BOLD + Font.ITALIC
Шрифти в Java складаються з літер, цифр, розділових знаків і ряду інших
символів. Так, якщо вивести шрифтом Dialog символ '\u2297', на екрані з'явиться
знак . Доступними є лише символи з набору в Юникоді. Виведення на екран
рядка "Hello, World" напівжирним шрифтом SanSerif розміром 14 пунктів:
Font sansboldl4 = new Font("SansSerif", Font.BOLD, 14);
g2.setFont(sansboldl4);
String message = "Hello, World!";
g2.drawString(message, 75, 100);
При розміщенні рядка, наприклад по центру, потрібно знати ширину і висоту рядка
в пікселях. Ці розміри залежать від використовуваного шрифту ( "SansSerif",
Font.BOLD, 14), символів в рядку (Hello, World!), пристроя виведення (монітор).
Метод getFontRenderContext () класу Graphics2D повертає об'єкт класу
FontRendeгContext, що представляє характеристики пристрою виведення. Об'єкт
передається методу getStringBounds () класу Font, який повертає об’єкт
прямокутника (Rectangle2D), що обмежує текстовий рядок.
FontRenderContext context = g2.getFontRenderContext ();
Rectangle2D bounds =
sansboldl4.getStringBounds(message, context);
Основні терміни, що застосовуються при друкарському наборі тексту: базова лінія,
підйом, спуск, інтерліньяж, висота шрифту. Сенс зрозумілий з малюнка

Висота шрифту - це відстань між сусідніми базовими лініями, яка дорівнює сумі
спуску, підйому і інтерліньяжу.
double stringWidth = bounds.getWidth() - довжина рядка
double stringHeight = bounds.getHeight() - висота рядка(шрифту)
double ascent = - bounds.getY(); - підйом рядки (шрифту)
Координата Y відраховується від базової лінії. Для верхньої частини прямокутника
вона є негативною.
Інтерліньяж або спуск можна дізнатися за
допомогою методу getLineMetrics () класу Font,
який повертає об'єкт класу LineMetrics.
Приклад в книзі «Хорстманн. Java. Бібліотека
професіонала, том 1. Основи. 10-е видання »,
стор 516.
У прикладі відображаються рядок, базова лінія та
обмежує прямокутник.
3.9.Відтворення зображень
Прості зображення утворюються малюванням ліній і форм. А складні зображення
на зразок фотографічних зазвичай формуються зовнішніми засобами, наприклад,
при скануванні або обробці в спеціальних графічних редакторах.
Якщо зображення зберігаються в файлах на комп'ютері або в Інтернеті, їх можна
ввести, а потім відтворити на екрані за допомогою об'єктів класу Graphics. Ввести
зображення можна різними способами. Можна, наприклад, скористатися класом
Imagelcon:
Image image = new Imagelcon(filename).getImage();
Змінна image містить посилання на об'єкт, що інкапсулює дані зображення.
Зображення можна далі вивести на екран за допомогою методу drawlmage () з
класу Graphics.
public void paintComponent(Graphics g) {
...
g.drawlmage (image, x, y, null);
}
Приклад в книзі «Хорстманн. Java. Бібліотека професіонала, том 1.
Основи. 10-е видання », стор 520.
Програма багаторазово виводить зображення в
вікні рядами. Виведення зображення рядами
здійснюється за допомогою методу
paintComponent (). Спочатку одна копія
зображення відтворюється в лівому верхньому
кутку вікна, а потім викликається метод соруАгеа(),
який копіює його по всьому вікну:
for (int i=0; i*imageWidth<=getWidth(); i++)
for (int j=0; j*imageHeight<=getHeight(); j++)
if (i+j>0) g.copyArea(0,0, imageWidth, imageHeight,
i*imageWidth, j*imageHeight);

You might also like