Размещение компонентов


В предыдущей главе мы размешали компоненты "вручную", задавая их размеры и положение в контейнере абсолютными координатами в координатной системе контейнера. Для этого мы применяли метод setBounds().
Такой способ размешает компоненты с точностью до пиксела, но не позволяет перемещать их. При изменении размеров окна с помощью мыши компоненты останутся на своих местах, привязанными к левому верхнему углу контейнера. Кроме того, нет гарантии, что все мониторы отобразят компоненты так, как вы задумали.
Чтобы учесть изменение размеров окна, надо задать размеры и положение компонента относительно размеров контейнера, например, так:
int w = getSizef).width;              // Получаем ширину 
int h = getSizeO.height;             //и высоту контейнера 
Button Ь = new Button("OK"); // Создаем кнопку 
b.setBounds(9*w/20, 4*h/5, w/10, h/10);
и при всяком изменении размеров окна задавать расположение компонента заново.
Чтобы избавить программиста от этой кропотливой работы, в библиотеку AWT внесены два интерфейса: LayoutManager и порожденный от него интерфейс LayoutManager2, а также пять реализаций этих интерфейсов: классы BorlerLayout, CardLayout, FlowLayout, GridLayout И GridBagLayout. Эти классы названы менеджерами размещения (layout manager) компонентов.
Каждый программист может создать свои менеджеры размещения, реализовав интерфейсы LayoutManager или LayoutManager2.
Посмотрим, как размещают компоненты эти классы.
Менеджер FlowLayout
Наиболее просто поступает менеджер размещения FlowLayout. Он укладывает в контейнер один компонент за другим слева направо как кирпичи, переходя от верхних рядов к нижним. При изменении размера контейнера "кирпичи" перестраиваются, как показано на  1. Компоненты поступают в том порядке, в каком они заданы в методах add ().
В каждом ряду компоненты могут прижиматься к левому краю, если в конструкторе аргумент align равен FlowLayout. LEFT, к правому краю, если этот аргумент FlowLayout. RIGHT, или собираться в середине ряда, если FlowLayout.CENTER.
Между компонентами можно оставить промежутки (gap) по горизонтали hgap и вертикали vgap. Это задается в конструкторе:
FlowLayout(int align, int hgap, int vgap)
Второй конструктор задает промежутки размером 5 пикселов:
FlowLayout(int align)
Третий конструктор определяет выравнивание по центру и промежутки 5 пикселов:
FlowLayout()
После формирования объекта эти параметры можно изменить методами:
setHgapfint hgap) setVgap(int vgap) setAlignment(int align)
В листинге 11.1 создаются кнопка Button, метка Label, кнопка выбора checkbox, раскрывающийся список choice, поле ввода TextFieid и все это размещается в контейнере Frame. Рис. 11.1 содержит вид этих компонентов
при разных размерах контейнера. 
Листинг 11.1 . Менеджер размещения FlowLayout 
import j ava.awt.*; 
import j ava.awt.event.*;
class FlowTest extends Frame{ 
FlowTest(String s) { 
super(s);
setLayout (new FlowLayout (FlowLayout.LEFT, 10, 10)); 
add(new Button("Кнопка")); 
add(new Label("Метка")); 
add(new Checkbox("Выбор"));
add(new Choice()); 
add(new TextFieldt"Справка", 10)); 
setSize(300, 100); setVisible(true); 

public static void main(String[] args){
Frame f= new FlowTest(" Менеджер FlowLayout"); 
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev){
System.exit(0); 
}
}); 

}

 
Менеджер BorderLayout


