Менеджеры расположения Layout

Менеджер расположения (layout manager) определяет, каким образом на форме будут располагаться компоненты. Независимо от платформы, виртуальной машины, разрешения и размеров экрана менеджер расположения гарантирует, что компоненты будут иметь предпочтительный или близкий к нему размер и располагаться в том порядке, который был указан программистом при создании программы.

На странице представлено описание следующих менеджеров расположения и примеров :

Исходные коды примеров различных менеджеров расположения, рассмотренных на странице можно скачать здесь (13.4 Кб).

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

Поддержка менеджеров расположения встроена в базовый класс контейнеров java.awt.Container. Все компоненты библиотеки Swing унаследованы от базового класса JComponent, который, в свою очередь, унаследован от класса Container. Таким образом, для любого компонента Swing можно установить менеджер расположения или узнать, какой менеджер им используется в данный момент. Для этого предназначены методы setLayout() и getLayout().

Конечно, изменять расположение желательно только в контейнерах, которые предназначены для размещения в них компонентов пользовательского интерфейса, то есть в панелях (JPanel) и окнах (унаследованных от класса Window). Не стоит менять расположение в кнопках или флажках, хотя такая возможность имеется. В стандартной библиотеке Java существует несколько готовых менеджеров расположения, и с их помощью можно реализовать абсолютно любое расположение.

Вызов менджера расположения, revalidate

Контейнер окна вызывает методы менеджера расположения каждый раз при изменении своих размеров или при первом появлении на экране. Кроме этого, можно программно запросить менеджер расположения заново расположить компоненты в контейнере: для этого служит так называемая проверка корректности (валидация) контейнера и содержащихся в нем компонентов. Проверка корректности очень полезна, если интерфейс приложения меняется динамически. Например, если динамически меняются размеры компонентов (во время выполнения программы изменяется текст надписи или количество столбцов таблицы — все это приведет к изменению размеров компонентов). После изменений компонентам может не хватать прежних размеров или наоборот, прежний размер будет для них слишком велик. Для этого и предназначена проверка корректности. Выполнить проверку корректности для любого компонента Swing, будь это контейнер или отдельный компонент, позволяет метод revalidate(), определенный в базовом классе библиотеки JComponent.

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

  • Предпочтительный размер. Размер, который идеально подходит компоненту. По умолчанию все размеры компонентов устанавливаются текущим менеджером внешнего вида и поведения (look and feel manager), но можно их изменить. Предпочтительный размер можно изменить с помощью метода setPrefferedSize().
  • Минимальный размер. Параметр определения минимального размера компонента. После достижения минимального размера всех компонентов контейнер больше не сможет уменьшить свой размер. Минимальный размер также можно изменить, для этого предназначен метод setMinimumSize().
  • Максимальный размер. Параметр определения максимального размера компонента при увеличении размеров контейнера. Например, максимальный размер текстового поля JTextField не ограничен. Чаще всего оно должно сохранять свой предпочтительный размер. Это можно исправить с помощью метода setMaximumSize(), устанавливающего максимальный размер. Большая часть менеджеров расположения игнорирует максимальный размер, работая в основном с предпочтительным и минимальным размерами.
  • Выравнивание по осям X и Y. Данные параметры нужны только менеджеру BoxLayout, причем для него они играют важнейшую роль.
  • Границы контейнера. Эти параметры контейнера определяют размеры отступов от границ контейнера. Значения границ контейнера позволяет получить метод getInsets(). Иногда менеджеру расположения приходится их учитывать.

Описание бизнес-логики работы менеджера расположения

Логика работы менеджера расположения происходит следующим образом : он ждет прихода сигнала от контейнера окна, требующего расположить в нем компоненты. Этому соответствует вызов метода layoutContainer() интерфейса LayoutManager. В методе layoutContainer() и происходит основная работа по расположению компонентов в контейнере.

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

Ниже представлен пример разработки менеджера вертикального расположения компонентов VerticalLayout. Он располагает компоненты вертикально с расстоянием между ними в 5 пикселов и использует для всех компонентов предпочтительный размер.

// Пример разработки менеджера вертикального расположения компонентов

