Материал: Портянкин И. Swing

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Искусство расположения

175

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

На первом этапе работы менеджера SpringLayout все компоненты находятся в начале координат контейнера и имеют предпочтительный размер. Чтобы разместить их по нужным позициям, обычно проводят следующие действия: первый компонент отделяют некоторым расстоянием от границы контейнера, второй отделяют от первого расстоянием между нужными границами, далее размещают третий компонент и т. д. Рассмотрим небольшой пример и увидим все в действии:

//SpringLayoutSample.java

//Работа менеджера SpringLayout import javax.swing.*;

import java.awt.*;

public class SpringLayoutSample extends JFrame { public SpringLayoutSample() {

super("SpringLayoutSample"); setDefaultCloseOperation(EXIT_ON_CLOSE);

//панель с использованием SpringLayout SpringLayout sl = new SpringLayout(); JPanel contents = new JPanel(sl);

//добавим пару компонентов

JButton button1, button2;

contents.add(button1 = new JButton("Первая")); contents.add(button2 = new JButton("Последняя"));

//настроим распорки sl.putConstraint(SpringLayout.WEST, button1,

5, SpringLayout.WEST, contents); sl.putConstraint(SpringLayout.WEST, button2, 5,

SpringLayout.EAST, button1);

//выведем окно на экран setContentPane(contents); setSize(300, 200); setVisible(true);

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

public void run() { new SpringLayoutSample(); } });

}

}

Мы создаем небольшое окно JFrame, его панелью содержимого является панель JPanel, использующая менеджер расположения SpringLayout. В полученную панель добавляются две

176

ГЛАВА 7

кнопки. Для того чтобы они заняли свое место, необходимо задать для них нужные расстояния. Расстояние задается методом putConstraint() класса SpringLayout. В нем нужно указать границу компонента, сам компонент, расстояние, а также границу второго компонента и сам второй компонент (это тот компонент, что вы хотите отделить заданным расстоянием от первого компонента). Первый вызов putConstraint() отделяет западную (левую) границу первой кнопки от западной же границы контейнера. Второй вызов разделяет западную (левую) границу второй кнопки и восточную (правую) границу первой кнопки пятью пикселами. В итоге мы получаем две кнопки, расположенные горизонтально и отделенные пятью пикселами. Вы сможете легко в этом убедиться, запустив программу с примером.

Менеджер SpringLayout довольно мощен и гибок, но совершенно не приспособлен для создания интерфейса «вручную». Посмотрите: чтобы расположить компоненты, нужны все ссылки на них, приходится оперировать абсолютными значениями расстояний между ними, и создание не самого сложного расположения из десятка компонентов рискует превратиться в мешанину из вызовов putConstraint(). Поддерживать такой код очень сложно, и это не удивительно: менеджер SpringLayout предназначен, прежде всего, для автоматизированного построения интерфейса, а для ручной работы есть более удобные приемы.

Абсолютное расположение

Никто не настаивает на обязательном использовании в контейнере менеджера расположения, вы можете удалить его, вызвав метод setLayout(null). В этом случае вся ответственность за правильное расположение компонентов на экране ложится на ваши плечи: размеры и позиции компонентов придется задавать прямо в программе, вызывая для каждого компонента метод setBounds() с подходящим прямоугольником.

Никогда не используйте абсолютное расположение, иначе рискуете навлечь на себя праведный гнев любого Java-программиста, который увидит ваш код. Все преимущества динамической смены внешнего вида приложения средствами библиотеки Swing, вся легкость перехода на другие платформы — все будет повергнуто в прах в случае абсолютного расположения. Забудьте о нем так, как будто его нет. Если ваше средство автоматизированного построения интерфейса предлагает проектировать интерфейс в абсолютных координатах, а затем безуспешно пытается привести то, что получилось, к расположению, соответствующему какому-либо менеджеру (в результате вам все равно приходится использовать абсолютное расположение), выбросите это средство.

Единственным случаем, в котором приходится применять абсолютное расположение, являются графические приложения, где мы рисуем или располагаем компоненты поверх остального интерфейса, например, логотип компании. Часто для этого применяется компонент JXLayer или прозрачная панель (glass pane), которые мы обсуждали в главе 6.

Вложенные расположения

В предыдущем разделе, совмещая табличное и последовательное расположения, мы познакомились с примером так называемого вложенного расположения (nested layout), основная идея которого очень проста — вы создаете несколько контейнеров с различ-

Искусство расположения

177

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

В принципе, обычный пользовательский интерфейс вполне можно создать на основе рассмотренных нами простейших расположений. Но, честно говоря, хотелось бы более гибкого подхода, особенно это касается расположения компонентов по вертикали. И потом, рассмотренные нами до этого расположения очень неаккуратно работают с расстоянием между компонентами — его можно задать один раз, причем сразу для всех входящих в расположение компонентов. Между тем, в качественном интерфейсе расстояние между компонентами играет важнейшую роль, и чаще всего между разными компонентами оно разное. Поэтому создавать большую часть интерфейса с помощью этой идеи мы, конечно, не станем, а рассмотрим универсальные расположения, применяемые при создании пользовательского интерфейса чаще других.

Блочное расположение BoxLayout

Блочное расположение BoxLayout — прекрасная альтернатива всем остальным менеджерам расположения. Обладающее большими возможностями расположение BoxLayout

не сложнее BorderLayout.

Менеджер блочного расположения выкладывает компоненты в контейнер блоками: столбиком (по оси Y) или полоской (по оси X), при этом каждый отдельный компонент можно выравнивать по центру, по левому или по правому краям, а также по верху или по низу. Расстояние между компонентами по умолчанию нулевое, но для его задания существуют специальные классы (об этом чуть позже). Как располагаются компоненты, хорошо видно на рис. 7.1

BoxLayout.Y_AXIS (столбиком)

BoxLayout.X_AXIS (полоской)

Рис. 7.1. Блочное расположение

Стрелки показывают, в каком порядке происходит добавление компонентов в контейнер. Чтобы указать менеджеру, как нужно выкладывать компоненты — столбиком или полоской, используются константы из класса BoxLayout, также показанные на рисунке. Рассмотрим простой пример:

//Box1.java

//Блочное расположение import javax.swing.*; import java.awt.*;

public class Box1 extends JFrame {

178

ГЛАВА 7

public Box1() { super("Box1 — Y"); setSize(400, 200);

setDefaultCloseOperation( EXIT_ON_CLOSE );

//получаем панель содержимого

Container c = getContentPane();

//устанавливаем блочное расположение по

//оси Y (столбиком)

BoxLayout boxy = new BoxLayout(c, BoxLayout.Y_AXIS); c.setLayout(boxy);

//добавляем компоненты c.add( new JButton("Один")); c.add( new JButton("Два")); c.add( new JButton("Три"));

//выводим окно на экран setVisible(true);

}

static class Box2 extends JFrame { public Box2() {

super("Box2 — X");

//устанавливаем размер и позицию окна setSize(400, 200);

setLocation(100, 100); setDefaultCloseOperation( EXIT_ON_CLOSE );

//получаем панель содержимого

Container c = getContentPane();

//устанавливаем блочное расположение по

//оси X (полоской)

BoxLayout boxx =

new BoxLayout(c, BoxLayout.X_AXIS); c.setLayout(boxx);

//добавляем компоненты c.add( new JButton("Один")); c.add( new JButton("Два")); c.add( new JButton("Три"));

//выводим окно на экран setVisible(true);

}

}

public static void main(String[] args) { SwingUtilities.invokeLater(

Искусство расположения

179

new Runnable() {

public void run() { new Box1(); new Box2(); } });

}

}

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

Вы можете видеть, что конструктор класса BoxLayout несколько необычен — ему необходимо указать контейнер, в котором он будет функционировать. Ни в одном из рассмотренных нами прежде менеджеров расположения такого не требовалось. Впрочем, можно не строить блочное расположение вручную, а использовать вспомогательный класс Box из пакета javax.swing. В нем определены два статических метода:

public static Box createHorizontalBox() public static Box createVerticalBox()

Эти методы возвращают экземпляр класса Box, который создан специально для поддержки блочного расположения и унаследован от базового класса Swing JComponent. Поэтому объекты Box вы можете использовать как обычные контейнеры для компонентов, только с заранее установленным блочным расположением. Первый метод возвращает контейнер с горизонтальным блочным расположением, второй — с вертикальным.

Однако контейнер, который создается классом Box, не всегда так же полезен, как обычная панель JPanel. Дело в том, что внешний вид любого компонента Swing, как мы знаем, определяется UI-представителем этого компонента. Это верно и для панелей JPanel, и именно подобным способом некоторые внешние виды приложений добавляют

Источник: https://studfile.net/preview/15935977/