Менеджер размещения BorderLayout делит контейнер на пять неравных областей, полностью заполняя каждую область одним компонентом, как показано на  2. Области получили географические названия NORTH, SOUTH, WEST, EAST И CENTER.
Метод add о в случае применения BorderLayout имеет два аргумента: ссылку на компонент сотр и область region, в которую помещается компонент — одну из перечисленных выше констант:
add(Component comp, String region)
Обычный метод add (Component comp) с одним аргументом помещает компонент В область CENTER .
В классе два конструктора:

  • BorderLayout () — между областями нет промежутков;
  • BorderLayout(int hgap int vgap) — между областями остаются горизонтальные hgap и вертикальные vgap промежутки, задаваемые в пикселах.

Если в контейнер помещается менее пяти компонентов, то некоторые области не используются и не занимают места в контейнере, как можно заметить на  3. Если не занята область CENTER , то компоненты прижимаются к границам контейнера.
В листинге 11.2 создаются пять кнопок, размещаемых в контейнере. Заметьте отсутствие установки менеджера в контейнере setLayout () — менеджер BorderLayout установлен в контейнере Frame по умолчанию. Результат размещения показан на  2.
Листинг 11.2. Менеджер размещения BorderLayout 
import java.awt.*; 
import ]ava.awt.event.* ;
class BorderTest extends Frame{ 
BorderTest(String s){ super(s);
add(new Button("North"), BorderLayout.NORTH); 
add(new Button("South"), BorderLayout.SOUTH); 
add(new Button("West"), BorderLayout.WEST); 
add(new Button("East"), BorderLayout.EAST); 
add(new Button("Center")); 
setSize(300, 200); 
setVisible(true); 

public static void main(String[] args){
Frame f= new BorderTest(" Менеджер BorderLayout"); 
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev){
System.exit(0); 
}
});

}
Менеджер размещения BorderLayout кажется неудобным: он располагает не больше пяти компонентов, последние растекаются по всей области, области имеют странный вид. Но дело в том, что в каждую область можно поместить не компонент, а панель, и размещать компоненты на ней, как сделано в листинге 11.3 и показано на  3. Напомним, что на панели Panel менеджер размещения по умолчанию FiowLayout.
Листинг 11.3. Сложная компоновка 
import j ava.awt.*; 
import java.awt.event.*;
class BorderPanelTest extends Frame{ 
BorderPanelTest(String s){ 
super(s);
    // Создаем панель р2 с тремя кнопками 
Panel p2 = new Panel();
p2.add(new Button("Выполнить")); 
p2.add(new Button("Отменить")); 
p2.add(new Button("Выйти"));
Panel pi = new Panel ();
pi.setLayout(new BorderLayout());
    // Помещаем панель р2 с кнопками на "юге" панели р1 
p1.add(p2, BorderLayout.SOUTH);
    // Поле ввода помещаем на "севере" 
p1.add(new TextFieldt"Поле ввода", 20), BorderLayout.NORTH);
    // Область ввода помещается в центре 
p1.add(new TextArea("Область ввода", 5, 20, TextArea.SCROLLBARS_NONE), BorderLayout.CENTER);
add(new Scrollbar(Scrollbar.HORIZONTAL), BorderLayout.SOUTH); 
addfnew Scrollbar(Scrollbar.VERTICAL), BorderLayout.EAST);
    // Панель p1 помещаем в "центре" контейнера add(p1, BorderLayout.CENTER); 
setSizePOO, 200); 
setVisible(true) ; 

public static void main(String[] args){
Frame f= new BorderPanelTest(" Сложная компоновка"); 
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev){
System.exit(0); 
}
}); 

}
 