import javax.swing.*;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;

// Менеджер вертикального расположения компонентов
class VerticalLayout implements LayoutManager
{
    private Dimension size = new Dimension();

    // Следующие два метода не используются
    public void addLayoutComponent   (String name, Component comp) {}
    public void removeLayoutComponent(Component comp) {}

    // Метод определения минимального размера для контейнера
    public Dimension minimumLayoutSize(Container c) {
        return calculateBestSize(c);
    }
    // Метод определения предпочтительного размера для контейнера
    public Dimension preferredLayoutSize(Container c) {
        return calculateBestSize(c);
    }
    // Метод расположения компонентов в контейнере
    public void layoutContainer(Container container)
    {
        // Список компонентов
        Component list[] = container.getComponents();
        int currentY = 5;
        for (int i = 0; i < list.length; i++) {
            // Определение предпочтительного размера компонента
            Dimension pref = list[i].getPreferredSize();
            // Размещение компонента на экране
            list[i].setBounds(5, currentY, pref.width, pref.height);
            // Учитываем промежуток в 5 пикселов
            currentY += 5;
            // Смещаем вертикальную позицию компонента
            currentY += pref.height;
        }
    }
    // Метод вычисления оптимального размера контейнера
    private Dimension calculateBestSize(Container c)
    {
        // Вычисление длины контейнера
        Component[] list = c.getComponents();
        int maxWidth = 0;
        for (int i = 0; i < list.length; i++) {
            int width = list[i].getWidth();
            // Поиск компонента с максимальной длиной
            if ( width > maxWidth ) 
                maxWidth = width;
        }
        // Размер контейнера в длину с учетом левого отступа
        size.width = maxWidth + 5;
        // Вычисление высоты контейнера
        int height = 0;
        for (int i = 0; i < list.length; i++) {
            height += 5;
            height += list[i].getHeight();
        }
        size.height = height;
        return size;
    }
}

public class VerticalLayoutTest
{
    public static void main(String[] args)
    {
        // Создаем окно
        JFrame frame = new JFrame("VerticalLayoutTest");
        // Определяем размеры
        frame.setSize(260, 150);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // Создаем панель с менеджером вертикального расположения компонентов
        JPanel contents = new JPanel(new VerticalLayout());
        // Добавим кнопки и текстовое поле в панель
        contents.add(new JButton("Продукты"  ));
        contents.add(new JButton("Галантерея"));
        contents.add(new JTextField(20));
        // Размещаем панель в контейнере
        frame.setContentPane(contents);
        // Открываем окно
        frame.setVisible(true);
    }
}

Менеджер расположения VerticalLayout реализует интерфейс LayoutManager. Самым важным методом является layoutContainer(), который определяет расположения всех компонентов, содержащиеся в контейнере. Алгоритм функционирования менеджера расположения не сложный : размещение компонентов по вертикали, отделяя их друг от друга расстоянием в 5 пикселов; все компоненты имеют предпочтительный размер. Чтобы реализовать алгоритм выполняются следующие шаги :

  1. Получение массива компонентов - метод контейнера getComponents().
  2. Организация цикла перебора компонентов.
  3. Определение предпочтительного размера для каждого из компонентов - метод getPreferredSize().
  4. Определение позиции компонента на экране методом setBounds().
  5. Смещение текущей вертикальной координаты Y, увеличением ее значения на высоту очередного компонента с учетом «декоративного» расстояния в 5 пикселов.

Таким образом, менеджер VerticalLayout разместит все компоненты контейнера друг над другом на расстоянии в 5 пикселов. Следует обратить внимание, что компоненты отделены и от левой границы контейнера.

Метод addLayoutComponent() предназначен для добавления компонентов в список менеджера расположения, а метод removeLayoutComponent() для удаления компонентов из списка. addLayoutComponent() позволяет ассоциировать с компонентом строку, которая может быть использована менеджером расположения как рекомендация относительно того, где именно необходимо разместить данный компонент. Наш пример менеджера расположения в отличие от BorderLayout не поддерживает подобных рекомендаций.

