Какой менеджер компоновок позволяет разместить компоненты в таблице с ячейками равного размера
Перейти к содержимому

Какой менеджер компоновок позволяет разместить компоненты в таблице с ячейками равного размера

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

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

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

  • Полярное расположение BorderLayout
  • Последовательное расположение FlowLayout
  • Табличное расположение GridLayout
  • Менеджер расположения GridBagLayout
  • Менеджер расположения CardLayout
  • Менеджер расположения BoxLayout
  • Менеджер расположения GroupLayout
  • Менеджер расположения SpringLayout
  • Пример диалогового окна авторизации
  • Пример собственного менеджера расположения

Исходные коды примеров различных менеджеров расположения, рассмотренных на странице можно скачать здесь (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 пикселов и использует для всех компонентов предпочтительный размер.

Менеджер расположения 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.NORTH North Компонент располагается вдоль верхней границы окна и растягивается на всю его ширину. Обычно в этом месте размещается панель инструментов.
BorderLayout.SOUTH South Компонент располагается вдоль нижней границы и растягивается на всю ширину окна. Такое положение характерно для строки состояния.
BorderLayout.WEST West Компонент располагается вдоль левой границы окна и растягивается на всю его высоту; при этом учитываются размеры северных и южных компонентов, имеющих приоритет.
BorderLayout.EAST East Компонент располагается вдоль правой границы окна. В остальном его расположение аналогично западному компоненту.
BorderLayout.CENTER Center Компонент помещается в центр окна, занимая максимально возможное пространство.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Java. Swing. Основы

В стандарт Java входит два пакета для создания оконного пользовательского интерфейса: awt и его надстройка swing. Компоненты swing имеют расширенные возможности по сравнению с аналогичными awt компонентами, поэтому упор будет сделан на них. Во-вторых, в отличие от awt компоненты swing не содержат платформо-зависимого кода. Так сказать являются облегченными (lightweight) компонентами.

контейнеры верхнего уровня

  • JApplet — главное окно апплета;
  • JFrame — окно приложения;
  • JDialog — диалог приложения.
  • JColorChooser — диалог выбора цвета;
  • JFileChooser — диалог выбора файлов и директорий;
  • FileDialog — диалог выбора файлов и директорий (awt компонент).

простые контейнеры

  • JPanel — простая панель для группировки элементов, включая вложенные панели;
  • JToolBar — панель инструментов (обычно это кнопки);
  • JScroolPane — панель прокрутки, позволяющая прокручивать содержимое дочернего элемента;
  • JDesktopPane — контейнер для создания виртуального рабочего стола или приложений на основе MDI (multiple-document interface);
  • JEditorPane, JTextPane — контейнеры для отображения сложного документа как HTML или RTF;
  • JTabbedPane — контейнер для управления закладками;
  • JSplitPane — контейнер, разделяющий два элемента и позволяющий пользователю изменять их размер.

элементы интерфейса

Следующие элементы управления могут использоваться и как контейнеры, так как наследуются от класса java.awt.Container.

  • JButton — кнопка;
  • JCheckBox — кнопка-флажок;
  • JComboBox — выпадающий список;
  • JLabel — метка, надпись;
  • JList — список;
  • JPasswordField — текстовое поле для скрытого ввода;
  • JProgressBar — компонент для отображения числа в некотором диапазоне;
  • JRadioButton — преключатели, радио-кнопки, обычно используется с
    компонентом ButtonGroup;
  • JSlider — компонент позволяющий выбрать значение из заданного диапазона;
  • JSpinner — компонент позволяющий выбрать значение из указанной последовательности;
  • JTable — таблица;
  • JTextField — однострочное текстовое поле;
  • JTextArea — многострочное текстовое поле;
  • JTree — дерево.

управление позиционированием и размерами

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

Ниже приведен список стандартных компоновщиков:

  • BorderLayout — размещает элементы в один из пяти регионов, как было указано при добавлении элемента в контейнер:
    наверх, вниз, влево, вправо, в центр;
  • FlowLayout — размещает элементы по порядку в том же направлении, что и ориентация контейнера (слева на право по умолчанию)
    применяя один из пяти видов выравнивания, указанного при создании менеджера.
    Данный менеджер используется по умолчанию в большинстве контейнерах;
  • GridLayout — размещает элементы таблично. Колличество столбцов и строк указывается
    при создании менеджера. По умолчанию одна строка, а число столбцов равно числу элементов;
  • BoxLayout — размещает элементы по вертикали или по горизонтали. Обычно он используется не
    напрямую а через контейнерный класс Box, который имеет дополнительные возможности;
  • SpringLayout — это менеджер низкого уровня и был разработан для программ
    построителей форм;
  • GroupLayout — данный менеджер также был разработан для построителей форм.

события

Элементы интерфейса и контейнеры генерируют ряд событий, например:

  • ActionEvent — событие, определяемое компонентом, например нажатие кнопки;
  • ComponentEvent — генерируется, когда позиция, размер или видимость компонента изменяются;
  • ContainerEvent — генерируется при добавлении или удалении элемента из контейнера;
  • FocusEvent — генерируется при получении или потери фокуса ввода компонентом;
  • ItemEvent — событие выбора или отменены выбора элемента.
    Например, изменение состояния кнопки-флажка, выбор элемента меню или списка;
  • KeyEvent — событие ввода с клавиатуры;
  • MouseEvent — события мыши;
  • WindowEvent — события окна, как активация и свертывание.

Для обработки событий элемента в нем необходимо зарегистрировать объект обработчик
в числе слушателей. Делается это методами типа addxxxListener, например addMouseListener(). В качестве объектов обработчиков обычно выбирают контейнер, в котором содержится элемент.Обработка события осуществляется через соответствующий интерфейс, например:

  • ActionListener — интерфейс обработки события ActionEvent;
  • ItemListener — интерфейс обработки события ItemEvent;
  • KeyListener — интерфейс обработки события KeyEvent;
  • MouseListener — интерфейс обработки события MouseEvent, для нажатия/отжатия кнопок и входа/ухода курсора мыши с
    области компонента;
  • MouseMotionListener — интерфейс обработки события MouseEvent, для движение курсора мыши или перетаскивании мышью;
  • MouseWheelListener — интерфейс обработки события MouseEvent, для прокрутки
    колеса мыши.

Если весь интерфейс реализовывать не нужно, например, нужен только
один из методов, то можно воспользоваться адаптерами.

Первое оконное приложение с использованием Java Swing

Обычно оконное приложение состоит из одного и более окон и диалогов.
В отличие от простых контейнеров контейнеры верхнего уровня имеют более сложную внутреннюю структуру. Для них автоматически создается корневой контейнер — объект класса JRootPane, который можно получить методом getRootPane(). Внутри корневого создаются еще дваобъекта: слойный контейнер и объект представляющий окно как компонент.

В большинстве случаев в слойном контейнере используются первых два контейнера слоя. Первый для хранения большинства элементов управления окна, так сказать клиентская область окна. Для доступа к нему прямо из окна используется метод getContentPane, также его можно заменить любым другим контейнером методом setContentPane(). Второй контейнер слой используется для хранения меню, панелей инструментов и т.п. Например, панель меню, добавляемая к окну, методом setJMenuBar() сохраняется именно там.

Методом getGlassPane можно получить объект представляющий окно как компонент для обработки событий или рисования поверх всех других компонент.

Ниже приведен минимальный шаблон оконного приложения.
Классы MyPanel и MyComponent — пользовательские классы, которые будут реализованы в некоторыхследующих примерах для демонстрации возможностей swing. Вам остается просто скопировать со страницы код MyPanel/MyComponent в проект со шаблоном, подправить шаблон и запустить его.

Ниже приведен более сложный пример с несколькими дочерними элементами и обработкой
событий.

Компоновщики

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

стандартные компоновщики

  • BorderLayout — размещает элементы в один из пяти регионов, как было указано при добавлении элемента в контейнер: наверх, вниз, влево, вправо, в центр. По умолчанию элемент добавляется в центр. Если в указанном регионе уже есть элемент, то он замещается новым. Поэтому, когда надо разместить несколько элементов в одном регионе, то их объединяют в один контейнер (обычно JPanel);
  • FlowLayout — размещает элементы по порядку в том же направлении, что
    и ориентация контейнера (слева на право по умолчанию)
    применяя один из пяти видов выравнивания, указанного при создании менеджера.
    Данный менеджер используется по умолчанию;
  • GridLayout — размещает элементы таблично. Колличество столбцов и строк указывается при создании менеджера. По умолчанию одна строка, а число столбцов равно числу элементов. Вся область контейнера разбивается на ячейки и размер каждого элемента устанавливается в размерячейки. Это больше подходит для выравнивания панелей и других контейнеров, а не элементов управления (нам ведь не нужны гигантские кнопки);
  • BoxLayout — размещает элементы по вертикали или по горизонтали.
    Обычно он используется не напрямую, а через контейнерный класс Box (ящик).

точное позиционирование и задание размеров

Если в контейнере отсутствует компоновщик (был вызван метод контейнера setLayout(null)), то позицию и размеры элементов необходимо задать явно методами элемента

  • setLocation(Point p) — переместить компонент в указанную точку;
  • setLocation(int x, int y) — переместить компонент в указанную точку;
  • setSize(Dimension d) — установить размеры компонента;
  • setSize(int width, int height) — установить размеры компонента;
  • setBounds(Rectangle r) — переместить и установить размеры компонента
    (вписать в четырехугольник);
  • setBounds(int x,int y, int width, int height) — переместить и установить
    размеры компонента.

предпочтительные размеры

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

  • getMaximumSize() — получение максимального размера;
  • setMaximumSize(Dimension d) — установка максимального размера;
  • getMinimumSize() — получение минимального размера;
  • setMinimumSize(Dimension d) — установка минимального размера;
  • getPreferredSize() — получение желательного размера;
  • setPreferredSize(Dimension d) — установка желательного размера.

компоновщики низкого уровня

Существует также два компоновщика низкого уровня, разработанных для программ построителей форм SpringLayout и GroupLayout. В
документации
для SpringLayout можно скачать файлик SpringUtilities.java, где реализованы два полезных способа компоновки на его основе (как там сказано просто вызываем методы из этого файла, не вникая в детали:).

класс Box

Класс Box реализует контейнер с компоновщиком BoxLayout. Если элементы размещаются по горизонтали, то высота всех элементов равна высоте самого высокого элемента.А ширина элементов такова, чтобы заполнить весь контейнер по ширине.
При изменении ширины контейнера элементы растягиваются пропорционально. Если у всех элементов достигнут предел растяжения (значение getMaximumSize()), то первый элемент растягивается насильно. Если остается хотя бы один элемент доступный для растяжения, то растягивается только он.

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

Класс Box имеет статические методы для создания невидимых элементов для различных целей:

  • createHorizontalStrut(int width) — создает компонент с фиксированной шириной. При горизонтальной укладке элемент используется чтобы освободить пространство между соседними элементами, иначе элементы будут впритык. При вертикальной укладке элемент используется для задания минимальной ширины остальных элементов;
  • createVerticalStrut(int height) — создает компонент с фиксированной высотой. При вертикальной укладке элемент используется чтобы освободить пространство между соседними элементами, иначе элементы будут впритык. При горизонтальной укладке элемент используется для задания минимальной высоты остальных элементов;
  • createRigidArea(Dimension d) — создает невидимый элемент фиксированного размера;
  • createGlue() — создает невидимый растягиваемый компонент. Используется, чтобы предотвратить насильное растяжение элементов. Например, пусть в контейнере видимые элементы фиксированного размера. Тогда положив данный компонент в начало и в конец контейнера, мы получим центрирование видимых элементов. А если расположить его после каждого видимого, то при увеличении размера контейнера, видимые элементы «разойдутся» друг от друга.

пример использования компоновщиков

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

Введение в JavaFx и работа с layout в примерах

Доброго времени суток. В этой статье я расскажу основы работы с классами пакета javafx.scene.layout.* (BorderPane, AnchorPane, StackPane, GridPane, FlowPane, TilePane, HBox, VBox) и их особенностями в пошаговых примера и иллюстрациях. Также в кратце пробежимся по иерархии классов JavaFx.

После установки Eclipse и плагина e(fx)lipse создадим новый проект:

Выбираем JavaFx проект:

По дефолту Eclipse создаст такую заготовку:

На сцену добавляется корневой узел, им должен быть класс унаследованный от Parent (узел, который может иметь детей) корневой узел добавляется на сцену (специальный контейнер для всего контента графа узлов), а она в свою очередь на стейжд, который и показывается.

Давайте разберемся с иерархией классов JavaFx:

Самым базовым абстрактным классом является Node — узел в графе сцены, наследникам предоставляются поля для настройки размеров: (minWidth — минимальная ширина, minHeight — минимальная высота, prefWidth — предпочтительная ширина, prefHeight — предпочтительная высота, maxWidth — максимальная ширина, maxHeight — максимальная высота).

Координаты узла: getLayoutX() и getLayoutY()
relocate(double x, double y) — изменяет координаты узла, если необходимо настроить положение каждой координаты по отдельности, используйте setLayoutX(double value) и setLayoutY(double value)

Важно понимать, что выставленные координаты и размеры (pref то есть prefer — предпочтительно) при компоновке, в зависимости от иерархии графа узлов и их настроек могу отличаться от ожидаемых. Примеры приведу чуть позже.

Node не может содержать дочерних элементов это и логично, для этого существует Parent прямой наследник Node, в который можно добавлять и удалять дочерние узлы. Кстати, говоря, есть классы которые представляю узлы, но не содержат дочерние узлы: Camera, Canvas, ImageView, LightBase, MediaView, Parent, Shape, Shape3D, SubScene, SwingNode.

Нас сегодня интересует подгруппа наследников класса Region (базовый класс всех лайуат контейнеров) в частности поговорим о основных потомках класса Pane о панелях, которые чаще всего требуются в повседневной разработке.

BorderPane

Это специальная панель которая располагает свою дочерние узлы верхней(setTop(Node)), нижней(setBottom(Note)), левой(setLeft(Node)), правой(setRight(Node)) и центральной(setCenter(Node)) позициях, добавим несколько кнопок во все эти позиции на BotderPane:

У секции top и bottom приоритет, поэтому они сужаю по высоте все остальные:

При попытке задать координаты к примеру у верхней кнопки:

Кнопка не изменит своего положения, почему так происходит? При компоновке детей в методе layoutChildren класса BorderPane переопределяется позиция каждого узла с учетом всех настроек. Решений исправить есть несколько, например поместить (обернуть) кнопку в дополнительный подходящий контейнер, например в базовую для всех панелей

Потому как Pane никак не переопределяет положение своих детей, мы получаем нужное смещение:

Можно не оборачивать кнопку, а просто выставить у нее внешний отступ c помощью статического метода setMargin(Node child, Insets value):

Insets — вспомогательный класс для настройки отступов, конструктор у него перегружен, может принимать один аргумент для все сторон, так и для каждой стороны в отдельности, пока мы настроили для все сторон один отступ, вот что мы получили:

Уберем отступы снизу и справа и получим желаемое смещение кнопки:

StackPane

Теперь давайте рассмотрим ситуацию в которой панель навязывает детям не только позицию, но и пытается их растянуть по всей ширине и высоте, заполнив всю область контента, заменим BorderPane и добавим туда сначала TextArea и Button.

Кстати, для добавления нескольких узлов в нужном порядке можно использовать метод:

Что мы видим, текстовое поле растянулись по нашей панели, а кнопка центрировалась:

Центрирование можно корректироваться с помощью setAlignment(Pos)

Сделать внутренний отступ с помощью setPadding(Insets)

Можно сделать индивидуальную настройку центрирования и отступов каждого узла с помощью статических методов:

AnchorPane

Якорная панель позволяет края дочерних узлов привязывать смещениями к краям панели, рассмотрим пример:

Добавим кнопку и привяжем ее к правому краю:

AnchorPane root = new AnchorPane();
Button button = new Button(«Button in AnchorPane»);
root.getChildren().add(button);
AnchorPane.setRightAnchor(button, 10.0);

Добавим привязку к нижнему краю:

Теперь в левому краю и верхнему:

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

GridPane

Рассмотрим очень полезную сеточную панель, добавление детей в эту панель необходимо делать через метод add(Node child, int columnIndex, int rowIndex) в котором первый параметр добавляемый узле, второй номер колонки, третий номер строки, вот простой пример:

Мы видим, что узлы можно добавлять в любую ячейку, пустые столбцы и строки создаются автоматически:

Для работы с колонками, есть специальный класс ColumnConstraints, для этого надо создать колонки, настроить их и добавить их в GridPane, в примеру если мы хотим выставить ширины первой колонки 130, а второй 20%:

Это самые базовые возможности, потребуется написать отдельную статья, для охвата всех тонкостей настройки GridPane.

FlowPane

Давайте сразу к примеру из него сразу станет все понятно, добавим шесть кнопок в FlowPane:

Посмотрим результат, кнопка выводятся одна за другой (по дефолту у FlowPane горизонтальный вывод Orientation.HORIZONTAL)


Теперь при уменьшении окна по ширине, мы видим что дочерние узлы начинают переносится:


И соответственно если выставить вертикальную ориентацию


При при уменьшении высоты окна получаем перенос:

Вертикальные и горизонтальные отступы между элементами можно настроиться с помощью:

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


Как мы видим все узлы теперь находятся в «тайла» одинаковых размеров, растянутых по наибольшему узлу.

HBox и VBox

Это обычные горизонтальный и вертикальный списки, комбинируйте их, чтобы добиться нужного результата:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *