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

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

270

ГЛАВА 10

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

Если с мнемониками все более или менее ясно (мы уже встречались с ними в главах 8 и 9), то клавиатурные сокращения — привилегия элементов меню, где они чрезвычайно полезны. Клавиатурное сокращение — это произвольная комбинация всевозможных управляющих клавиш (Shift, Ctrl, Alt) с клавишей некоторого латинского символа, нажатие которой эквивалентно выбору элемента меню, что освобождает пользователя от необходимости разыскивать этот элемент в системе меню.

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

//GoodMenu.java

//Клавиатурные комбинации и мнемоники для меню Swing import javax.swing.*;

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

public class GoodMenu extends JFrame { public GoodMenu() {

super("GoodMenu"); setDefaultCloseOperation( EXIT_ON_CLOSE );

//создаем строку главного меню

JMenuBar menuBar = new JMenuBar();

//некоторые весьма часто встречающиеся

//выпадающие меню menuBar.add(createFileMenu()); menuBar.add(createEditMenu());

//поместим меню в наше окно setJMenuBar(menuBar);

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

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

}

// создает меню "Файл"

private JMenu createFileMenu() { // выпадающее меню

JMenu file = new JMenu("Файл"); file.setMnemonic('Ф');

// пункт меню "Открыть"

Меню и панели инструментов

271

JMenuItem open = new JMenuItem("Открыть"); open.setMnemonic('О'); // русская буква

//установим клавишу быстрого доступа (латинская буква) open.setAccelerator(

KeyStroke.getKeyStroke('O', KeyEvent.CTRL_MASK));

//пункт меню "Сохранить"

JMenuItem save = new JMenuItem("Сохранить"); save.setMnemonic('С');

save.setAccelerator(

KeyStroke.getKeyStroke('S', KeyEvent.CTRL_MASK)); // добавим все в меню

file.add(open); file.add(save); return file;

}

// создает меню "Правка" private JMenu createEditMenu() {

// выпадающее меню

JMenu edit = new JMenu("Правка"); edit.setMnemonic('П');

// пункт меню "Вырезать"

JMenuItem cut = new JMenuItem("Вырезать"); cut.setMnemonic('В');

cut.setAccelerator(

KeyStroke.getKeyStroke('X', KeyEvent.CTRL_MASK)); // пункт меню "Копировать"

JMenuItem copy = new JMenuItem("Копировать"); copy.setMnemonic('К');

//клавишу быстрого доступа можно создать и так copy.setAccelerator(KeyStroke.getKeyStroke("ctrl C"));

//готово

edit.add(cut);

edit.add(copy); return edit;

}

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

new Runnable() {

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

}

}

272

ГЛАВА 10

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

Вы можете видеть, что мнемоники устанавливаются хорошо знакомым нам методом setMnemonic(), а вот клавиши быстрого доступа для элементов меню создаются с помощью класса KeyStroke. В этом классе определено несколько перегруженных статических методов вида getKeyStroke(), которые возвращают экземпляр нужной клавиатурной комбинации. В примере демонстрируются два варианта этого метода: один требует указания символа для клавиши быстрого доступа и набора управляющих клавиш (вы можете указать несколько управляющих клавиш, используя соответствующие константы из класса KeyEvent, связав их операцией поразрядного «ИЛИ»), а другой позволяет получить нужное клавиатурное сокращение с помощью строки, в которой сначала указывают псевдонимы управляющих клавиш, а затем символ клавиши быстрого доступа.

Запустив программу с примером, вы столкнетесь с досадной проблемой мнемоник. Если вы уже находитесь в меню, то есть оно получило фокус ввода, мнемоники с русскими символами работают. Но если вы хотите получить доступ к одному из выпадающих меню первый раз (меню не обладает фокусом ввода), мнемоники не работают (меню файл не активируется с помощью клавиш Alt-Ф). Какие бы сочетания клавиш мы не нажимали, это не поможет, и меню так и не получит фокус ввода. Это -- большой недостаток, и избежать его можно, либо включив в русские названия элементов меню латинские буквы, либо заранее предупредив пользователя о том, что строка меню в Swing получает фокус ввода c помощью клавиши F10 (по сути, она считается стандартной клавишей перехода на строку меню, но часто ли ее используют? Я не припомню, чтобы мне приходилось нажимать ее вместо мнемоники).

Но, как бы там ни было, клавиши быстрого доступа работают исправно, и довольно значительно повышают привлекательность приложения, так что не забывайте про них. Главное, помните о том, что в мире интерфейсов устоялись свои стандарты, пусть и молодые, и не стоит заново изобретать альтернативу старым добрым Control-S и Control-С, пусть они и набили уже всем оскомину. Даже на русском языке эти сочетания остаются собой. Для всех важных и частых операций своего приложения продумывайте наличие эффективных клавиш быстрого доступа1.

1 Программистам прекрасно знакомы клавиши быстрого доступа и их значение. Ни один потрясающей красоты дизайн не заменит возможности быстрым нажатием провернуть одну из множества нужных в данный момент операций, не отвлекаясь на их поиск в меню. Иногда список быстрых клавиш не умещается на нескольких страницах руководства средства разработки, такого как IDEA.

Меню и панели инструментов

273

Всплывающие меню JPopupMenu

Меню не обязательно относятся ко всему приложению, они могут пригодиться и для частей этого приложения (например, для текстового поля в редакторе). В таком случае меню появляется на экране только по желанию пользователя, поэтому их называют всплывающими (popup menu), или контекстными (context-sensitive menu). Пользователь вызывает это меню, чтобы получить список команд для того объекта приложения, с которым он работает, не тратя время на поиск этих команд в главном меню.

Всплывающие меню в Swing реализованы классом JPopupMenu. На самом деле вы уже видели этот класс «в деле» — именно он применяется в выпадающем меню JMenu для вывода его элементов. Но использовать его можно и отдельно, в чем мы сейчас убедимся:

//PopupMenus.java

//Работа с всплывающими меню import javax.swing.*;

import java.awt.*;

public class PopupMenus extends JFrame { public PopupMenus() {

super("PopupMenus"); setDefaultCloseOperation( EXIT_ON_CLOSE );

//получаем всплывающее меню

JPopupMenu popup = createPopupMenu();

//и привязываем к нашей панели содержимого

((JComponent)getContentPane()). setComponentPopupMenu(popup);

//"прозрачная" для меню кнопка

JButton button = new JButton("Проба пера"); button.setInheritsPopupMenu(true); add(button, "South");

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

}

// создаем наше всплывающее меню private JPopupMenu createPopupMenu() {

//создаем само всплывающее меню

JPopupMenu pm = new JPopupMenu();

//создаем его пункты

JMenuItem good = new JMenuItem("Отлично");

JMenuItem excellent = new JMenuItem("Замечательно"); // и добавдяем все тем же методом add() pm.add(good);

274

ГЛАВА 10

 

pm.add(excellent);

 

return pm;

 

}

 

public static void main(String[] args) {

 

SwingUtilities.invokeLater(

 

new Runnable() {

 

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

}

}

 

В этом примере мы создаем простейшее всплывающее меню из двух элементов; это делает метод createPopupMenu(). Как видно, все действия аналогичны тем, что мы делали при создании выпадающих меню JMenu. После того как всплывающее меню подготовлено к работе, необходимо определить, где и при каком условии нужно вывести его на экран. Так как на различных платформах способ вызова всплывающего меню может быть разным, момент, когда это необходимо сделать, определяет в Swing текущий менеджер внешнего вида и поведения2. Ну а само меню задается для конкретного компонента, методом setComponentPopupMenu(). В примере мы задаем меню сразу же для всей панели содержимого нашего окна. Данный метод находится в базовом классе библиотеки JComponent, и таким образом доступен для всех компонентов. Есть еще один интересный метод для всплывающих меню с названием setInheritsPopupMenu(). Это булево свойство, по умолчанию отключенное (равное false). Означает оно, что компонент будет унаследовать всплывающее меню от своего компонента-предка (как правило контейнера). В нашем примере кнопка унаследует всплывающее меню от панели содержимого, в чем вы сможете легко убедиться, запустив программу.

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

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

Реализовано всплывающее меню в Swing достаточно разумно. В обычной ситуации оно представляет собой легковесный компонент, унаследованный от базового класса

2 Для большинства платформ это щелчок правой кнопкой мыши или сочетание клавиш ShiftF10. Интересно, что сочетание клавиш вызовет меню для компонента, обладающего фокусом ввода, а иногда требуется вызывать его и для не способных обладать фокусом компонентов.

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