Две функции менеджера (предпочтительный preferredLayoutSize() и минимальный minimumLayoutSize()) сообщают размеры контейнера. Для нашего простого менеджера расположения минимальный и предпочтительный размеры контейнера совпадают, их вычисляет метод calculateBestSize(). Для вычисления оптимального размера контейнера в цикле выполняется поиск компонента с самой большой длиной. К найденной длине добавляется 5 пикселов в качестве отступа от левой границы контейнера и получаем оптимальную длину контейнера. Для высоты вычисления чуть сложнее : необходимо сложить высоты всех находящихся в контейнере компонентов, а также прибавлять к ним расстояние в 5 пикселов между всеми компонентами. Полученная сумма и является оптимальной высотой контейнера.

Для тестирования менеджера вертикального расположения в методе main() создаем небольшое окно с рамкой JFrame. Создаем панель с устанавленным менеджером расположения VerticalLayout. В панель добавляется пара кнопок и текстовое поле. Созданную панель размещаем в панели содержимого, после чего окно выводится на экран. На следующем скриншоте представлен интерфейс окна примера использования вертикального менеджера расположения компонентов.

Знание основных принципов работы менеджера расположения позволяет глубже понять технологию размещения компонентов в контейнере при использовании библиотеки Swing.


Полярное расположение BorderLayout

Менеджер BorderLayout специально предназначен для обычных и диалоговых окон. Он позволяет быстро и просто расположить наиболее часто используемые элементы любого окна: панель инструментов, строку состояния и основное содержимое. Для этого BorderLayout разбивает окно на четыре области, а все оставшееся место заполняется компонентом, выполняющим основную функцию приложения - в редакторе это будет текстовое поле, в многооконном приложении — рабочий стол.

Менеджер расположения BorderLayout иммет отличия от остальных. Чтобы добавить с его помощью компонент в методе add() необходимо использовать дополнительный параметр, который определяет область контейнера для размещения компонента. В таблице перечислены допустимые значения этого параметра.

ЗначениеСтрокаОписание
BorderLayout.NORTHNorth Компонент располагается вдоль верхней границы окна и растягивается на всю его ширину. Обычно в этом месте размещается панель инструментов.
BorderLayout.SOUTHSouth Компонент располагается вдоль нижней границы и растягивается на всю ширину окна. Такое положение характерно для строки состояния.
BorderLayout.WESTWest Компонент располагается вдоль левой границы окна и растягивается на всю его высоту; при этом учитываются размеры северных и южных компонентов, имеющих приоритет.
BorderLayout.EASTEast Компонент располагается вдоль правой границы окна. В остальном его расположение аналогично западному компоненту.
BorderLayout.CENTERCenter Компонент помещается в центр окна, занимая максимально возможное пространство.
Рекомендации : на север помещайте панель инструментов вашего приложения. На юг помещайте строку состояния. Оставляйте западные и восточные зоны окна свободными — только в этом случае панель инструментов можно будет перетаскивать. Для главного окна вашего приложения всегда используйте расположение BorderLayout.

Рассмотрим простой BorderLayout пример. В примере создается окно JFrame, в котором менеджер BorderLayout используется по умолчанию. Во все доступные зоны добавляются компоненты :

// Пример полярного расположения компонентов - BorderLayout

import java.awt.*;
import javax.swing.*;

public class BorderLayoutTest extends JFrame
{
    public BorderLayoutTest()
    {
        super("BorderLayoutTest");
        setDefaultCloseOperation( EXIT_ON_CLOSE );
        setSize(250, 250);
        // Панель содержимого
        Container container = getContentPane();
        /*
         *  Размещаем в панели компоненты
         *  В качестве параметров можно использовать 
         *  строки и константы класса BorderLayout
         */
        container.add(new JButton("Север" ), "North"); 
        container.add(new JButton("Юг"    ), "South");
        container.add(new JLabel ("Запад" ), BorderLayout.WEST);
        container.add(new JLabel ("Восток"), BorderLayout.EAST);
        // При отсутствии 2-го параметра компонент размещается в центре
        container.add(new JButton("Центр"));
        // Открываем окно
        setVisible(true);
    }
    public static void main(String[] args)
    {
        new BorderLayoutTest();
    }
}

