Книга о языке Java

ГЛАВА 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. Программа рисования с меню

Далее