Добавил:
СПбГУТ * ИКСС * Программная инженерия Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Портянкин И. Swing

.pdf
Скачиваний:
140
Добавлен:
07.10.2020
Размер:
4.63 Mб
Скачать

Внутренние винтики Swing

115

public class KeyBindingTest extends JFrame { public KeyBindingTest() {

super("KeyBindingTest");

//выход при закрытии окна setDefaultCloseOperation(EXIT_ON_CLOSE);

//настраиваем карты команд и входных событий для

//корневой панели приложения

InputMap im = getRootPane().getInputMap();

ActionMap am = getRootPane().getActionMap();

//срабатывает при отпускании сочетания Ctrl+A im.put(KeyStroke.getKeyStroke(

KeyEvent.VK_A,

KeyEvent.CTRL_MASK, true), "Action");

//срабатывает при печати буквы 'Я' im.put(KeyStroke.getKeyStroke('Я'), "Action"); am.put("Action", new AnAction());

//выводим окно на экран

setSize(200, 200); setVisible(true);

}

// класс нашей команды

class AnAction extends AbstractAction { public void actionPerformed(ActionEvent e) {

System.out.println("OK");

}

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

public void run() { new KeyBindingTest(); } });

}

}

В данном примере мы создаем маленькое окно и настраиваем клавиатурные сокращения для корневой панели этого окна (в любом контейнере высшего уровня Swing есть корневая панель). В нашем примере используются два сокращения: первое срабатывает при отпускании сочетания клавиш Ctrl+A (именно при отпускании, вы увидите это, запустив пример, такие сокращения позволяет создавать класс KeyStroke), а второе показывает возможность работы и с кириллицей. Правда, кириллические буквы будут распознаваться только для событий типа KEY_TYPED (печать символа), потому что в событиях KEY_PRESSED и KEY_RELEASED участвуют только символы с виртуальными кодами, определенными в классе KeyEvent, а кириллических символов там нет. Поэтому

116

ГЛАВА 5

при создании объектов KeyStroke для кириллических символов используйте те методы getKeyStroke(), которые создают клавиатурное сокращение для событий KEY_TYPED. Один из таких методов мы и задействовали в примере. Эта проблема очень неприятно сказывается на клавиатурных сокращениях, используемых в кнопках и меню Swing, когда клавиши быстрого доступа отказываются работать с русской раскладкой клавиатуры2. Мы обсудим это в главе 9, посвященной кнопкам.

Между делом, отметьте, какую гибкость способны придать приложению карты входных событий и команд. Мы создали два клавиатурных сокращения (поместив их в карту для состояния WHEN_FOCUSED, именно эта карта возвращается методом getInputMap() без параметров), но привязали их одному и тому же событию. Будь сокращения отображены непосредственно на команды, сделать этого не удалось бы. Остается лишь запустить приложение и убедиться в том, что механизмы поддержки клавиатурных сокращений Swing действуют.

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

Система передачи фокуса ввода

Фокус ввода — довольно простое определение. Компонент, обладающий фокусом ввода, первым получает все события от клавиатуры. Эти события не обязательно остаются в самом компоненте (как мы уже видели, клавиатурные сокращения обрабатываются даже в тех случаях, когда событие от клавиатуры произошло в другом компоненте), но тем не менее у компонента, обладающего фокусом ввода, всегда есть шанс обработать нажатие клавиш первым. Фокус ввода передается от компонента к компоненту различными способами: когда пользователь щелкает на другом компоненте мышью (если тот обрабатывает щелчки мыши) или нажимает специальные клавиши (чаще всего клавишу Tab или ее сочетания с управляющими клавишами). Система передачи фокуса ввода, встроенная в любую схему пользовательского интерфейса, определяет, какие компоненты могут обладать фокусом ввода и порядок его передачи.

Вся власть и полномочия по передаче фокуса ввода находятся у класса библиотеки AWT с названием KeyboardFocusManager. Любые сочетания клавиш и события, подходящие для передачи фокуса ввода, приходят прежде всего к нему. Происходит это на самом низком уровне обработки событий базового компонента всех графических библиотек Java Component, что позволяет унифицировать процесс передачи фокуса для любых компонентов, независимо от того, тяжеловесные они или легковесные и к какой библиотеке принадлежат. Любой унаследованный от Component класс (а значит и все компоненты библиотеки Swing) находится под контролем новой системы фокуса ввода и класса KeyboardFocusManager.

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

2 Кстати, не только с русской, но и с любой другой, отличной от английской.

Внутренние винтики Swing

117

Настройка системы передачи фокуса

Если не вдаваться в подробности реализации системы передачи фокуса ввода, можно сказать, что она исключительно прозрачна и проста. Для любого компонента, унаследованного от класса Component, вы можете указать, нужен ли этому компоненту фокус ввода, вызвав для этого метод setFocusable() (по умолчанию считается, что компонент нуждается в фокусе ввода, то есть обрабатывает события от клавиатуры), и настроить список клавиатурных сокращений, согласно которым фокус ввода будет передаваться к следующему или предыдущему компоненту. Клавиатурные сокращения, служащие для передачи фокуса ввода, хранятся во множествах Set, передать их в компонент можно методом setFocusTraversalKeys(). По умолчанию для передачи фокуса используются клавиши Tab и Shift+Tab, для передачи фокуса к следующему и предыдущему компоненту соответственно. После настройки ваш компонент окажется под надежной опекой класса KeyboardFocusManager, который позаботится о том, чтобы фокус ввода вовремя оказывался у вашего компонента и покидал его только при нажатии тех клавиш, что вы указали. Рассмотрим небольшой пример:

//FocusKeysTest.java

//Настройка клавиш перехода фокуса ввода import javax.swing.*;

import java.awt.*;

import java.awt.event.KeyEvent; import java.util.HashSet;

public class FocusKeysTest extends JFrame { public FocusKeysTest() {

super("FocusKeysTest");

//выход при закрытии окна setDefaultCloseOperation(EXIT_ON_CLOSE);

//добавляем пару кнопок

setLayout(new FlowLayout()); // особая кнопка

JButton button = new JButton("Особая"); add(button);

add(new JButton("Обычная"));

//настроим клавиши перехода фокуса

HashSet<AWTKeyStroke> set = new HashSet<AWTKeyStroke>(); set.add(AWTKeyStroke.getAWTKeyStroke(

'Q', KeyEvent.CTRL_MASK)); button.setFocusTraversalKeys(

KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, set);

//выводим окно на экран

setSize(200, 200); setVisible(true);

}

118

ГЛАВА 5

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

public void run() { new FocusKeysTest(); } });

}

}

В данном примере мы добавляем в окно две кнопки, для одной из которых специально настраиваем клавиши передачи фокуса ввода следующему компоненту. Для этого необходимо поместить в множество Set (класс множеств Set является абстрактным, у него есть несколько подклассов, мы использовали HashSet) клавиатурные сокращения, при нажатии которых будет происходить передача фокуса. Клавиатурные сокращения для системы передачи фокуса создаются статическими методами класса AWTKeyStroke3. В примере мы создаем сочетание Ctrl+Q, добавляем его в множество, и передаем множество компоненту, указывая константой FORWARD_TRAVERSAL_KEYS, что это сочетание будет использоваться для передачи фокуса следующему компоненту (клавиши для остальных ситуаций при этом не меняются). Запустив программу, вы убедитесь, что теперь фокус ввода передается от первой кнопки ко второй только новым сочетанием клавиш, в то время как вторая кнопка исправно реагирует на нажатие клавиши Tab.

Теперь, когда мы разобрались, как настраивать клавиши, используемые для передачи фокуса ввода от одного компонента к другому, интересно будет узнать, как система передачи фокуса ввода определяет, какому компоненту будет передан фокус. Этим заведуют подклассы абстрактного класса FocusTraversalPolicy. При срабатывании сочетания клавиш, отвечающего за передачу фокуса ввода, текущий подкласс FocusTraversalPolicy определяет, какой именно компонент получит фокус ввода следующим4. Создать собственный алгоритм нетрудно, однако AWT и Swing предоставляют несколько стандартных алгоритмов передачи фокуса ввода, которых вполне хватает для большинства ситуаций (табл. 5.2).

