Искусство расположения |
185 |
public class BoxRigidAreas extends JFrame { public BoxRigidAreas() {
super("BoxRigidAreas"); setSize(250, 200);
setDefaultCloseOperation( EXIT_ON_CLOSE ); // вертикальная панель
JPanel pVert = BoxLayoutUtils.createVerticalPanel(); pVert.add(new JButton("Один"));
// горизонтальная панель
JPanel pHor = BoxLayoutUtils.createHorizontalPanel(); pHor.add(new JButton("Два"));
//размер пространства задается в виде объекта
//Dimension из пакета java.awt pHor.add(Box.createRigidArea(new Dimension(50,120))); pHor.add(new JButton("Три"));
pVert.add(pHor);
//добавляем вертикальную панель в центр окна add(pVert);
//выводим окно на экран
setVisible(true);
}
public static void main(String[] args) { SwingUtilities.invokeLater(
new Runnable() {
public void run() { new BoxRigidAreas(); } });
}
}
В этом примере продемонстрирован наиболее вероятный вариант использования фиксированной области — в виде двух совмещенных распорок, горизонтальной и вертикальной.
Если вы знаете, что вам нужно разделить компоненты в обоих направлениях, можно ограничиться одной фиксированной областью. Обратите внимание, когда будете
186 |
ГЛАВА 7 |
запускать программу с примером — вертикальная панель снова уплывает куда-то к середине окна. Вскоре мы возьмем эту ситуацию под контроль, и любое расположение будет у нас в руках.
Проблема с распорками
Распорки совершенно необходимы при создании интерфейсов с применением блочного расположения компонентов, и как мы посмотрели, работа их выглядит вполне прозрачно — мы просто вставляем своеобразные «спички» между компонентами. Однако после рассмотрения заполнителей оказывается, что возникает недоразумение с распорками, созданными классом Box. Дело в том, что максимальный размер по второй оси (к примеру, по вертикали для горизонтальной распорки) неограничен. Как мы уже выяснили, блочное расположение при наличии свободного пространства в контейнере распределяет его поровну между компонентами, которые могут «расти», еще не достигнув максимального размера. Так вот, если в панели с блочным расположением по горизонтали имеются стандартные распорки, общий максимальный размер панели по вертикали будет неограничен, и это, как правило, совсем не тот эффект, которого мы хотим добиться. Тоже самое случится и с вертикальными распорками в вертикальной панели.
Поэтому лучше создать распорки самим, не применяя стандартные. Тут нам помогут фиксированные области, у которых одно расстояние будет распоркой, а второе всегда нулевым. Именно такое поведение нам и требуется при разделении компонентов. Добавим в наш вспомогательный класс BoxLayoutUtils еще пару удобных методов:
//com/porty/swing/BoxLayoutUtils.java
//Класс для удобной работы с менеджером BoxLayout package com.porty.swing;
import javax.swing.*;
public class BoxLayoutUtils
{
//создает горизонтальную распорку
//фиксированного размера
public static Component createHorizontalStrut(int size) { return Box.createRigidArea(new Dimension(size, 0));
}
//создает вертикальную распорку
//фиксированного размера
public static Component createVerticalStrut(int size) { return Box.createRigidArea(new Dimension(0, size));
}
// далее идут методы, описанные ранее
…
}
Наши распорки созданы на основе уже знакомых нам фиксированных областей и будут выполнять те же функции, что и стандартные распорки из класса Box, не устанавливая при этом неограниченным общий максимальный размер панели. А если нам понадобится увеличить максимальный размер панели, мы всегда можем сделать это вручную.
Искусство расположения |
187 |
Выравнивание компонентов по осям
Выравнивание по осям — достаточно каверзный аспект работы менеджера BoxLayout, и если не знать деталей, расположение вполне может получиться абсолютно противоположным тому, что изначально задумывалось. Вам может даже показаться, что поведение компонентов при блочном расположении вообще непредсказуемо. Впрочем, не все так страшно, и мы постараемся без особых трудностей справиться с выравниванием по осям.
Каждый компонент (унаследованный от класса java.awt.Component) имеет два параметра, служащие для его выравнивания по осям X и Y, то есть для его более точного размещения в контейнере. Что это за оси? Рассмотрим сначала вертикальную панель, где компоненты располагаются сверху вниз. Мы можем захотеть изменить горизонтальную позицию компонентов (то есть позицию по оси X) такой панели (вертикальные позиции жестко заданы положением компонентов, распорок и заполнителей) — поместить их слева, справа или по центру. Так вот, сделать это путем выравнивания по осям нельзя.
ВНИМАНИЕ
Выравнивание компонентов по осям не позволяет, как это может показаться на первый взгляд, изменить позицию компонентов относительно контейнера. Эти параметры задают положение компонентов относительно друг друга, то есть относительно остальных компонентов, размещенных в контейнере. То есть попытки использовать механизм выравнивания по осям так же, как и при последовательном расположении (FlowLayout), приведут к неудаче.
На самом деле расположение компонента с определенным выравниванием будет зависеть исключительно от выравнивания и размеров остальных компонентов. Для горизонтального выравнивания в классе Component определены следующие константы:
Component.CENTER_ALIGNMENT — вертикальная ось будет проходить через середину компонента;
Component.LEFT_ALIGNMENT — компонент будет прижат к вертикальной оси своей левой границей;
Component.RIGHT_ALIGNMENT — компонент будет прижат к вертикальной оси своей правой границей.
При блочном расположении положение вертикальной оси определяется по компонентам с центральным выравниванием, а уже после этого компоненты с другими параметрами выравнивания размещаются относительно этой оси. Окончательно разъясняет ситуацию рис. 7.2.
LEFT |
LEFT |
RIGHT |
CENTER |
LEFT |
RIGHT |
RIGHT |
LEFT |
RIGHT |
Рис. 7.2. Блочное расположение с горизонтальным выравниванием
188 |
ГЛАВА 7 |
Наиболее общий случай показан на рисунке слева. Здесь также можно безболезненно удалить один из трех компонентов — Когда в контейнере присутствуют два или три компонента с неодинаковым выравниванием, расположение всегда имеет такой вид. На двух других схемах показано, что происходит, если все компоненты имеют одинаковое выравнивание, причем компоненты с выравниванием по центру отсутствуют. Такое расположение действительно напоминает расположение FlowLayout (только не по горизонтали, а по вертикали), оно интуитивно понятно и предсказуемо. Блочное расположение становится одновременно мощным и достаточно простым именно тогда, когда все компоненты в контейнере выровнены согласованно, и в дальнейшем мы так и будем задавать параметры выравнивания. А пока, чтобы не быть голословными, убедимся, что все действительно так и работает:
//BoxAlignment.java
//Как блочное расположение обеспечивает выравнивание
//компонентов по осям
import javax.swing.*;
import com.porty.swing.BoxLayoutUtils;
public class BoxAlignment extends JFrame { public BoxAlignment() {
super("BoxAlignment"); setSize(400, 150);
setDefaultCloseOperation( EXIT_ON_CLOSE ); // вертикальная панель
JPanel pv = BoxLayoutUtils.createVerticalPanel();
//кнопка с выравниванием по левой границе
JButton jb = new JButton("Левая граница"); jb.setAlignmentX(LEFT_ALIGNMENT); pv.add(jb);
//копка с центральным выравниванием
jb = new JButton("Выравнивание по центру"); jb.setAlignmentX(CENTER_ALIGNMENT); pv.add(jb);
//наконец, кнопка с выравниванием по правому краю jb = new JButton("Правая граница"); jb.setAlignmentX(RIGHT_ALIGNMENT);
pv.add(jb);
//добавляем панель в центр окна
add(pv);
// выводим окно на экран setVisible(true);
}
public static void main(String[] args) { SwingUtilities.invokeLater(
Искусство расположения |
189 |
new Runnable() {
public void run() { new BoxAlignment(); } });
}
}
Запустите программу с примером и посмотрите на результат. Чтобы окончательно освоиться с выравниванием по осям при блочном расположении, вы можете поэкспериментировать с этим примером, изменяя выравнивание компонентов по своему вкусу. Если у вас есть под рукой хорошая среда визуального построения пользовательского интерфейса с поддержкой блочного расположения (например, NetBeans), проведите опыты с ее помощью.
Аналогично обстоит дело с вертикальным выравниванием (по оси Y). Требуется такое выравнивание в панелях с горизонтальным расположением компонентов, и позволяет изменить вертикальные позиции компонентов относительно друг друга (горизонтальные позиции задаются самим расположением). В классе Component для вертикального выравнивания определены следующие константы:
Component.CENTER_ALIGNMENT — горизонтальная ось будет проходить через середину компонента;
Component.TOP_ALIGNMENT — компонент будет прижат к горизонтальной оси своей верхней границей;
Component.BOTTOM_ALIGNMENT — компонент будет прижат к горизонтальной оси своей нижней границей.
Как и ранее, для компонента с центральным выравниванием ось будет проходить через его середину (рис. 7.3, слева).
TOP |
TOP |
TOP |
BOTTOM |
|
|
CENTER |
|
|
TOP |
|
|
Рис. 7.3. Блочное расположение с вертикальным выравниванием
Если все компоненты имеют выравнивание TOP_ALIGNMENT, то ось проходит сверху контейнера, а все компоненты прижимаются к ней верхней границей, как показано справа на рис. 7.3. Схема для выравнивания BOTTOM_ALIGNMENT выглядит аналогично,