ГЛАВА 13
Создание меню на java
В контейнер типа Frame заложена возможность установки стандартной строки меню (menu bar), располагаемой ниже строки заголовка, как показано на рис. 13.1. Эта строка — объект класса MenuBar.
Все, что нужно сделать для установки строки меню в контейнере Frame — это создать объект класса MenuBar и обратиться к методу setMenuBar ():
Frame f = new Frame("Пример меню");
MenuBar mb = new MenuBar();
f.setMenuBar(mb);
Если имя mb не понадобится, можно совместить два последних обращения к методам:
f.setMenuBar(new MenuBar());
Разумеется, строка меню еще пуста и пункты меню не созданы.
Каждый элемент строки меню — выпадающее меню (drop-down menu ) — это объект класса Menu. Создать эти объекты и занести их в строку меню ничуть не сложнее, чем создать строку меню:
Menu mFile = new Menu("Файл");
mb.add(mFile);
Menu mEdit = new Menu("Правка");
mb.add(mEdit);
Menu mView = new Menu("Вид");
mb.add(mView);
Menu mHelp = new Menu("Справка");
mb.setHelpMenu(mHelp);
и т. д. Элементы располагаются слева направо в порядке обращений к методам add(), как показано на рис. 13.1. Во многих графических системах принято меню Справка (Help) прижимать к правому краю строки меню. Это достигается обращением к методу setHelpMenu (), но фактическое положение меню Справка определяется графической оболочкой.
Рис. 13.1. Система меню