Таблица 5.2. Стандартные алгоритмы передачи фокуса

Имя класса

Предназначение

ContainerOrderFocusTraversalPolicy

Данный

алгоритм имитирует использовавшийся

 

в прежних версиях JDK переход фокуса ввода со-

 

гласно очередности добавления компонентов в кон-

 

тейнер. Первый добавленный в контейнер компо-

 

нент получает фокус при выводе окна на экран, фо-

 

кус переходит к компоненту, добавленному вторым

 

и т. д.

 

DefaultFocusTraversalPolicy

Работает

аналогично предыдущему алгоритму,

 

и к тому же взаимодействует с помощниками (peer)

 

компонентов, что расширяет его возможности по

 

работе с тяжеловесными компонентами. По умол-

 

чанию используется в приложениях AWT. В данный

момент плохо сочетается с легковесными компонен-

тами Swing

3Это полный аналог класса KeyStroke. С версии JDK 1.4 все функции класса KeyStroke перешли

кAWTKeyStroke, а KeyStroke просто наследует от него.

4 Класс FocusTraversalPolicy — это ни что иное, как стратегия, или подключаемый алгоритм.

Внутренние винтики Swing

119

Таблица 5.2 (продолжение)

 

 

 

Имя класса

Предназначение

 

 

SortingFocusTraversalPolicy

Предоставляется библиотекой Swing. Позволяет

 

организовать передачу фокуса ввода согласно не-

 

которому признаку, который определяет, какие ком-

 

поненты получают фокус раньше, а какие позже.

 

Для работы требует объект Comparator, обеспечи-

 

вающий сравнение компонентов. Может исполь-

 

зоваться для получения весьма интересных спе-

 

циализированных алгоритмов передачи фокуса, так

 

как написать объект сортировки Comparator куда

 

проще, чем создавать алгоритм передачи фокуса

 

«с нуля»

LayoutFocusTraversalPolicy

Расширяет предыдущий алгоритм, передавая

 

ему для сортировки компонентов объект Layout-

 

Comparator. Последний получает список компо-

 

нентов контейнера и выясняет, как они располага-

 

ются на экране. Это позволяет передавать фокус

 

ввода именно в том порядке, в котором располо-

 

жены компоненты перед глазами пользователя.

 

Учитывает особенности локализованных про-

 

грамм (в том числе письмо справа налево). По

 

умолчанию в окнах Swing используется именно

 

этот алгоритм

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

//FocusPolicyTest.java

//Различные алгоритмы передачи фокуса ввода import javax.swing.*;

import java.awt.*; import java.awt.event.*;

public class FocusPolicyTest extends JFrame { public FocusPolicyTest() {

super("FocusPolicyTest");

//при закрытии окна выход setDefaultCloseOperation(EXIT_ON_CLOSE);

//добавляем три кнопки

add(new JButton("Левая"), "West");

//добавляем эту кнопку второй, но она будет ниже

//двух других кнопок

120

ГЛАВА 5

JButton button = new JButton("Сменить"); button.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) { // при нажатии сменим алгоритм для окна setFocusTraversalPolicy(

new ContainerOrderFocusTraversalPolicy());

}

});

add(button, "South");

add(new JButton("Правая"), "East"); // выводим окно на экран setSize(200, 200); setVisible(true);

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

public void run() { new FocusPolicyTest(); } });

}

}

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

Запустив программу с примером, вы сможете оценить работу двух различных алгоритмов передачи фокуса ввода. Сначала действует алгоритм LayoutFocusTraversalPolicy, и фокус ввода передается так, как располагаются кнопки в окне. Сменив алгоритм на ContainerOrderFocusTraversalPolicy, вы увидите, во-первых, что теперь фокус переходит так, как мы добавляли кнопки в окно (и с точки зрения пользователя это довольно неудобно), а, во-вторых, что на некоторое время фокус исчезает в каких-то невидимых компонентах. Это проблем, так как система считает, что любой компонент нуждается в фокусе ввода, хотя корневая панель в нем не нуждается. Именно в корневой панели и «застревает» ненадолго фокус ввода. Алгоритм LayoutFocusTraversalPolicy справляется с этой проблемой, потому что дополнительно проверяет старые свойства, связанные с фокусом ввода, определенные в классе JComponent еще до появления новой системы. Поэтому лучше не использовать в приложениях Swing алгоритмы передачи фокуса AWT.