Менеджер GridLayout
Менеджер размещения GridLayout расставляет компоненты в таблицу с заданным в конструкторе числом строк rows и столбцов columns:
GridLayout(int rows, int columns)
Все компоненты получают одинаковый размер. Промежутков между компонентами нет.
Второй конструктор позволяет задать промежутки между компонентами в пикселах по горизонтали hgap и вертикали vgap:
GridLayout(int rows, int columns, int hgap, int vgap)
Конструктор по умолчанию GridLayout о задает таблицу размером 0x0 без промежутков между компонентами. Компоненты будут располагаться в одной строке.
Компоненты размещаются менеджером GridLayout слева направо по строкам созданной таблицы в том порядке, в котором они заданы в методах add().
Нулевое количество строк или столбцов означает, что менеджер сам создаст нужное их число.
В листинге 11.4 выстраиваются кнопки для калькулятора, а  4 показывает, как выглядит это размещение.
Листинг 11.4. Менеджер GridLayout 
import Java.awt.*;
import j ava.awt.event.*;
import java.util.*;
class GridTest extends Frame{ 
GridTest(String s){ super(s); 
setLayout(new GridLayout(4, 4, 5, 5));
StringTokenizer st =
new StringTokenizer("7 89/456*123-0.=+"); 
while(st.hasMoreTokens())
add(new Button(st.nextToken()));
setSize(200, 200); setvisible(true); 

public static void main(String[] args){
Frame f= new GridTestt" Менеджер GridLayout"); 
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev){
System.exit(0); 
}
}); 

}
Менеджер Card Lay out
Менеджер размещения cardLayout своеобразен — он показывает в контейнере только один, первый (first), компонент. Остальные компоненты лежат под первым в определенном порядке как игральные карты в колоде. Их расположение определяется порядком, в котором написаны методы add (). Следующий компонент можно показать методом next (Container с), предыдущий — методом previous (Container с), Последний— методом last (Container с), первый — методом first (Container с). Аргумент этих методов — ссылка на контейнер, в который помещены компоненты, обычно this.
В классе два конструктора:

  • СardLayout () — не отделяет компонент от границ контейнера;
  • CardLayout (int hgap, int vgap) — задает горизонтальные hgap и вертикальные vgap поля.

Менеджер CardLayout позволяет организовать и произвольный доступ к компонентам. Метод add () для менеджера CardLayout имеет своеобразный вид:
add(Component comp, Object constraints)
Здесь аргумент constraints должен иметь тип string и содержать имя компонента. Нужный компонент с именем name можно показать методом:
show(Container parent, String name)
В листинге 11.5 менеджер размещения c1 работает с панелью р, помещенной в "центр" контейнера Frame. Панель р указывается как аргумент parent в методах next () и show (). На "север" контейнера Frame отправлена панель р2 с меткой и раскрывающимся списком ch. Рис. 11.5 демонстрирует результат работы программы.
Листинг 11.5. Менеджер CardLayout 
import j ava.awt.*; 
import j ava.awt.event.*;
class CardTest extends Frame{ CardTest(String s){ 
super(s);
Panel p = new Panel();
CardLayout cl = new CardLayout();
p.setLayout(cl);
p.add(new Button("Русская страница"),"pagel");
p.add(new Button("English page"), "page2");
p.add(new Button("Deutsche Seite"), "pageЗ");
add(p);
cl.next(p);
cl.show(p, "pagel");
Panel p2 = new Panel();
p2.add(new Label("Выберите язык:"));
Choice ch = new Choice(); 
ch.add("Русский"); 
ch.add("Английский"); 
ch.add("Немецкий");'
p2.add(ch);
add(p2, BorderLayout.NORTH);
setSize(400, 300); 
setvisible(true); }
public static void main(String[] args){
Frame f= new CardTest{" Менеджер CardLayout"); 
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev){
System.exit(0); 
}
}); 

}
Менеджер GridBagLayout
Менеджер размещения GridBagLayout расставляет компоненты наиболее гибко, позволяя задавать размеры и положение каждого компонента. Но он оказался очень сложным и применяется редко.
В классе GridBagLayout есть только один конструктор по умолчанию, без аргументов. Менеджер класса GridBagLayout, в отличие от других менеджеров размещения, не содержит правил размещения. Он играет только организующую роль. Ему передаются ссылка на компонент и правила расположения этого компонента, а сам он помещает данный компонент по указанным правилам в контейнер. Все правила размещения компонентов задаются в
Объекте другого класса, GridBagConstraints.
Менеджер размещает компоненты в таблице с неопределенным заранее числом строк и столбцов. Один компонент может занимать несколько ячеек этой таблицы, заполнять ячейку целиком, располагаться в ее центре, углу или прижиматься к краю ячейки.
Класс GridBagConstraints содержит одиннадцать полей, определяющих размеры компонентов, их положение в контейнере и взаимное положение, и несколько констанГ — значений некоторых полей. Они перечислены в табл. 11.1. Эти параметры определяются конструктором, имеющим одиннадцать аргументов. Второй конструктор — конструктор по умолчанию — присваивает параметрам значения, заданные по умолчанию.
Таблица 11.1. Поля класса GridBagConstraints


