|
|
|||||||||||||||||||||
|
Размещение компонентов
В предыдущей главе мы размешали компоненты "вручную", задавая их размеры и положение в контейнере абсолютными координатами в координатной системе контейнера. Для этого мы применяли метод 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. Он укладывает в контейнер один компонент за другим слева направо как кирпичи, переходя от верхних рядов к нижним. При изменении размера контейнера "кирпичи" перестраиваются, как показано на рис. 11.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); } }); } }
Рис. 11.1. Размещение компонентов с помощью FlowLayout Менеджер размещения BorderLayout делит контейнер на пять неравных областей, полностью заполняя каждую область одним компонентом, как показано на рис. 11.2. Области получили географические названия NORTH, SOUTH, WEST, EAST И CENTER. Метод add о в случае применения BorderLayout имеет два аргумента: ссылку на компонент сотр и область region, в которую помещается компонент — одну из перечисленных выше констант: add(Component comp, String region) Обычный метод add (Component comp) с одним аргументом помещает компонент В область CENTER. В классе два конструктора:
Если в контейнер помещается менее пяти компонентов, то некоторые области не используются и не занимают места в контейнере, как можно заметить на рис. 11.3. Если не занята область CENTER, то компоненты прижимаются к границам контейнера. В листинге 11.2 создаются пять кнопок, размещаемых в контейнере. Заметьте отсутствие установки менеджера в контейнере setLayout () — менеджер BorderLayout установлен в контейнере Frame по умолчанию. Результат размещения показан на рис. 11.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); } }); } }
Рис. 11.2. Области размещения BorderLayout Менеджер размещения BorderLayout кажется неудобным: он располагает не больше пяти компонентов, последние растекаются по всей области, области имеют странный вид. Но дело в том, что в каждую область можно поместить не компонент, а панель, и размещать компоненты на ней, как сделано в листинге 11.3 и показано на рис. 11.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); } }); } }
Рис. 11.3. Компоновка с помощью FiowLayout и BorderLayout Менеджер размещения 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 выстраиваются кнопки для калькулятора, а рис. 11.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); } }); } }
Рис. 11.4. Размещение кнопок менеджером GridLayout Менеджер размещения cardLayout своеобразен — он показывает в контейнере только один, первый (first), компонент. Остальные компоненты лежат под первым в определенном порядке как игральные карты в колоде. Их расположение определяется порядком, в котором написаны методы add (). Следующий компонент можно показать методом next (Container с), предыдущий — методом previous (Container с), Последний— методом last (Container с), первый — методом first (Container с). Аргумент этих методов — ссылка на контейнер, в который помещены компоненты, обычно this. В классе два конструктора:
Менеджер 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); } }); } }
Рис. 11.5. Менеджер размещения CardLayout Менеджер размещения GridBagLayout расставляет компоненты наиболее гибко, позволяя задавать размеры и положение каждого компонента. Но он оказался очень сложным и применяется редко. В классе GridBagLayout есть только один конструктор по умолчанию, без аргументов. Менеджер класса GridBagLayout, в отличие от других менеджеров размещения, не содержит правил размещения. Он играет только организующую роль. Ему передаются ссылка на компонент и правила расположения этого компонента, а сам он помещает данный компонент по указанным правилам в контейнер. Все правила размещения компонентов задаются в Объекте другого класса, GridBagConstraints. Менеджер размещает компоненты в таблице с неопределенным заранее числом строк и столбцов. Один компонент может занимать несколько ячеек этой таблицы, заполнять ячейку целиком, располагаться в ее центре, углу или прижиматься к краю ячейки. Класс GridBagConstraints содержит одиннадцать полей, определяющих размеры компонентов, их положение в контейнере и взаимное положение, и несколько констанГ — значений некоторых полей. Они перечислены в табл. 11.1. Эти параметры определяются конструктором, имеющим одиннадцать аргументов. Второй конструктор — конструктор по умолчанию — присваивает параметрам значения, заданные по умолчанию. Таблица 11.1. Поля класса GridBagConstraints
Как правило, объект класса 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, то посмотрите эти исходные тексты. |
|||||||||||||||||||||
|
|
||||||||||||||||||||||