Система меню
Рисунок 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.