В примере метод установки менеджера расположения setLayout() не вызывался. В окнах JFrame (также в окнах JWindow и JDialog) расположение BorderLayout применяется автоматически c принимаемой по умолчанию константой Center. При использовании строк в качестве параметров метода add() надо быть внимательным. Со строкой легко сделать трудно обнаруживаемую ошибку, в то время как ошибку при использовании констант сразу же обнаружит компилятор.

Интерфейс примера BorderLayout представлен на следующем скриншоте.

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


Последовательное расположение FlowLayout

Менеджер последовательного расположение FlowLayout размещает компоненты в контейнере слева направо, сверху вниз. При полном заполнении компонентами строки контейнера FlowLayout переходит на следующую строку вниз. Данное расположение устанавливается по умолчанию в панелях JPanel. Основным свойством FlowLayout является определение предпочтительного размера компонентов. Например, размер метки с текстом JLabel соответствует размеру текста. Рассмотрим простой пример FlowLayout :

// Пример последовательного расположения компонентов - FlowLayout

import java.awt.*;
import javax.swing.*;

public class FlowLayoutTest extends JFrame
{
    public FlowLayoutTest()
    {
        super("FlowLayout");
        setDefaultCloseOperation( EXIT_ON_CLOSE );
        setSize(300, 120);
        // Панель содержимого
        Container container = getContentPane();
        /*
         * Определение последовательного расположения 
         * с выравниванием компонентов по центру
         */
        container.setLayout (new FlowLayout(FlowLayout.CENTER));
        // добавляем компоненты
        container.add( new JButton("Школа"   ));
        container.add( new JButton("Институт"));
        container.add( new JButton("Академия"));
        // Открываем окно
        setVisible(true);
    }
    public static void main(String[] args) {
        new FlowLayoutTest();
    }
}

Конструктор класса FlowLayout имеет три перегруженные версии: без параметров, с параметрами выравнивания компонентов, с параметрами выравнивания компонентов и расстояний между ними. В примере использована вторая версия, устанавливающая последовательное расположение по центру.

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

На правом скриншоте размер окна не позволил менеджеру FlowLayout разместить компоненты в одной строке, и один компонент сместился в следующую строку.

При последовательном расположении менеджер FlowLayout всегда сохраняет предпочтительный размер компонентов. Если места в контейнере становится мало, то FlowLayout просто прячет «лишние» компоненты, а не уменьшает их размеры.

Также к важным свойствам менеджера расположения FlowLayout следует отнести то, что при вызове метода preferredLayoutSize() или minimumLayoutSize(), позволяющего узнать предпочтительный и минимальный размеры контейнера, в котором этот менеджер действует, метод возвращает размер, соответствующий ситуации расположения всех компонентов в одну строку. Это особенно важно при совмещении последовательного расположения с другими вариантами расположения. Вследствие этого свойства менеджеры других вариантов расположения будут стараться найти достаточно места для размещения компонентов в одну строку.

Поэтому использовать последовательное расположение следует только в контейнере, где достаточно места, или там, где контейнеру некуда будет «прятать» свои компоненты. Пример совмещении последовательного расположения с табличным представлен на этой странице здесь. Тем не менее, этот простотой менеджер расположения FlowLayout очень хорош при организации несложных вариантов расположения.


Табличное расположение GridLayout

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

Пример табличного расположения компонентов - GridLayout :

// Пример табличного расположения компонентов - GridLayout

import java.awt.*;
import javax.swing.*;

public class GridLayoutTest extends JFrame
{
    public GridLayoutTest()
    {
        super("GridLayoutTest");
        setSize(320, 320);
        setLocation(100, 100);
        setDefaultCloseOperation( EXIT_ON_CLOSE );
        // Вспомогательная панель
        JPanel grid = new JPanel();
        /*
         * Первые два параметра конструктора GridLayout определяют количество
         * строк и столбцов в таблице. Вторые 2 параметра - расстояние между
         * ячейками по горизонтали и вертикали
         */
        GridLayout layout = new GridLayout(2, 0, 5, 12);
        grid.setLayout(layout);
        // Создаем 8 кнопок
        for (int i = 0; i < 8; i++) {
            grid.add(new JButton("Кнопка " + i));
        }
        // Размещаем нашу панель в панели содержимого 
        getContentPane().add(grid);
        // Устанавливаем оптимальный размер окна
        pack();
        // Открываем окно
        setVisible(true);
    }
    public static void main(String[] args) {
        new GridLayoutTest();
    }
}