Расширенные возможности

В системе передачи фокуса ввода также есть несколько дополнительных возможностей. Прежде всего стоит отметить понятие цикла передачи фокуса (focus cycle) и его корня (focus cycle root). Фокус ввода передается только в пределах цикла передачи фокуса, который представляет собой набор из некоторых компонентов. Компоненты находятся

Внутренние винтики Swing

121

в контейнере, который называется корнем цикла. По умолчанию в качестве корня используются только контейнеры высшего уровня, и все добавляемые в них компоненты оказываются в одном цикле, однако корнем можно сделать любой контейнер, что может быть полезным для очень больших контейнеров, напичканных компонентами. Для перехода из одного цикла передачи фокуса в другой применяется специальное множество клавиатурных сокращений, его позволяет задать класс KeyboardFocusManager. Чтобы заставить контейнер вести себя как корень цикла, необходимо переопределить его метод isFocusCycleRoot() так, чтобы он возвращал значение true. Тем не менее, в обычных приложениях с обычными пользовательскими интерфейсами создание дополнительных циклов передачи фокуса требуется редко, поскольку лишь «добавляет пользователям головной боли».

Далее стоит сказать о возможностях окон Java, унаследованных от класса Window. Благодаря усилиям класса KeyboardFocusManager, у окон AWT имеется возможность отказываться от фокуса ввода. Для отключения возможности получения фокуса ввода в окне вы можете использовать метод setFocusableWindowState(false). После этого компоненты, расположенные в окне, не будут получать сообщений от клавиатуры. События (описанные в интерфейсе слушателя WindowFocusListener) позволяют различить активизацию окна (в общем случае это означает, что пользователь использовал окно последним) и получение окном фокуса ввода (что может произойти только в окне, которое соглашается обладать фокусом ввода). Интересно, что события, сообщающие о получении фокуса ввода, полностью создаются внутри Java классом KeyboardFocusManager, а не приходят из операционной системы.

Также благодаря тому, что система передачи фокуса ввода полностью написана на Java, появилась возможность программно управлять передачей фокуса, и вдобавок получать исчерпывающую информацию о состоянии системы и компонентах, обладающих фокусом. Все это также относится к функциям класса KeyboardFocusManager. С его помощью вы сможете легко передать фокус следующему, предыдущему или произвольному компоненту, а также узнать, какой компонент обладает в данный момент фокусом ввода и какое окно является активным. Более подробно познакомиться с возможностями системы передачи фокуса ввода и методами ее центрального класса KeyboardFocusManager можно в интерактивной документации Java.

Всплывающие подсказки и клиентские свойства

Кроме тех важнейших базовых возможностей, которыми обеспечивает библиотеку Swing класс JComponent и которые мы только что рассмотрели, у него осталось еще несколько обязанностей. С ними он также справляется с блеском, и представить Swing без этого просто невозможно.

Очень полезным свойством всех без исключения компонентов Swing является возможность показывать всплывающие подсказки (tool tips) при небольшой задержке указателя мыши над компонентом. Поддержка Swing всплывающих подсказок также обеспечивается базовым классом JComponent. В нем определен метод setToolTipText(), в который вы передаете текст подсказки. При передаче в данный метод текста JComponent регистрирует компонент во вспомогательном классе ToolTipManager. Последний представляет собой одиночку и централизованно управляет процессом вывода подсказок в системе. При регистрации компонентов он присоединяется к ним в качестве слушателя событий от мыши, и при появлении указателя мыши на компоненте запускает таймер, следящий за временем, в течение которого указатель мыши остается на компоненте неподвижным, и таким образом определяет, когда следует вывести подсказку. Подробнее о всплывающих подсказках мы узнаем в главе 8.