Затем определяем каждое выпадающее меню, создавая его пункты. Каждый пункт меню — это объект класса Menuitem. Схема его создания и добавления к меню точно такая же, как и самого меню:
Menuitem create = new Menuitem("Создать");
mFile.add(create);
Menuitem open = new Menuitem("Открыть...");
mFile.add(open);
и т. д. Пункты меню будут расположены сверху вниз в порядке обращения к методам add().
Часто пункты меню объединяются в группы. Одна группа от другой отделяется горизонтальной чертой. На рис. 13.1 черта проведена между командами Открыть и Отправить. Эта черта создается методом addseparator () класса Menu или определяется как пункт меню с надписью специального вида — дефисом:
mFile.addfnew Menuitem("-"));
Интересно, что класс Menu расширяет класс Menuitem, а не наоборот. Это означает, что меню само является пунктом меню, и позволяет задавать меню в качестве пункта другого меню, тем самым организуя вложенные подменю:
Menu send = new Menu("Отправить");
mFile.add(send);
Здесь меню send добавляется в меню mFile как один из его пунктов. Подменю send заполняется пунктами меню как обычное меню.
Часто команды меню создаются для выбора из них каких-то возможностей, подобно компонентам checkbox. Такие пункты можно выделить щелчком кнопки мыши или отменить выделение повторным щелчком. Эти команды — объекты класса CheckboxMenuItem:
CheckboxMenuItem disk = new CheckboxMenuItem("Диск A:", true);
send.add(disk);
send.add(new CheckboxMenuItem("Архив")) ;
И Т.Д.
Все, что получилось в результате перечисленных действий, показано на рис. 13.1.
Многие графические оболочки, но не MS Windows, позволяют создавать отсоединяемые (tear-off) меню, которые можно перемещать по экрану. Это указывается в конструкторе
Menu(String label, boolean tearOff)
Если tearoff == true и графическая оболочка умеет создавать отсоединяемое меню, то оно будет создано. В противном случае этот аргумент просто игнорируется.
Наконец, надо назначить действия командам меню. Команды меню типа Menuitem порождают события типа ActionEvent, поэтому нужно присоединить к ним объект класса-слушателя как к обычным компонентам, записав что-то вроде
create.addActionListener(new SomeActionEventHandler())
open.addActionListener(new AnotherActionEventHandler())
Пункты типа CheckboxMenuItem порождают события типа ItemEvent, поэтому надо обращаться к объекту-слушателю этого события:
disk.addltemListener(new SomeltemEventHandler())
Очень часто действия, записанные в командах меню, вызываются не только щелчком кнопки мыши, но и "горячими" клавишами-акселераторами (shortcut), действующими чаще всего при нажатой клавише <Ctrl>. На экране в пунктах меню, которым назначены "горячие" клавиши, появляются подсказки вида Ctrl+N, Ctrl+O, как на рис. 13.1. "Горячая" клавиша определяется объектом класса MenuShortcut и указывается в его конструкторе константой класса KeyEvent, например:
MenuShortcut keyCreate = new MenuShortcut(KeyEvent.VK_N);
После этого "горячей" будет комбинация клавиш <Ctrl>+<N>. Затем полученный объект указывается в конструкторе класса Menuitem:
Menuitem create = new Menuitem("Создать", keyCreate);
Нажатие <Ctrl>+<N> будет вызывать окно создания. Эти действия, разумеется, можно совместить, например,
Menuitem open = new Menultern("Открыть...",
new -MenuShortcut(KeyEvent.VK_O));
Можно добавить еще нажатие клавиши <Shift>. Действие пункта меню будет вызываться нажатием комбинации клавиш <Shift>+<Ctrl>+<X>, если воспользоваться вторым конструктором:
MenuShortcut(int key, boolean useShift)
С аргументом useShift == true.
Программа рисования, созданная в листинге 12.4 и показанная на рис. 12.3, явно перегружена кнопками. Перенесем их действия в пункты меню. Добавим возможность манипуляции файлами и команду завершения работы. Это сделано в листинге 13.1. Класс scribble не изменялся и в листинге не приведен. Результат показан на рис. 13.2.
Листинг 13.1. Программа рисования с меню
import j ava.awt.*;
import j ava.awt.event.*;
public class MenuScribble extends Frame{
public MenuScribble(String s) { super(s);
ScrollPane pane = new ScrollPane();
pane.setSize(300, 300);
add(pane, BorderLayout.CENTER);
Scribble scr = new Scribble(this, 500, 500);
pane.add(scr);
MenuBar mb = new MenuBar();
setMenuBar(mb);
Menu f = new Menu("Файл");
Menu v = new Menu("Вий");
mb.add(f); mb.add(v);
Menuitem open = new Menuitem("Открыть...",
new MenuShortcut(KeyEvent.VK_0));
Menuitem save = new Menuitem("Сохранить",
new MenuShortcut(KeyEvent.VK_S));
Menuitem saveAs = new Menultera("Сохранить как...");
Menuitem exit = new Menuitem("Выход",
new MenuShortcut(KeyEvent.VK_Q));
f.add(open); f.add(save); f.add(saveAs);
f.addSeparator(); f.add(exit);
open.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
FileDialog fd = new FileDialog(new Frame(),
" Загрузить", FileDialog.LOAD);
fd.setVisible(true);
}
});
saveAs.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
FileDialog fd = new FileDialog(new Frame(),
" Сохранить", FileDialog.SAVE);
fd.setVisible(true);
}
exit.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.exit(0);
}
});
Menu с = new Menu("Цвет");
Menultem clear = new Menultem("Очистить",
new MenuShortcut(KeyEvent.VK_D));
v.add(c); v.add(clear);
Menultem red = new Menultem("Красный");
Menultem green = new Menultem("Зеленый");
Menultem blue = new Menultem("Синий");
Menultem black = new Menultem("Черный");
c.add(red); c.add(green); c.add(blue); c.add(black);
red.addActionListener(scr);
green.addActionListener(scr);
blue.addActionListener(scr) ;
black.addActionListener(scr) ;
clear.addActionListener(scr) ;
addWindowListener(new WinClose()); pack();
setVisible(true) ;
}
class WinClose extends WindowAdapter{
public void windowClosing(WindowEvent e){
System.exit(0);
}
}
public static void main(String[] args){
new MenuScribble(" \"Рисовалка\" с меню");
}
}
Рис. 13.2. Программа рисования с меню