В примере задается произвольное количество столбцов. Для этого в конструкторе вместо конкретного числа столбцов указывается ноль. Аналогично можно задать и произвольное количество строк в таблице.

Интерфейс работы программы представлен на следующем скриншоте.

Если произвольно увеличить размер окна, то менеджер расположения GridLayout также занимает все место, доступное в данный момент в окне, и пропорционально увеличивает размеры компонентов. Если уменьшить окно, то GridLayout также пропорционально уменьшит размеры компонентов. Основные свойства менеджера табличного расположения :

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

Чаще всего совмещают панели с различными менеджерами расположения для получения необходимого интерфейса окна. В следующем примере совмещаем менеджер табличного расположения компонентов GridLayout с менеджером последовательного расположения FlowLayout, которое никогда не делает содержащиеся в нем компоненты больше их предпочтительного размера. Для этого создадим элемент пользовательского интерфейса, встречающийся практически в любом диалоговом окне, а именно строку кнопок (кнопки ОК и Отмена). Табличное расположение придаст кнопкам одинаковый размер, а последовательное расположение не даст им «расплыться» и заодно выровняет их по правому краю.


Пример совмещения табличного GridLayout и последовательного FlowLayout расположения компонентов

// Пример использования совмещенного табличного GridLayout и 
// последовательного FlowLayout расположения компонентов.

import java.awt.*;
import javax.swing.*;

public class ManagerLayoutsTest extends JFrame
{
    public ManagerLayoutsTest() {
        super("ManagerLayoutsTest");
        setSize(320, 240);
        setLocation(100, 100);
        setDefaultCloseOperation( EXIT_ON_CLOSE );
        // Создание панели с табличным расположением
        JPanel grid = new JPanel(new GridLayout(1, 2, 5, 0) );
        // Добавление кнопок в панель
        grid.add (new JButton("OK"    ));
        grid.add (new JButton("Отмена"));
        // Создание панели с последовательным расположением 
        // компонентов и выравниванием по правому краю
        JPanel flow = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        flow.add(grid);
        // Получение панели содержимого
        Container container = getContentPane();
        // Размещение панели с кнопками внизу справа
        container.add(flow, BorderLayout.SOUTH);
        // Открытие окна
        setVisible(true);
    }
    public static void main(String[] args) {
        new ManagerLayoutsTest();
    }

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


Менеджер расположения GridBagLayout

Менеджер расположения GridBagLayout подобно табличному менеджеру устанавливает компоненты в таблицу. Но он дает возможность определять для компонентов разную ширину и высоту колонок и строк таблицы. Фактически GridBagLayout позволяет получить абсолютно любое расположение компонентов.

Пример менеджера расположения GridBagLayout

// Пример использования менеджера расположения GridBagLayoutTest

import java.awt.*; 
import javax.swing.JButton; 
import javax.swing.JFrame; 

public class GridBagLayoutTest
{
    /**
     * Метод определения интерфейса панели
     * @param container
     */
    public static void createPanelUI(Container container)
    { 
        JButton button; 

        container.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); 
 
        container.setLayout(new GridBagLayout()); 
        GridBagConstraints constraints = new GridBagConstraints(); 
         
        // По умолчанию натуральная высота, максимальная ширина 
        constraints.fill = GridBagConstraints.HORIZONTAL; 
        constraints.weightx = 0.5;
        constraints.gridy   = 0  ;  // нулевая ячейка таблицы по вертикали    
        
        button = new JButton("Школа"); 
 
        constraints.fill = GridBagConstraints.HORIZONTAL; 
        constraints.gridx = 0;      // нулевая ячейка таблицы по горизонтали
        container.add(button, constraints); 
 