Наконец, в арсенале класса JComponent есть еще одно оружие — клиентские свойства (client properties), весьма удачная находка создателей Swing. Эти свойства практически

122

ГЛАВА 5

аналогичны свойствам JavaBeans, только они не требуют наличия в классе компонента поля, хранящего значение самого свойства, и пары методов get/set. Вместо этого значение свойства хранится в специальном ассоциативном массиве, а для его изменения

иполучения используется пара методов putClientProperty() и getClientProperty(). Клиентские свойства, как и свойства JavaBeans, являются привязанными и позволяют настраивать

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

Резюме

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

Глава 6. Контейнеры высшего уровня

После создания пользовательского интерфейса необходимо вывести его на экран, чтобы пользователь увидел его и смог им воспользоваться. Для этого предназначены специальные компоненты библиотеки Swing, называемые контейнерами высшего уровня (top level containers). Они представляют собой окна операционной системы, в которых вы размещаете компоненты своего пользовательского интерфейса. К контейнерам высшего уровня относятся окна JFrame и JWindow, диалоговое окно JDialog, а также апплет JApplet (который не является окном, но тоже предназначен для вывода интерфейса в браузере, запускающем этот апплет). В этой главе мы также рассмотрим компонент- «рабочий стол» JDesktopPane и внутренние окна JInternalFrame, которые хоть формально и не являются контейнерами высшего уровня, но по сути выполняют такие же задачи.

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

На самом деле оказывается, что контейнеры высшего уровня Swing — это самые незатейливые компоненты библиотеки. Они просто наследуют от соответствующих классов AWT (Frame, Window, Dialog и Applet), а также, чтобы смягчить разницу между контейнерами AWT и компонентами Swing, застилают свое пространство специальной «соломкой» в виде так называемой корневой панели, которая обеспечивает легковесные компоненты некоторыми возможностями, отсутствующими в контейнерах AWT (например, специальным местом для строки меню Swing, о которой AWT знать не знает). На этом работа контейнеров высшего уровня Swing заканчивается. Можно попробовать разместить компоненты Swing напрямую в окнах AWT, но в результате получится не слишком работоспособный интерфейс, так как корневая панель предоставляет компонентам Swing весьма важные услуги.

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

Корневая панель JRootPane

Каждый раз, когда вы создаете новый контейнер высшего уровня, будь то обычное окно, диалоговое окно или апплет, в конструкторе этого контейнера создается особый компонент — экземпляр класса JRootPane, который добавляется в контейнер, причем так, чтобы занять все доступное в контейнере место. Более того, все контейнеры высшего уровня Swing следят за тем, чтобы другие компоненты не смогли «пробраться» за пределы этого специального компонента: они переопределяют метод add(), предназначенный для добавления компонентов, и при вызове этого метода принудительно добав-

124

ГЛАВА 6

ляют их в специально предназначенное для этого место. Этот специальный компонент и называется корневой панелью (root pane). Все компоненты своего пользовательского интерфейса вы будете добавлять именно в корневую панель.

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

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

Многослойная панель JLayeredPane

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

Многослойная панель используется для добавления в контейнер свойства глубины (depth), иногда еще говорят, что многослойная панель упорядочивает компоненты в соответствии с их порядком в стопке (Z-order). То есть многослойная панель позволяет организовать в контейнере новое, третье, измерение, вдоль которого располагаются слои (layers) компонента. В обычном контейнере расположение компонента определяется прямоугольником, который показывает, какую часть контейнера занимает компонент. При добавлении компонента в многослойную панель необходимо указать не только прямоугольник, занимаемый компонентом, но и слой, в котором он будет располагаться. Слой в многослойной панели определяется целым числом — слой находится тем выше, чем больше определяющее его число. Окончательно прояснит ситуацию небольшая иллюстрация (рис. 6.1).

1

10

20

30

Рис. 6.1. Слои в многослойной панели

1 Если выражаться языком шаблонов проектирования, можно сказать, что корневая панель — это компоновщик (composite).