Материал: Портянкин И. Swing

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

130

ГЛАВА 6

запрещает поместить все ваши компоненты в отдельную панель с удобным вам расположением, а затем сделать ее панелью содержимого вашего окна. Это дело вкуса. Рассмотрим небольшой пример:

//ContentPaneAdd.java

//Замена панели содержимого import javax.swing.*;

import java.awt.*;

public class ContentPaneAdd extends JFrame { public ContentPaneAdd() {

super("ContentPaneAdd"); setDefaultCloseOperation(EXIT_ON_CLOSE);

//создадим панель с двумя кнопками

JPanel contents = new JPanel(); contents.add(new JButton("Один")); contents.add(new JButton("Два"));

//заменим панель содержимого setContentPane(contents);

//выведем окно на экран setSize(200, 100); setVisible(true);

}

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

new Runnable() {

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

}

}

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

Строка меню

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

Контейнеры высшего уровня

131

Однако стандартные окна AWT, напрямую связанные с операционной системой, могут размещать только строки меню AWT и не знают о легковесных меню Swing. Здесь нам помогает корневая панель. Она выделяет под строку меню специальное место и предоставляет метод setJMenuBar(), позволяющий вам установить в контейнере новую строку меню2 (строка меню может использоваться в окне JFrame, диалоговом окне JDialog и апплете JApplet).

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

Прозрачная панель

Прозрачная панель (glass pane) — это последний составляющий элемент корневой панели. Прозрачная панель размещается корневой панелью выше всех элементов многослойной панели — как бы высоко не находился используемый вами слой, прозрачная панель всегда будет выше. Следит за выполнением этого правила корневая панель, которая размещает прозрачную панель выше многослойной панели, причем так, чтобы она полностью закрывала всю область окна, включая и область, занятую строкой меню.

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

видимой, нужно быть уверенным в том, что она прозрачна (ее свойство непрозрачности opaque равно false), потому что в противном случае она закроет все остальные

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

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

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

132

ГЛАВА 6

пользователь сможет эффективно им пользоваться. Попробуем реализовать такое поведение с помощью прозрачной панели:

//HelpSystemDemo.java

//Как прозрачная панель может помочь в создании

//системы помощи

import javax.swing.*; import java.awt.*; import java.awt.event.*;

public class HelpSystemDemo extends JFrame { // необходимые нам поля

private JButton button1, button2, help; private HelpSystem hs = new HelpSystem(); private InterceptPane ip = new InterceptPane();

private ImageIcon helpIcon = new ImageIcon("Help.gif");

public HelpSystemDemo() { super("HelpSystemDemo"); setDefaultCloseOperation(EXIT_ON_CLOSE); // создаем нащ интерфейс

button1 = new JButton("Что-то делает"); button2 = new JButton("Тоже что-то делает"); JPanel contents = new JPanel(); contents.add(button1); contents.add(button2);

// кнопка вызова помощи

help = new JButton(helpIcon); help.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

//при нажатии включаем прозрачную панель ip.setVisible(true);

//и специальный указатель мыши getRootPane().setCursor(getToolkit().

createCustomCursor(helpIcon.getImage(), new Point(0, 0), ""));

}

});

contents.add(help);

// настраиваем наш интерфейс и прозрачную панель setContentPane(contents);

setGlassPane(ip);

Контейнеры высшего уровня

133

// выводим окно на экран setSize(200, 200); setVisible(true);

}

// компонент, перехватывающий события class InterceptPane extends JComponent {

InterceptPane() {

//надо включить события от мыши enableEvents(MouseEvent.MOUSE_EVENT_MASK); enableEvents(KeyEvent.KEY_EVENT_MASK);

//по умолчанию невидим и прозрачен setVisible(false); setOpaque(false);

}

// перехватываем события от мыши

public void processMouseEvent(MouseEvent e) { // отслеживаем нажатия мыши

if ( e.getID() == MouseEvent.MOUSE_PRESSED) {

//определяем, какой компонент был выбран

Component contentPane = getContentPane(); MouseEvent ne =

SwingUtilities.convertMouseEvent( this, e, contentPane);

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

Component visibleComp = SwingUtilities.getDeepestComponentAt(

contentPane, ne.getX(), ne.getY());

//показываем справочную информацию

JOptionPane.showMessageDialog(

null, hs.getHelpFor(visibleComp));

//отключаемся

setVisible(false);

// возвращаем на место обычный указатель мыши getRootPane().setCursor(

Cursor.getDefaultCursor());

}

}

}

// прототип системы помощи class HelpSystem {

// получает помощь для компонентов

134

ГЛАВА 6

 

public String getHelpFor(Component comp) {

 

if ( comp == button1)

 

return "Останавливает реактор. Лучше не жмите";

 

else if ( comp == button2 )

 

return "Хотите лимонада? Тогда жмите смело!";

 

return "Даже и не знаю, что это такое";

 

}

 

}

 

public static void main(String[] args) {

 

SwingUtilities.invokeLater(

 

new Runnable() {

 

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

}

}

 

В данном примере мы создаем небольшое окно с тремя кнопками, две из которых представляют собой обычные элементы пользовательского интерфейса (здесь для простоты они ничего не делают), а третья, со специальным значком3 вместо надписи, включает режим получения помощи, в котором элементы интерфейса перестают реагировать на нажатие кнопок мыши, вместо них манипуляции кнопками контролирует прозрачная панель, вызывая для выбранного компонента систему помощи. Чтобы реализовать подобное поведение, нам потребовалось несколько этапов. Во-первых, мы создали специальный компонент InterceptPane, унаследовав его от базового класса JComponent. Заметьте, что мы сразу же указываем в конструкторе, что наш компонент является прозрачным (невидимым) — свойство непрозрачности меняется на false (как было отмечено в главе 4, по умолчанию оно равно true). Интересно, что здесь же, в конструкторе нашего компонента, нам приходится вручную включать режим получения им сообщений от мыши (методом enableEvents()). Мы не добавляем слушателей, переопределяя вместо этого метод processMouseEvent(), что в нашем случае удобнее (это позволяет получить доступ сразу ко всем событиям от мыши), и поэтому события не включаются автоматически (маскирование событий мы обсуждали в главе 3). Компонент InterceptPane будет использоваться как прозрачная панель нашего приложения, и в его методе processMouseEvent() мы будем перехватывать нажатия кнопок мыши, вызывая при этом помощь для компонента, в области которого было зафиксировано нажатие кнопки. Роль справочной системы играет внутренний класс HelpSystem, который в нашем примере просто возвращает для каждого компонента небольшое сообщение, а в реальности может представлять собой полнофункциональную систему помощи.

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

3 Этот значок взят из стандартного набора графики Java Look And Feel Graphics Repository, распространяемого сайтом java.sun.com и созданного специально для внешнего вида Metal.

Источник: https://studfile.net/preview/15935977/