Менеджери розташування (Layout Managers, перекл. також як диспетчери компонування або менеджери компонування) розміщують графічні компоненти у контейнері відповідно до певної схеми розташування (layout scheme). Кожен контейнер (фрейм, панель тощо) має менеджер розташування по замовчуванню.
Навіщо потрібні менеджери розташування? Розташовувати компоненти інтерфейсу користувача можна і вручну, проте це доволі трудомістка процедура, крім того, що Вам необхідно задати координати та розміри компонент, ви повинні, також, передбачити як змінюватиметься графічний інтерфейс при зміні розміру вікна. Для полегшення цієї задачі і створено ряд класів менеджерів розташування, які більшість рутинної роботи беруть на себе.
Для додавання менеджера до вашого контейнера використовується метод setLayout(). Наприклад:
setLayout (new BorderLayout());
Розглянемо детальніше роботу з кожним менеджером розташування.
FlowLayout
FlowLayout – найпростіший із менеджерів розташування, який застосовують по замовчуванню у деяких контейнерах, зокрема в JPanel. Він розміщує елементи один за одним справа на ліво і зверху вниз. Подібно до того як текстовому редакторі розміщуються слова в тексті. Менеджер також дозволяє здійснювати вирівнювання вмісту контейнера по ліву та праву сторону і по центру (LEFT, RIGHT, CENTER). Недоліком його є непередбачуваність інтерфейсу програми. Так якщо наприклад у Вас розташовано в ряд 5-ть кнопок, то зменшення розміру вікна призводить до переносу частини кнопок вниз (дивіться приклад далі).
Існує три конструктори FlowLayout: FlowLayout(); FlowLayout(int how); FlowLayout(int how, int horz, int vert); Перший застосовує схему розташування по замовчуванню, тобто по центрі. У другому випадку задається спосіб вирівнювання, наприклад, можна задати вирівнювання FlowLayout.Left. В третьому конструкторі крім вирівнювання вказуються відстань по горизонталі та по вертикалі між компонентами.
Наступна програма демонструє розміщення компонентів:
import java.awt.FlowLayout; import java.awt.LayoutManager; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel;
public class FlowLayoutExample {
public static void main(String[] args) { ProgramFrame frame = new ProgramFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true);
class ProgramFrame extends JFrame{ ProgramFrame(){ //задаємо розмір фрейму setSize(450, 150); //створюємо кнопки JButton red = new JButton("Червоний"); JButton yellow=new JButton("Жовтий"); JButton green = new JButton("Зелений"); JButton blue=new JButton("Синій"); JButton black = new JButton("Чорний"); JButton white=new JButton("Білий"); // створюємо панель, на якій будуть розміщені кнопки JPanel panel = new JPanel(); // встановлюємо менеджер FlowLayout // з вирівнюванням вліво // якщо пропустити наступний рядок, то по замовчуванню буде по центру panel.setLayout (new FlowLayout(FlowLayout.LEFT)); // додаємо панель у фрейм this.add(panel); // додаємо кнопки на панель
panel.add(red); panel.add(yellow); panel.add (green); panel.add (black); panel.add (white);
BorderLayout
BorderLayout розташовує об’єкти в одну з п’яти географічних позицій (північ, південь, захід, схід і центр), що представлені константами в класі BorderLayout: NORTH, SOUTH, EAST, WEST, CENTER. BorderLayout є менеджером для об’єктів JWindow та JFrame.
BorderLayout має два конструктори: BorderLayout(); BorderLayout(int horz, int vert); Як і в FlowLayout другий конструктор задає відстані між компонентами. Для того ж щоб задати вирівнювання компонентів потрібно скористатися методом add класу Container. void add (Component compObj, Object region); Тут compObj – компонент, що додається. region – область розсташування компонента.
При додаванні графічних елементів безпосередньо на контейнер призводить до того, що вони одержують максимальний розмір.
import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JFrame;
public class BorderLayoutExample1 { public static void main(String[] args) { ProgFrame frame = new ProgFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true);
class ProgFrame extends JFrame{ ProgFrame(){ setSize(300,300); setLocation(200,200); // setLayout(new BorderLayout()); по замовчуванню для JFrame add (new JButton ("North"), BorderLayout.NORTH); add (new JButton ("South"), BorderLayout.SOUTH); add (new JButton ("East"), BorderLayout.EAST); add (new JButton ("West"), BorderLayout.WEST); add (new JButton ("Center"), BorderLayout.CENTER);
Результат виконання:
Як бачимо кнопки були спотворені при заповненні простору. Уникнути такого можна попередньо додавши у відповідні позиції панелі JPanel на яких і розміщувати компоненти (кнопки в даному випадку).
import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel;
public class BorderLayoutExample2 { public static void main(String[] args) { ProgFrame2 frame = new ProgFrame2(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true);
class ProgFrame2 extends JFrame{ ProgFrame2(){ setSize(250,200); setLocation(200,200); setLayout(new BorderLayout()); // в даному випадку необов'язково JPanel p= new JPanel(); p.add (new JButton ("North")); add (p, BorderLayout.NORTH); p=new JPanel(); p.add(new JButton ("South")); add (p, BorderLayout.SOUTH); p=new JPanel(); p.add(new JButton ("East")); add (p, BorderLayout.EAST); p=new JPanel(); p.add(new JButton ("West")); add (p, BorderLayout.WEST); p=new JPanel(); p.add(new JButton ("Center")); add (p, BorderLayout.CENTER);
Як бачимо у кожен сектор ми додаємо панель, а вже на ній розміщуємо кнопку.
Зверніть увагу, що кнопки розташовані по центру зверху. Це тому, що у панелі по замовчуванню діє менеджер розташування FlowLayout. Кожній панелі можна призначити іншого менеджера. Таким чином можна розробляти більш складніший інтерфейс на основі простих менеджерів FlowLayout та BorderLayout.
GridLayout
Менеджер розташування GridLayout розташовує компоненти по рядкам і стовпцям, подібно як в електронних таблицях. Проте при цьому всі комірки однакового розміру. Компоненти автоматично будуть приведені до розміру комірок, їхні попередні розміри будуть проігноровані. При зміні розміру вікна, компоненти будуть змінюватися пропорційно.
GridLayout отримує кількість рядків та стовпців у своєму конструкторі. panel.setLayout (new GridLayout(5,4));
Можна також вказати відстань між компонентами по горизонталі та вертикалі. panel.setLayout(new GridLayout(5,4,3,3));
Відстані між компонентами задаються в пікселях. Самі ж компоненти додаються порядково, спочатку перший компонент першого рядка, згодом другий компонент першого рядка і т.д. panel.add(new JButton (“1”)); panel.add(new JButton (“2”));
Наступний код виводить на екран вікно з 15-ма кнопками з використанням GridLayout.
import java.awt.Font; import java.awt.GridLayout; import java.awt.Panel; import javax.swing.JButton; import javax.swing.JFrame;
public class GridLayoutExample { public static void main(String[] args) { Frame15 frame = new Frame15(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true);
class Frame15 extends JFrame{ Frame15(){ int k=0; Panel p=new Panel(); setSize(300,250); p.setLayout(new GridLayout(4,4));
for (int i=0;i<15;i++){ k=i+1; JButton button=new JButton(""+k); button.setFont(new Font("SansSerif", Font.BOLD, 20)); p.add (button);
add(p);
Наведений приклад може бути використаний для реалізації гри в п’ятнадцять. Також GridLayout корисний для реалізації інтерфейсу калькулятора. В багатьох книжках програмування на Джава наведені приклади реалізації простого калькулятора з використанням даного менеджера.
На практиці GridLayout не дуже часто використовується. Він може бути використаний для поділу вікна на кілька рівних частин. Зокрема, якщо вказати GridLayout(1,0) – ми отримуємо один рядок і необмежену кількість стовпчиків, аналогічно GridLayout(2,0) – два рядки і необмежена кількість стовпчиків. Можна також вказувати навпаки кількість стовпчиків і тоді буде необмеженою кількість рядків. Даний менеджер розташування зручний для реалізації панелей інструментів, де кнопки мають бути однакового розміру.
BoxLayout Менеджер BoxLayout розташовує компоненти в один рядок або стовпець. Він корисний для створення панелей інструментів, або вертикальної панелі кнопок.
BoxLayout можна застосовувати напряму як інші менеджери. У Swing також існує доволі зручний cпеціальний для цієї мети контейнер Box, який використовує BoxLayout і надає ряд корисних методів. По суті Box – це панель, для якої вже налаштоване блокове розміщення. Створюється така панель не конструктором, а одним з двох статичних методів, що визначені в класі Box: createHorizontalBox() та createVerticalBox().
Компоненти, що додаються на панель з блоковим розташуванням, вишиковуються один за іншим. Відстань між компонентами по замовчуванню нульова. Проте між ними можна додавати невидиму «розпірку» (strut), призначення якої - розсувати сусідні компоненти на потрібну відстань. Горизонтальна розпірка створюється статичним методом createHorizontalStrut (int width), а вертикальна – методом createVerticalStrut (int height).
Крім розпірок між компонентами можна вставляти так звані склейки (glue). Якщо поставити склейки між двома компонентами, то вони розсунуть їх на максимально можливу відстань, зайнявши весь вільний простір у контейнері. Якщо вставити склейки в різних місцях, то вільний простір розподілиться між компонентами де вони застосовані. Горизонтальні та вертикальні склейки створюються відповідними методами: createHorizontalGlue() і createVerticalGlue().
Наступний приклад демонструє використання об’єкту Box, розпірки та склейки.
import javax.swing.Box; import javax.swing.JButton; import javax.swing.JFrame;
public class BoxLayoutExample { public static void main(String[] args)
PFrame frame = new PFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true);
class PFrame extends JFrame{ PFrame(){ setTitle("Box Layout Example"); setSize(200, 400);
Box box = Box.createVerticalBox(); box.add(new JButton("Кнопка 1")); box.add(Box.createVerticalStrut(20)); box.add(new JButton("Кнопка 2")); box.add(Box.createVerticalGlue()); box.add(new JButton("Кнопка 3")); box.add(Box.createVerticalGlue()); box.add(new JButton("Кнопка 4")); box.add(new JButton("Кнопка 5"));
add(box);
Як бачимо склейки використані між кнопками 2-3 та 3-4. Простір розподілено порівну. Між 1 та 2 стоїть розпірка, а між 4-5 немає нічого.
В даному прикладі усі кнопки вирівняні зліва вікна. Це вирівнювання по замовчуванню. Для цього можна скористатися методами класу JComponent setAlignmentX(float alignment), setAlignmentY(float alignment) та константами даного класу: LEFT_ALIGNMENT (по лівому краю), RIGHT_ALIGNMENT (по правому краю), CENTER_ALIGNMENT (по центру). Для вирівнюванню по вертикалі — BOTTOM_ALIGNMENT (по нижньому краю), TOP_ALIGNMENT (по верхньому краю) і CENTER_ALIGNMENT (по центру). JButton rightButton = new JButton("Кнопка Х"); rightButton.setAlignmentX(JComponent.RIGHT_ALIGNMENT); box.add(rightButton); Проте коли ви спробуєте надавати кожному компоненту окреме від інших вирівнювання, Ви не отримаєте потрібного результату. Причиною є те, що вирівнювання відбувається не по краях вікна, а по невидимій лінії вирівнюванню. Так якщо ви вирівнюєте по праву сторону кнопку, то лінія буде справа, а всі інші елементи зліва цієї лінії. Так наведений нижче рисунок показує результат дещо модифікованої програми, де додані вище наведені рядки.
Якщо кожній кнопці по окремості задати одне й те ж вирівнювання, то усе відображатиметься так як треба.
CardLayout