Учебная страница курса биоинформатики,
год поступления 2010
Графический пользовательский интерфейс (GUI)
Взаимодействие с программой часто удобнее осуществлять через графический пользовательский интерфейс (GUI – Graphical User Interface) с кнопочками, окошечками, иконками и др. наглядными элементами. До Java графические библиотеки отражали особенности ОС и, меняя ОС, приходилось привыкать к новым графическим функциям, даже если не менялся язык программирования. Java же, как мы знаем, - кросс-платформенный язык и значит его графические библиотеки не должны зависеть от конкретной графической системы. В Java GUI состоит из двух частей: зависимой от ОС (обычно оно остается скрытым от разработчика) и независимой от ОС.
Есть две основные графические библиотеки java.awt.* и javax.swing.*. Первая содержит помимо всего прочего старые реализации графических элементов.
За графическое окно отвечает класс JFrame, и все конкретные окна должны его наследовать. Пример пустого окна:
Это окно вполне полноценно. Но если вы кликнет на крестик, окно скроется, но программа так и продолжит работать. Если вы хотите, чтобы с закрытием окна программа завершалась, надо добавить строчку:
1 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Важными понятием GUI является компонент (JComponent). Это абстрактный класс – вершина иерархии компонентов в пакете swing. Примерами компонентов могут быть кнопки, лэйблы, текстовые поля и т.д. Рассмотрим основные свойства этого класса:
Положение компонента описывается двумя целыми числами (тип int) x и y. В Java (как и во многих языках программирования) ось x проходит традиционно – горизонтально, направлена вправо, а ось у – вертикально, но направлена вниз, а не вверх, как принято в математике. Для компонента эта точка задает положение левого верхнего угла.
Размер. Компонент имеет прямоугольную форму, а потому его размер описывается также двумя целочисленными параметрами – width (ширина) и height (высота).
1 setSize(int x, int y), getWidth(), getHeigth(), setBounds()
Видимость: setVisible(boolean), isVisible()
Цвет: set/get Foreground/Background() .
Цвет хранится в объекте класса Color: Color(int r, int g, int b), Color.RED
Container. Существует еще одно важное свойство другого характера. Очевидно, что практически всегда пользовательский интерфейс состоит из более чем одного компонента. В больших приложениях их обычно гораздо больше. Так вот к каждый компонент можно положить другой компонент (или даже несколько). Таким образом, компонент выступает в роли контейнера. Важно отметить, что компонент может находиться лишь в одном компоненте. Это означает, что все элементы сложного пользовательского интерфейса объединяются в иерархическое дерево. Каждый компонент знает, в каком компоненте он лежит, и какие компоненты лежат в нем. Соответственно положение компонента (x, y) отсчитывается от верхнего левого угла того компонента, в котором он находится.
Контейнеру можно добавлять компоненты, вызвая метод void add(JComponent).
Простые компоненты (наследники JComponent):
JLabel - строка текста (не редактируемая); назначение – отобразить строку текста (название поля, списка…); может использоваться для отображения иконок
JButton – кнопка; одно состояние (всегда не нажата); назначение – выполнить некоторое действие после нажатия;
JTextField - область ввода одной строки текста (поле ввода); назначение – отображать текст, вводить и редактировать текст
JTextArea - область ввода текста с произвольным количеством строк; назначение – отображать текст, вводить и редактировать текст
Пример окна с лейблом:
1 import javax.swing.JFrame;
2 import javax.swing.JLabel;
3 public class TestFrame
4 {
5 public static void main(String[] args)
6 {
7 JFrame frame = new JFrame("My First Frame");
8 frame.getContentPane().setLayout(null);// "заклинание", определяющее способ расположения компонентов
9 JLabel label = new JLabel("label");
10 label.setBounds(30,70,100,20);
11 frame.getContentPane().add(label);
12 frame.setSize(400, 350);
13 frame.setVisible(true);
14 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
15 }
16 }
frame.getContentPane() возвращает главный контейнер окна.
Графические события
Графические события вызываются графической системой Java в ответ на действия пользователя, и не только. На этом занятии мы рассмотрим только те события, которые возникают в ответ на действия пользователя. Например:
- Нажатие на клавишу клавиатуры
- Нажатие на кнопку
- Нажатие на кнопку мыши
- Движение мыши
- …
Что значит реагировать на события с точки зрения программирования? Это значит выполнять определенный код после наступления определенного события. У события всегда есть источник (объект, с которым событие ассоциируется), например кнопка. И слушатель или наблюдатель (он же обработчик). Это класс, содержащий код реакции на событие). Источник всегда знает, какие слушатели к нему прикреплены. Когда с наблюдаемым объектом что-то происходит (например, на кнопку нажали), создается объект "событие" (event), который "посылается" всем слушателям. Так слушатель узнает, например, о действии пользователя и может на него отреагировать в зависимости от свойств события.
Содержимое события
Конкретное событие – экземпляр соответствующего класса (по принятому соглашению название класса заканчивается на Event). Несет в себе информацию, характерную для данного типа события (например, какой объект является источником этого события).
MouseEvent – возникает в результате нажатия кнопок мыши, передвижения мыши
KeyEvent – возникает при нажатии клавиш клавиатуры
ActionEvent - семантический тип событий. То действие, в результате которого возникает ActionEvent, определяется типом источника. Например, у кнопки – это ее нажатие, у текстового поля – нажатие Enter в нем. Т.е. все детали обработки движения и нажатия мышки опускаются, а вместо них генерируется вполне понятное события типа «кнопка нажата».
1 Object getSource()
Чтобы между GUI и программой состоялся разговор на языке событий необходимо:
- описать класс слушателя: его методы будут вызываться графической системой при наступлении событий и
зарегистрировать экземпляр этого класса в графической системе, то есть присоединить этого слушателя к источнику событий – какому-то компоненту.
Интерфейсы слушателей
Слушатель, получающий информацию о событиях, – это класс, расширяющий специальный интерфейс, соответствующий типу получаемых событий:
ActionEvent – ActionListener
KeyEvent – KeyListener
MouseEvent – MouseListener
…Event – …Listener
(Библиотека java.awt.event)
Интерфейс ActionListener содержит всего один метод:
Чтобы кнопка реагировала как-то на ее нажатие, нужно добавить ей слушателя - объект класса, реализующий интерфейс слушателя (в данном случае ActionListener):
То же самое можно реализовать без описания класса слушателя отдельно, а воспользоваться анонимной реализацией (также бывает анонимное расширение):
Это удобно только в том случае, если вы собираетесь создавать всего один объект этого класса без названия.
Когда объект "кнопка" поймет, что на него нажали и пора оповестить об этом всех слушателей, он создаст послание ActionEvent, пробежится по всем зарегистрированным слушателям (ActionListener), и у каждого из них вызовет метод actionPerformed(ActionEvent).
Интерфейсы слушателей для события MouseEvent:
1 public interface MouseListener extends EventListener
2 {
3 public void mouseClicked(MouseEvent e);
4 public void mousePressed(MouseEvent e);
5 public void mouseReleased(MouseEvent e);
6 public void mouseEntered(MouseEvent e);
7 public void mouseExited(MouseEvent e);
8 }
9 public interface MouseMotionListener extends EventListener
10 {
11 public void mouseDragged(MouseEvent e);
12 public void mouseMoved(MouseEvent e);
13 }
Для события KeyEvent:
Классы-адаптеры
Для интерфейсов некоторых слушателей написаны "пустые" реализации – адаптеры. Это сделано для удобства разработчиков. Удобно это потому, что если мы реализуем интерфейс, то нам придется реализовывать все методы, объявленные в нем, но ведь некоторые методы нам просто не нужны, и нам бы пришлось писать для них пустые реализации. В адаптерах ровно это и сделано. Например:
Пример про убегающую кнопку
Представьте, что нам нужно реализовать кнопку, избегающую попадания на нее мышки. В этом случае эта кнопка должна иметь слушатель события вхождения мышки внутрь кнопки. Но также должен быть слушатель для события нажатия кнопки (если вам все же удасться на нее нажать).
1 import java.awt.event.ActionEvent;
2 import java.awt.event.ActionListener;
3 import java.awt.event.MouseAdapter;
4 import java.awt.event.MouseEvent;
5
6 import javax.swing.JButton;
7 import javax.swing.JFrame;
8
9 public class RunningButton extends JFrame
10 {
11 private JButton but;
12
13 public static void main(String[] args)
14 {
15 RunningButton frame = new RunningButton();
16 frame.setVisible(true);
17 }
18 public RunningButton()
19 {
20 super();
21 getContentPane().setLayout(null);
22 setDefaultCloseOperation(EXIT_ON_CLOSE);
23 setSize(500,300);
24 but = new JButton("CATCH ME!");
25 but.setBounds(100, 10, 150, 20);
26 but.addMouseListener(new ButtonMouseListener());
27 but.addActionListener(new ButtonActionListener());
28 this.getContentPane().add(but);
29 }
30 private class ButtonMouseListener extends MouseAdapter
31 {
32 public void mouseEntered(MouseEvent e)
33 {
34 but.setLocation((int)(Math.random()*
35 (but.getParent().getWidth()-but.getWidth())),
36 (int)(Math.random()*
37 (but.getParent().getHeight()-but.getHeight())));
38 }
39 }
40 private class ButtonActionListener implements ActionListener
41 {
42 public void actionPerformed(ActionEvent e)
43 {
44 System.out.println("You are a winner!!!");
45 }
46 }
47 }