        button = new JButton("Институт"); 
        constraints.fill = GridBagConstraints.HORIZONTAL; 
        constraints.gridx = 1;      // первая ячейка таблицы по горизонтали
        container.add(button, constraints); 
         
        button = new JButton("Академия"); 
        constraints.fill = GridBagConstraints.HORIZONTAL; 
        constraints.gridx = 2;      // вторая ячейка таблицы по горизонтали
        container.add(button, constraints); 
 
        button = new JButton("Высокая кнопка размером в 2 ячейки"); 
        constraints.fill = GridBagConstraints.HORIZONTAL; 
        constraints.ipady     = 45;   // кнопка высокая 
        constraints.weightx   = 0.0; 
        constraints.gridwidth = 2;    // размер кнопки в две ячейки
        constraints.gridx     = 0;    // нулевая ячейка по горизонтали
        constraints.gridy     = 1;    // первая ячейка по вертикали
        container.add(button, constraints); 
 
        button = new JButton("Семья"); 
        constraints.fill = GridBagConstraints.HORIZONTAL; 
        constraints.ipady     = 0;    // установить первоначальный размер кнопки 
        constraints.weighty   = 1.0;  // установить отступ
                                      // установить кнопку в конец окна
        constraints.anchor    = GridBagConstraints.PAGE_END; 
        constraints.insets    = new Insets(5, 0, 0, 0);  // граница ячейки по Y 
        constraints.gridwidth = 2;    // размер кнопки в 2 ячейки 
        constraints.gridx     = 1;    // первая ячейка таблицы по горизонтали
        constraints.gridy     = 2;    // вторая ячейка по вертикали
        container.add(button, constraints);  
    } 

    public static void main(String[] args)
    {
        // Создание окна 
        JFrame frame = new JFrame("GridBagLayoutTest"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
         
        // Определить панель содержания 
        createPanelUI(frame.getContentPane()); 
 
        // Показать окно 
        frame.pack(); 
        frame.setVisible(true); 
    } 
}

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

Пользовательский интерфейс примера GridBagLayout представлен на следующих скриншотах. На нижнем скриншоте представлен интерфейс для уменьшенного размера окна.


Менеджер расположения CardLayout

Менеджер CardLayout можно использовать для создания так называемых вкладок (tabs), выбирая которые будут избранно открываться разные панели, занимающие одно и то же место в интерфейсе окна. В библиотеке Swing данную задачу можно решить с использованием класса JTabbedPane, организовывающего управление панелями с вкладками.

Пример менеджера расположения CardLayout

// Пример использования менеджера расположения CardLayoutTest

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class CardLayoutTest implements ItemListener
{ 
    private static JPanel cards;
    
    final   static String BUTTONPANEL = "Панель с кнопками"       ; 
    final   static String TEXTPANEL   = "Панель с текстовым полем"; 
     
    /**
     * Метод определения интерфейса панели
     * @param container - панель содержимого
     */
    public void createPanelUI(Container container)
    { 
        // Создание компонента с выпадающим списком 
        JComboBox<String> combobox = new JComboBox<String>(
                                      new String[] {BUTTONPANEL, TEXTPANEL}); 
        combobox.setEditable    (false); 
        combobox.addItemListener(this );
        
        // Помещаем JComboBox в JPanel для наглядности.
        JPanel cbPanel = new JPanel(); 
        cbPanel.add(combobox); 
 
        // Создание "cards". 
        JPanel card1 = new JPanel(); 
        card1.add(new JButton("Продукты")); 
        card1.add(new JButton("Одежда"  )); 
        card1.add(new JButton("Обувь"   )); 
 
        JPanel card2 = new JPanel(); 
        card2.add(new JTextField("TextField", 15)); 
         
        // Создаем панель с менеджером расположения CardLayout
        cards = new JPanel(new CardLayout());
        // Добавляем вкладки
        cards.add(card1, BUTTONPANEL); 
        cards.add(card2, TEXTPANEL); 
 
        container.add(cbPanel, BorderLayout.PAGE_START); 
        container.add(cards  , BorderLayout.CENTER    ); 
    } 
    // Обработчик события
    public void itemStateChanged(ItemEvent event)
    { 
        CardLayout layout = (CardLayout)(cards.getLayout());
        layout.show(cards, (String)event.getItem());
    } 
     
    public static void main(String[] args) 
         throws ClassNotFoundException, InstantiationException, 
                IllegalAccessException, UnsupportedLookAndFeelException 
    { 
        // Создание и настройка окна 
        final JFrame frame = new JFrame("CardLayoutTest"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        
        javax.swing.SwingUtilities.invokeLater(new Runnable() { 
            public void run() { 
                (new CardLayoutTest()).createPanelUI(frame.getContentPane()); 
                 
                // Открытие окна 
                frame.pack(); 
                frame.setVisible(true); 
            } 
        }); 
    } 
}

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


Менеджер расположения BoxLayout

Менеджер расположения BoxLayout позволяет управлять размещением компонентов либо в вертикальном, либо в горизонтальном направлениях и управлять пространством между компонентами, используя вставки. Для размещения компонентов в вертикальной плоскости необходимо конструктору передать константу BoxLayout.Y_AXIS, для размещения в горизонтальной - BoxLayout.X_AXIS.

Пример менеджера расположения BoxLayout

// Пример использования менеджера расположения BoxLayout

import java.awt.Component; 
import java.awt.Container; 
import javax.swing.JFrame; 
import javax.swing.JButton; 
import javax.swing.BoxLayout; 

public class BoxLayoutTest
{
    /**
     * Процедура добавления кнопки в контейнер
     * @param caption заголовок кнопки
     * @param container контейнер
     */
    private static void addButton(String caption, Container container)
    { 
        JButton button = new JButton(caption); 
        button.setAlignmentX(Component.CENTER_ALIGNMENT); 
        container.add(button); 
    } 
    /**
     * Процедура создания интерфейса формы 
     * @param container контейнер
     */
    public static void createUI(Container container) { 
        container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS)); 
        addButton("Хлеб"        , container); 
        addButton("Молоко"      , container); 
        addButton("Колбасы"     , container); 
        addButton("Мясо и птица", container); 
        addButton("Мороженные продукты", container); 
    } 
     