Поле

Значение

anchor

Направление размещения компонента в контейнере. Константы:
CENTER, NORTH, EAST, NORTHEAST, SOUTHEAST, SOUTH, SOUTHWEST,
WEST, и NORTHWEST; no умолчанию CENTER

fill

Растяжение компонента для заполнения ячейки. Константы: NONE, HORIZONTAL, VERTICAL, BOTH; ПО умолчанию NONE

gridheight

Количество ячеек в колонке, занимаемых компонентом. Целое типа int, по умолчанию 1. Константа REMAINDER означает, что компонент займет остаток колонки, RELATIVE — будет следующим по порядку в колонке

gridwidth

Количество ячеек в строке, занимаемых компонентом. Целое типа int, по умолчанию 1. Константа REMAINDER означает, что компонент займет остаток строки, RELATIVE — будет следующим в строке по порядку

gridx

Номер ячейки в строке. Самая левая ячейка имеет номер 0. По умолчанию константа RELATIVE, что означает: следующая по порядку

gridy

Номер ячейки в столбце. Самая верхняя ячейка имеет номер 0. По умолчанию константа RELATIVE, что означает: следующая по порядку

insets

Поля в контейнере. Объект класса insets; по умолчанию объект с нулями

ipadx, ipady

Горизонтальные и вертикальные поля вокруг компонентов; по умолчанию 0

weightx,
weighty

Пропорциональное растяжение компонентов при изменении размера контейнера; по умолчанию 0,0

Как правило, объект класса GridBagConstraints создается конструктором по умолчанию, затем значения нужных полей меняются простым присваиванием новых значений, например:
GridBagConstraints gbc = new GridBagConstraints(); 
gbc.weightx = 1.0;
gbc.gridwidth = GridBagConstraints.REMAINDER; 
gbc.gridheight =2;
После создания объекта gbc класса GridBagConstraints менеджеру размещения указывается, что при помещении компонента сотр в контейнер следует применять правила, занесенные в объект gbc. Для этого применяется метод
add(Component comp, GridBagConstraints gbc)
Итак, схема применения менеджера GridBagLayout такова :
GridBagLayout gbl = new GridBagLayout();     // Создаем менеджер 
setLayout(gbl);                              // Устанавливаем его в контейнер 
                                               // Задаем правила размещения по умолчанию 
GridBagConstraints с = new GridBagConstraints(); 
Button b2 = new Button();                    // Создаем компонент 
c.gridwidth =2;                              // Меняем правила размещения 
add(bl, с);                                  // Помещаем компонент b2 в контейнер
                                             // по указанным правилам размещения с
Button Ь2 = new Button();                    // Создаем следующий компонент 
c.gridwidth = 1;                             // Меняем правила для его размещения 
add(b2, с);                                  // Помещаем в контейнер
и т.д.
В документации к классу GridBagLayout приведен хороший пример использования этого менеджера размещения.
 
Заключение
Все менеджеры размещения написаны полностью на языке Java, в состав SUN J2SDK входят их исходные тексты. Если вы решили написать свой менеджер размещения, реализовав интерфейс LayoutManager или LayoutManager2, то посмотрите эти исходные тексты.

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г. Яндекс.Метрика