Меню и панели инструментов |
265 |
}
public void actionPerformed(ActionEvent e) { System.exit(0);
}
}
public static void main(String[] args) { SwingUtilities.invokeLater(
new Runnable() {
public void run() { new MenuSystem(); } });
}
}
Итак, в этом примере создается относительно простая система меню. Как мы уже отмечали, элементы меню — это фактически кнопки, собранные в список. Списки элементов меню, или правильнее выпадающие меню (drop-down menus), реализованы в Swing классом JMenu. Именно они создаются методами createFileMenu() и createWhoMenu(), внутри которых в выпадающие меню методом add() добавляются разнообразные элементы меню, в том числе элементы-флажки и элементыпереключатели. После этого остается вывести созданные выпадающие меню на экран, для чего служит так называемая строка меню (menu bar), создать которую позволяет класс JMenuBar. В нем также есть метод add(), только не для элементов меню, а для выпадающих меню JMenu. Разместив все выпадающие меню своего приложения в строке меню, вы можете поместить ее в окно, вызвав предназначенный для этого метод setJMenuBar().
Что касается элементов меню, то это те же кнопки, флажки и переключатели. Вы можете указывать для них названия, значки и мнемоники, создавать их на основе интерфейса Action, и все это проиллюстрирует наш пример. Единственное новшество в примере — это разделитель (separator), который позволяет организовать смысловые группы в выпадающих меню. В примере показано, как его создать, а подробнее мы поговорим о нем чуть позже.
Что же, система меню создается действительно просто, и ничего экстраординарного в этом процессе нет. Однако меню Swing способны и на многое другое, поэтому давайте рассмотрим их подробнее.
266 |
ГЛАВА 10 |
Строка меню JMenuBar
Главное, что нужно помнить при создании строки меню JMenuBar в своей программе, — это самый обыкновенный контейнер, ничем не отличающийся от панели JPanel и обладающий теми же самыми свойствами. Не нужно думать, что строка меню рождена только для работы с выпадающими меню. Вы можете смело добавлять в нее всевозможные компоненты, например надписи со значками или раскрывающиеся списки. Беззастенчиво заглянув внутрь класса JMenuBar, можно увидеть, что даже менеджер расположения у строки меню не какой-то экзотический, а прекрасно знакомый нам менеджер BoxLayout с расположением компонентов по горизонтали. Так что создание с виду совершенно новаторского меню оказывается весьма простым делом. Например, можно сделать со строкой меню следующее:
//TrickyMenuBar.java
//Полоска меню JMenuBar может многое import javax.swing.*;
import java.awt.*;
public class TrickyMenuBar extends JFrame { public TrickyMenuBar() {
super("TrickyMenuBar"); setDefaultCloseOperation( EXIT_ON_CLOSE );
//создаем главную полоску меню
JMenuBar menuBar = new JMenuBar();
//добавляем в нее выпадающие меню menuBar.add(new JMenu("Файл")); menuBar.add(new JMenu("Правка"));
//мы знаем, что используется блочное
//расположение, так что заполнитель
//вполне уместен menuBar.add(Box.createHorizontalGlue());
//теперь поместим в полоску меню
//не выпадающее меню, а надпись со значком
JLabel icon = new JLabel(
new ImageIcon("images/download.gif")); icon.setBorder(
BorderFactory.createLoweredBevelBorder());
menuBar.add(icon);
//помещаем меню в наше окно setJMenuBar(menuBar);
//выводим окно на экран
setSize(300, 200); setVisible(true);
}
public static void main(String[] args) {
Меню и панели инструментов |
267 |
SwingUtilities.invokeLater( new Runnable() {
public void run() { new TrickyMenuBar(); } });
}
}
В примере мы сначала добавили в строку меню традиционные выпадающие меню (они, правда, для экономии места были оставлены пустыми), а затем, предварительно использовав заполнитель, поместили в строку меню самую обычную надпись со значком, установив для нее тисненую рамку. Мы специально использовали анимированный GIF-файл, чтобы пример произвел еще более сильный эффект. Не правда ли, напоминает современные браузеры? И все, что мы сделали для этого, — это добавили два компонента.
Отметьте также, что размещение строки меню в окне осуществляется не с помощью обычного метода add() и менеджера расположения, а с помощью специального метода setJMenuBar(). Этот метод на самом деле принадлежит не классу окна JFrame, а корневой панели JRootPane, которая и заботится о том, чтобы строка меню занимала подобающее ей положение на вершине окна, оставляя вам все пространство в панели содержимого.
Таким образом, знание того факта, что строка меню — это обычный контейнер, позволяет творить со строкой меню просто невероятные вещи. Это хороший пример того, как важна при разработке библиотеки ее прозрачность — никто не скрывает от вас тонкости реализации, и то же можно сказать обо всех компонентах. Знание основ устройства библиотеки — гораздо более мощное оружие, чем может показаться на первый взгляд.
Впрочем, не стоит сильно увлекаться созданием абсолютно нового облика меню в вашей программе, иначе пользователям трудно будет быстро освоиться с ней. Все-таки вид и поведение меню уже устоялись, и в привычном облике работать с меню проще.
Выпадающие меню JMenu и разделители JSeparator
Как мы уже отмечали, для упорядочения элементов меню служат выпадающие меню JMenu. Интересно, что класс JMenu унаследован от обычного элемента меню JMenuItem, и его функция заключается только в том, чтобы при щелчке мышью показать в нужном месте экрана всплывающее меню, в котором и содержатся все добавленные элементы меню. Ничего хитрого в этом классе нет, и сказать о нем можно только то, что он позволяет организовывать вложение меню любой сложности. Для этого вы просто вкладываете выпадающие меню друг в друга, и получаете перечни элементов меню произвольной длины (каскадные меню).
Для того чтобы организовать в меню несколько групп элементов, используются разделители JSeparator. Мы можете добавлять их в выпадающие меню, создавая напрямую, или же использовать для этого специальный метод addSeparator(). Кроме того разделите-
268 |
ГЛАВА 10 |
ли можно применять и вне меню в качестве разделительных линий, в том числе вертикальных. Рассмотрим пример:
//CascadedMenus.java
//Создание вложенных меню любой сложности import javax.swing.*;
import java.awt.*;
public class CascadedMenus extends JFrame { public CascadedMenus() {
super("CascadedMenus"); setDefaultCloseOperation( EXIT_ON_CLOSE );
//создаем строку главного меню
JMenuBar menuBar = new JMenuBar();
//создаем выпадающее меню
JMenu text = new JMenu("Текст");
//и несколько вложенных меню
JMenu style = new JMenu("Стиль"); JMenuItem bold = new JMenuItem("Жирный");
JMenuItem italic = new JMenuItem("Курсив"); JMenu font = new JMenu("Шрифт");
JMenuItem arial = new JMenuItem("Arial"); JMenuItem times = new JMenuItem("Times"); font.add(arial);
font.add(times);
//размещаем все в нужном порядке style.add(bold); style.add(italic); style.addSeparator(); style.add(font);
text.add(style);
menuBar.add(text);
//помещаем меню в окно setJMenuBar(menuBar);
//разделитель может быть полезен не только в меню
((JComponent)getContentPane()).setBorder( BorderFactory.createEmptyBorder(0, 5, 0, 0));
add(new JSeparator(SwingConstants.VERTICAL), "West");
//выводим окно на экран
setSize(300, 200); setVisible(true);
}
Меню и панели инструментов |
269 |
public static void main(String[] args) { SwingUtilities.invokeLater(
new Runnable() {
public void run() { new CascadedMenus(); } });
}
}
В этом примере мы создали весьма правдоподобное меню, которое содержит команды для работы с простым текстовым редактором. Для получения каскадных меню несколько выпадающих меню были просто вложены друг в друга в нужном порядке. Заодно мы еще раз использовали разделитель, который акцентировал различие между командами для выбора стиля текста и для выбора шрифта для него.
Посмотрите, как можно использовать разделитель вне меню. В примере мы создали вертикальный разделитель (для этого есть специальный конструктор), который добавили на запад своей панели содержимого. Получилось весьма неплохое украшение для возможного интерфейса. Правда, для того чтобы в печатной книге его было лучше видно, мы дополнительно отделили разделитель от границ окна с помощью рамки с пустым пространством EmptyBorder.
В примере была создана очень простая система меню, обычно она в несколько раз больше и сложнее. Но даже для такой простой системы код получился немного неряшливым (чего стоят одни только добавления одного в другого, а другого в третье). Действительно, инструкции создания меню в коде сильно «загрязняют» последний, это хорошо известный факт, что «декларативный» стиль описания объекта не слишком элегантно выглядит через призму вызовов объектно-ориентированных методов. Мы ведь просто хотим указать структуру меню, а не вызываем никаких действий. Чуть позже мы попытаемся решить эту проблему.
Клавиатурные сокращения и мнемоники
Если часто работаешь с одним и тем же приложением, и раз за разом выполняешь одни и те же операции, поневоле хочется повысить свою производительность и не тратить время на то, что делалось уже много раз. Именно для этого в графических приложениях и появились клавиатурные сокращения, или клавиши быстрого доступа (accelerators) и мнемоники (mnemonics). Опытные пользователи высоко ценят возможность выполнить операцию, требующую в обычных условиях долгих «блуж-