    public static void main(String[ ] args)
    { 
        // Создание окна 
        final JFrame frame = new JFrame("BoxLayoutTest"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

        // Определение интерфейса окна
        createUI(frame.getContentPane()); 
 
        javax.swing.SwingUtilities.invokeLater(new Runnable() { 
            public void run() { 
                // Открытие окна 
                frame.pack(); 
                frame.setVisible(true); 
            } 
        }); 
    } 
}

Пользовательский интерфейс примера менеджера расположения BoxLayout представлен на следующих скриншотах. На верхнем скриншоте представлен интерфейс окна с вертикальным расположением компонентов. На нижнем скриншоте компоненты размещены в горизонтальной плоскости.


Менеджер расположения GroupLayout

Менеджер расположения компонентов GroupLayout появился только в Java 6. Он раскладывает компоненты по группам. Группы имеют горизонтальное и вертикальное направление и могут быть параллельными и последовательными. В последовательной группе у каждого следующего компонента координата вдоль оси на единицу больше (имеется в виду координата в сетке), в параллельной – компоненты имеют одну и ту же координату.

Пример менеджера расположения GroupLayout

// Пример использования менеджера расположения GroupLayout

import javax.swing.*; 

import static javax.swing.GroupLayout.Alignment.*; 

public class GroupLayoutTest extends JFrame 
{ 
    public GroupLayoutTest() 
    { 
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
        // Список компонентов формы
        JLabel      label           = new JLabel("Поиск строки :"); 
        JTextField  textField       = new JTextField(); 
        JCheckBox   cbCaseSensitive = new JCheckBox("Учет регистра"); 
        JCheckBox   cbWholeWords    = new JCheckBox("Целое слово"  ); 
        JCheckBox   cbBackward      = new JCheckBox("Поиск назад"  ); 
        JButton     btnFind         = new JButton("Найти"   ); 
        JButton     btnCancel       = new JButton("Отменить"); 
         
        cbCaseSensitive.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); 
        cbWholeWords   .setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); 
        cbBackward     .setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); 
         
        // Определение менеджера расположения
        GroupLayout layout = new GroupLayout(getContentPane()); 
        getContentPane().setLayout(layout); 
        layout.setAutoCreateGaps(true); 
        layout.setAutoCreateContainerGaps(true); 
        // Создание горизонтальной группы
        layout.setHorizontalGroup(layout.createSequentialGroup() 
                .addComponent(label) 
                .addGroup(layout.createParallelGroup(LEADING) 
                        .addComponent(textField) 
                        .addGroup(layout.createSequentialGroup() 
                        .addGroup(layout.createParallelGroup(LEADING) 
                                .addComponent(cbCaseSensitive) 
                                .addComponent(cbBackward)) 
                        .addGroup(layout.createParallelGroup(LEADING) 
                                .addComponent(cbWholeWords)))) 
                .addGroup(layout.createParallelGroup(LEADING) 
                .addComponent(btnFind) 
                .addComponent(btnCancel)) 
        ); 
         
        layout.linkSize(SwingConstants.HORIZONTAL, btnFind, btnCancel); 
         
        // Создание вертикальной группы
        layout.setVerticalGroup(layout.createSequentialGroup() 
                .addGroup(layout.createParallelGroup(BASELINE) 
                        .addComponent(label) 
                        .addComponent(textField) 
                        .addComponent(btnFind)) 
                .addGroup(layout.createParallelGroup(LEADING) 
                .addGroup(layout.createSequentialGroup() 
                        .addGroup(layout.createParallelGroup(BASELINE) 
                                .addComponent(cbCaseSensitive)
                                .addComponent(cbWholeWords)) 
                        .addGroup(layout.createParallelGroup(BASELINE) 
                                .addComponent(cbBackward))) 
                .addComponent(btnCancel)) 
        ); 
         
        setTitle("Поиск"); 
        pack(); 
    } 
    public static void main(String args[])
    { 
        java.awt.EventQueue.invokeLater(new Runnable() { 
            public void run() {
                JFrame.setDefaultLookAndFeelDecorated(true);
                new GroupLayoutTest().setVisible(true); 
            } 
        }); 
    } 
}

