Оглавление
Окна и диалоговые панели |
Как мы уже говорили, приложение MenuApp работает автономно. Поэтому мы импортируем только класс java.awt.*, необходимый для работы с окнами:
import java.awt.*;
В нашем приложении определено три класса - MenuApp, MainFrameWnd и MessageBox.
Класс MenuAppВ главном классе приложения MenuApp мы определили только один метод main. Этот метод получает управление при запуске приложения.
Первым делом метод main создает объект класса MainFrameWnd, определенного в нашем приложении:
MainFrameWnd frame = new MainFrameWnd("MenuApp");
Этот класс, созданный на базе класса Frame, определяет поведение главного окна нашего приложения.
На втором шаге метод init настраивает размеры главного окна с учетом размеров внешней рамки и заголовка окна:
frame.setSize(frame.getInsets().left + frame.getInsets().right + 320, frame.getInsets().top + frame.getInsets().bottom + 240);
Поля left и right объекта класса Insets, ссылку на который возвращает метод getInsets, содержат ширину левой и правой части рамки окна, соответственно. Поле top содержит высоту верхней части рамки окна с учетом заголовка, а поле bottom - высоту нижней части рамки окна.
Для отображения окна фрейма мы вызываем метод show, как это показано ниже:
frame.show();Класс MainFrameWnd
Класс MainFrameWnd создан на базе класса Frame:
class MainFrameWnd extends Frame { . . . }
В нем мы определили три поля, конструктор, методы paint, handleEvent и action.
Поле mbMainMenuBar предназанчено для хранения ссылки на главное меню приложения, создаваемое как объект класса MenuBar:
MenuBar mbMainMenuBar;
Поля mnFile и mnHelp хранят ссылки на меню File и Help, соответственно:
Menu mnFile; Menu mnHelp;
Данные меню создаются на базе класса Menu.
В качестве единственного параметра конструктору класса MainFrameWnd передается заголовок создаваемого окна. В первой исполняемой строке наш конструктор вызывает конструктор из базового класса, передавая ему строку заголовка через параметр:
public MainFrameWnd(String sTitle) { super(sTitle); . . . }
Далее конструктор определяет размеры окна, вызывая для него метод setSize:
setSize(400, 200);
Затем мы устанавливаем для нашего окна желтый цвет фона и черный цвет изображения:
setBackground(Color.yellow); setForeground(Color.black);
По умолчанию для окон класса Frame устанавливается режим добавления компонент BorderLayout. Мы изменяем этот режим на FlowLayout, вызывая метод setLayout:
setLayout(new FlowLayout());
Далее конструктор приступает к формированию главного меню окна. Это меню создается как объект класса MenuBar:
mbMainMenuBar = new MenuBar();
Затем мы создаем и наполняем меню "File":
mnFile = new Menu("File");
mnFile.add("New"); mnFile.add("-"); mnFile.add("Exit");
Это меню создается на базе класса Menu. Обратите внимание, что между строками New и File расположен разделитель.
Аналогичным образом мы добавляем в главное меню другое меню - "Help":
mnHelp = new Menu("Help");
mnHelp.add("Content"); mnHelp.add("-"); mnHelp.add("About");
После своего окончательного формирования меню "File" и "Help" добавляются в главное меню окна mbMainMenuBar:
mbMainMenuBar.add(mnFile); mbMainMenuBar.add(mnHelp);
И, наконец, когда главное меню будет сформировано, оно подключается к окну вызовом метода setMenuBar, как это показано ниже:
setMenuBar(mbMainMenuBar);
Метод paint получает в качестве параметра ссылку на контекст отображения, пригодный для рисования в нашем окне. Пользуясь этим контекстом, мы устанавливаем шрифт текста и рисуем текстовую строку. Затем мы вызываем метод paint из базового класса Frame, на основе которого создан наш класс MainFrameWnd:
public void paint(Graphics g) { g.setFont(new Font( "Helvetica", Font.PLAIN, 12));
g.drawString("Frame window", 10, 70);
super.paint(g); }
Для того чтобы определить реакцию окна на попытку пользователя закрыть окно с помощью органов управления, расположенных в заголовке окна, или другим способом, мы переопределили метод handleEvent.
При получении кода события Event.WINDOW_DESTROY (удаление окна) мы скрываем окно, вызывая метод setVisible с параметром false.
Затем с помощью статического метода exit класса System мы завершаем работу интерпретатора:
public boolean handleEvent(Event evt) { if(evt.id == Event.WINDOW_DESTROY) { setVisible(false); System.exit(0); return true; } else return super.handleEvent(evt); }
Этот метод обрабатывает события, возникающие при выборе строка из меню.
В начале своей работы метод action проверяет, действительно ли событие вызвано меню:
MenuItem mnItem;
if(evt.target instanceof MenuItem) { . . . } return false;
Если это так, в поле mnItem сохраняется ссылка на элемент меню, вызвавший событие:
mnItem = (MenuItem)evt.target;
Тем не менее, для определения строки, выбранной пользователем, нам достаточно проанализировать второй параметр метода action:
if(obj.equals("Exit")) { System.exit(0); }
else if(obj.equals("New")) { MessageBox mbox;
mbox = new MessageBox( "Item New selected", this, "Dialog from Frame", true); mbox.show(); }
else if(obj.equals("Content")) { . . . }
else if(obj.equals("About")) { . . . }
В данном случае второй параметр метода action будет представлять собой ссылку на строку, выбранную из меню, поэтому для определения выбранной строки мы можем выполнить простое сравнение методом equals.
Если пользователь выбрал из меню File строку Exit, мы вызываем метод System.exit, предназначенный для завершения работы виртуальной машины Java.
В том случае когда пользователь выбирает любую другую строку из меню, метод action создает диалоговую панель на базе определенного нами класса MessageBox. В этой диалоговой панели отображаетя название выбранной строки меню.
Заметим, что сразу после создания конструктором диалоговая панель не появляется на экране. Мы отображаем ее, вызывая метод show.
Для отображения названий выбранных строк меню мы создаем диалоговую панель, определив свой класс MessageBox на базе класса Dialog, как это показано ниже:
class MessageBox extends Dialog { . . . }
В классе MessageBox есть два поля, конструктор, методы handleEvent и action.
Внутри диалоговой панели мы расположили текстовое поле класса Label, предназначенное для отображения сообщения, и кнопку с надписью OK, с помощью которой можно завершить работу диалоговой панели.
Ссылка на текстовое поле хранится в поле lbMsg, на кнопку - в поле btnOK.
Наш конструктор создает диалоговую панель с заданным сообщением внутри нее. Ссылка на строку сообщения передается конструктору через первый параметр. Остальные параметры используются конструктором базового класса Dialog для создания диалоговой панели:
super(parent, sTitle, modal);
После вызова конструктора из базового класса наш конструктор устанавливает размеры окна созданной диалоговой панели, вызывая метод resize:
resize(200, 100);
Отменяя установленный по умолчанию режим размещения компонент BorderLayout, конструктор устанавливает режим GridLayout:
setLayout(new GridLayout(2, 1));
Окно диалоговой панели при этом разделяется на две части по горизонтали. В верхнюю часть добавляется текстовое поле для отображения сообщения, в нижнюю - кнопка OK:
lbMsg = new Label(sMsg, Label.CENTER); add(lbMsg); btnOK = new Button("OK"); add(btnOK);
Когда пользователь пытается закрыть окно диалоговой панели, например, сделав двойной щелчок левой клавишей мыши по системному меню или одиночный щелчок по кнопке удаления окна, возникает событие Event.WINDOW_DESTROY. Мы его обрабатываем следующим образом:
if(evt.id == Event.WINDOW_DESTROY) { dispose(); return true; } else return super.handleEvent(evt);
Вызывая метод dispose, мы удаляем окно диалоговой панели и освобождаем все связанные с ним ресурсы.
Если пользователь нажимает кнопку OK, расположенную в окне диалоговой панели, метод action вызывает для панели метод dispose, удаляя эту панель с экрана и из памяти:
if(evt.target.equals(btnOK)) { dispose(); }