Интерфейс окна примера менеджера расположения GroupLayout представлен на следующем скриншоте.


Менеджер расположения SpringLayout

Несмотря на универсальность менеджера расположения SpringLayout, действие его весьма специфично и не похоже на действие ни одного из уже рассмотренных выше менеджеров расположения.

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

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

Пример менеджера расположения SpringLayout

// Пример использования менеджера расположения SpringLayout

import java.awt.Component;
import java.awt.Container;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SpringLayout;

public class SpringLayoutTest
{
    public static void main(String args[])
    {
        JFrame frame = new JFrame("SpringLayoutTest");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container contentPane = frame.getContentPane();

        SpringLayout layout = new SpringLayout();
        contentPane.setLayout(layout);

        Component label = new JLabel("Метка");
        Component field = new JTextField(15);

        contentPane.add(label);
        contentPane.add(field);
        layout.putConstraint(SpringLayout.WEST , label, 10, 
                             SpringLayout.WEST , contentPane);
        layout.putConstraint(SpringLayout.NORTH, label, 25, 
                             SpringLayout.NORTH, contentPane);
        layout.putConstraint(SpringLayout.NORTH, field, 25, 
                             SpringLayout.NORTH, contentPane);
        layout.putConstraint(SpringLayout.WEST , field, 20, 
                             SpringLayout.EAST , label      );

        frame.setSize(300, 110);
        frame.setVisible(true);
    }
}

Интерфейс окна примера менеджера расположения SpringLayout представлен на следующем скриншоте.


Интерфейс диалогового окна авторизации

Интерфейс примера диалогового окна авторизации LoginDialog представлен на следующем скриншоте.

Исходный код примера LoginDialog в виду его большого размера не приводится. Но его можно скачать вместе с остальными примерами.

  Рейтинг@Mail.ru