Программирование мобильных телефонов на Java


Программирование мобильных телефонов

  • Введение
  • Глава 1. Устройство мобильных телефонов
  • Глава 2. Платформа Java 2 Micro Edition
  • Глава 3. Средства разработки мобильных приложений
  • Глава 4. Телефонные эмуляторы
  • Глава 5. Механизм работы приложений Java 2 ME
  • Глава 6. Классы пользовательского интерфейса
  • Глава 7. Программирование графики
  • Глава 8. Техника создания игр
  • Глава 9. Мобильная мультимедиа-библиотека
  • Заключение
  • Приложение 1. Основы языка Java
  • Приложение 2. Справочник по Java 2 Micro Edition

     

    Программирование на Java

  • Введение
  • Глава 1. Встроенные типы данных, операции над ними
  • Глава 2. Объектно-ориентированное программирование в Java
  • Глава 3. Пакеты и интерфейсы
  • Глава 4. Классы-оболочки
  • Глава 5. Работа со строками
  • Глава 6. Классы-коллекции
  • Глава 7. Классы-утилиты
  • Глава 8. Принципы построения графического интерфейса
  • Глава 9. Графические примитивы
  • Глава 10. Основные компоненты
  • Глава 11. Размещение компонентов
  • Глава 12. Обработка событий
  • Глава 13. Создание меню
  • Глава 14. Апплеты
  • Глава 15. Изображения и звук
  • Глава 16. Обработка исключительных ситуаций
  • Глава 17. Подпроцессы
  • Глава 18. Потоки ввода/вывода
  • Глава 19. Сетевые средства Java
  • Приложение. Развитие Java

  • 

    3fb01dc2


     

     

    ГЛАВА 12
    Обработка событий

    В двух предыдущих главах мы написали много программ, создающих интерфейсы, но, собственно, интерфейса, т. е. взаимодействия с пользователем, эти программы не обеспечивают. Можно щелкать по кнопке на экране, она будет "вдавливаться" в плоскость экрана, но больше ничего не будет происходить. Можно ввести текст в поле ввода, но он не станет восприниматься и обрабатываться программой. Все это происходит из-за того, что мы не задали обработку действий пользователя, обработку событий.

    Событие (event) в библиотеке AWT возникает при воздействии на компонент какими-нибудь манипуляциями мышью, при вводе с клавиатуры, при перемещении окна, изменении его размеров.

    Объект, в котором произошло событие, называется источником (source) события.

    Все события в AWT классифицированы. При возникновении события исполняющая система Java автоматически создает объект соответствующего событию класса. Этот объект не производит никаких действий, он только хранит все сведения о событии.

    Во главе иерархии классов-событий стоит класс Eventobject из пакета java.utii — непосредственное расширение класса object. Его расширяет абстрактный класс AWTEvent из пакета java.awt — глава классов, описывающих события библиотеки AWT. Дальнейшая иерархия классов-событий показана на рис. 12.1. Все классы, отображенные на рисунке, кроме класса AWTEvent, собраны в пакет java.awt.event.

    События типа ComponentEvent, FbeusEvent, KeyEvent, MouseEvent возникают во всех компонентах.

    А события типа ContainerEvent — только в контейнерах: Container, Dialog, FileDialog, Frame, Panel, ScrollPane, Window.

     

    Рис. 12.1 . Иерархия классов,  описывающих события AWT

    События типа WindowEvent возникают ТОЛЬКО В окнах: Frame, Dialog, FileDialog, Window.

    События типа TextEvent генерируются только в контейнерах Textcomponent, TextArea, TextField.

    События типа ActionEvent проявляются только в контейнерах Button, List, TextField.

    События типа ItemEvent возникают только в контейнерах Checkbox, Choice, List.

    Наконец, события типа AdjustmentEvent возникают только в контейнере Scrollbar.

    Узнать, в каком объекте произошло событие, можно методом getsourceo класса Eventobject. Этот метод возвращает тип object.

    В каждом из этих классов-событий определен метод paramstring (), возвращающий содержимое объекта данного класса в виде строки string. Кроме того, в каждом классе есть свои методы, предоставляющие те или иные сведения о событии. В частности, метод getioo возвращает идентификатор (identifier) события — целое число, обозначающее тип события. Идентификаторы события определены в каждом классе-событии как константы.

    Методы обработки событий описаны в интерфейсах- слушателях (listener). Для каждого показанного на рис. 12.1 типа событий, кроме inputEvent (это событие редко используется самостоятельно), есть свой интерфейс. Имена интерфейсов составляются из имени события и слова Listener, например, ActionListener, MouseListener. Методы интерфейса "слушают", что происходит в потенциальном источнике события. При возникновении события эти методы автоматически выполняются, получая в качестве аргумента объект-событие и используя при обработке сведения о событии, содержащиеся в этом объекте.

    Чтобы задать обработку события определенного типа, надо реализовать соответствующий интерфейс. Классы, реализующие такой интерфейс, классы-обработчики (handlers) события,, называются слушателями (listeners): они "слушают", что происходит в объекте, чтобы отследить возникновение события и обработать его.

    Чтобы связаться с обработчиком события, классы-источники события должны получить ссылку на экземпляр eventHandier класса-обработчика события одним из методов addXxxListener(XxxEvent eventHandier), где Ххх — имя события.

    Такой способ регистрации, при котором слушатель оставляет "визитную карточку" источнику для своего вызова при наступлении события, называется обратный вызов (callback). Им часто пользуются студенты, которые, звоня родителям и не желая платить за телефонный разговор, говорят: "Перезвони мне по такому-то номеру". Обратное действие — отказ от обработчика, прекращение прослушивания — выполняется методом removeXxxListener ().

    Таким образом, компонент-источник, в котором произошло событие, не занимается его обработкой. Он обращается к экземпляру класса-слушателя, умеющего обрабатывать события, делегирует (delegate) ему полномочия по обработке.

    Такая схема получила название схемы делегирования (delegation). Она удобна тем, что мы можем легко сменить класс-обработчик и обработать событие по-другому или назначить несколько обработчиков одного и того же события. С другой стороны, мы можем один обработчик назначить на прослушивание нескольких объектов-источников событий.

    Эта схема кажется слишком сложной, но мы ей часто пользуемся в жизни. Допустим, мы решили оборудовать квартиру. Мы помещаем в нее, как в контейнер, разные компоненты: мебель, сантехнику, электронику, антиквариат. Мы предполагаем, что может произойти неприятное событие — квартиру посетят воры, — и хотим его обработать. Мы знаем, что классы-обработчики этого события — охранные агентства, — и обращаемся к некоторому экземпляру такого класса. Компоненты-источники события, т. е. те, которые могут быть украдены, присоединяют к себе датчики методом addXxxListener(). Затем экземпляр-обработчик "слушает", что происходит в объектах, к которым он подключен. Он реагирует на наступление только одного события — похищения прослушиваемого объекта, — прочие события, например, короткое замыкание или обрыв водопроводной трубы, его не интересуют. При наступлении "своего" события он действует по контракту, записанному в методе обработки.

    Замечание

    В JDK 1.0 была принята другая модель обработки событий. Не удивляйтесь, читая старые книги и просматривая исходные тексты старых программ, но и не пользуйтесь старой моделью.

    Приведем пример. Пусть в контейнер типа Frame помещено поле ввода tf типа TextField, не редактируемая область ввода ta типа TextArea и кнопка ь типа Button. В поле tf вводится строка, после нажатия клавиши <Enter> или щелчка кнопкой мыши по кнопке ь строка переносится в область ta. После этого можно снова вводить строку в поле tf и т. д.

    Здесь и при нажатии клавиши <Enter> и при щелчке кнопкой мыши возникает событие класса ActionEvent, причем оно может произойти в двух компонентах-источниках: поле tf или кнопке ь. Обработка события в обоих случаях заключается в получении строки текста из поля tf (например, методом tf .getTexto) и помещений ее в область ta (скажем, методом ta. append ()). Значит, можно написать один обработчик события ActionEvent, реализовав соответствующий интерфейс, который называется ActionListener. В этом Интерфейсе всего один метод actionPerformed().

    Итак, пишем:

    class TextMove implements ActionListener{

    private TextField tf;

    private TextArea ta;

    TextMove(TextField tf, TextArea ta){ 

    this.tf = tf; this.ta = ta;

    }

    public void actionPerformed(ActionEvent ae){ 

    ta.append(tf.getText()+"\n");

    }

    Обработчик событий готов. При наступлении события типа ActionEvent будет создан экземпляр класса-обработчика TextMove, конструктор получит ссылки на конкретные поля объекта-источника, метод actionPerformed (), автоматически включившись в работу, перенесет текст из одного поля в другое.

    Теперь напишем класс-контейнер, в котором находятся источники tf и ь события ActionEvent, и подключим к ним слушателя этого события TextMove, передав им ссылки на него методом addActionListenerO, как показано в листинге 12.1.

    Листинг 12.1. Обработка события ActionEvent 

    import j ava.awt.*;

    impo rt j ava.awt.event.*;

    class MyNotebook extends Frame{ 

    MyNotebook(String title) {

    super(title);

    TextField tf = new TextField("Вводите текст", 50); 

    add(tf, BorderLayout.NORTH);

    TextArea ta = new TextArea(); 

    ta.setEditable(false); 

    add(ta);

    Panel p = new Panel(); 

    add(p, BorderLayout.SOUTH);

    Button b = new Button("Перенести"); 

    p.add(b);

    tf.addActionListener(new TextMove(tf, ta)); 

    b.addActionListener(new TextMove(tf, ta));

    setSize(300, 200); setvisible(true); 

    public static void main(String[] args){

    Frame f = new MyNotebook(" Обработка ActionEvent"); 

    f.addWindowListener(new WindowAdapter(){

    public void windowClosing(WindowEvent ev){

    System.exit(0); 

    }

    }); 

    }

    // Текст класса TextMove 

    // ...

    На рис. 12.2 показан результат работы с этой программой.

    В листинге 12.1 в методах addActionListener() создаются два экземпляра класса TextMove — для прослушивания поля tf и для прослушивания кнопки ь. Можно создать один экземпляр класса TextMove, он будет прослушивать оба компонента:

    TextMove tml = new TextMove(tf, ta); 

    tf.addActionListener(tml); 

    b.addActionListener(tml);

    Но в первом случае экземпляры создаются после наступления события в соответствующем компоненте, а во втором — независимо от того, наступило событие или нет, что приводит к расходу памяти, даже если событие не произошло. Решайте сами, что лучше.

    Рис. 12.2. Обработка события  ActionEvent

    Класс, содержащий источники события, может сам обрабатывать его. Вы можете самостоятельно прослушивать компоненты в своей квартире, установив пульт сигнализации у кровати.

    Для этого достаточно реализовать соответствующий интерфейс прямо в классе-контейнере, как показано в листинге 12.2.

    Листинг 12.2. Самообработка события ActionEvent 

    import j ava.awt.*; 

    import java.awt.event.*;

    class MyNotebook extends Frame implements ActionListener{ 

    private TextField tf; 

    private TextArea ta; 

    MyNotebook(String title){ 

    super(title) ;

    tf = new TextField ("Вводите текст**", 50) ; 

    add(tf, BorderLayout.NORTH);

    ta = new TextArea(); 

    ta.setEditable(false); 

    add(ta);

    Panel p = new Panel();

    add(p, BorderLayout.SOUTH);

    Button b = new Button("Перенести"); 

    p.add(b);

    tf.addActionListener(this) ; 

    b.addActionListener(this) ;

    setSize(300, 200); setVisible(true) ; } 

    public void actionPerformed(ActionEvent ae){

    ta.append(tf.getText()+"\n"); } 

    public static void main(String[] args){

    Frame f = new MyNotebook(" Обработка ActionEvent"); 

    f.addWindowListener(new WindowAdapter(){

    public void windowClosing(WindowEvent ev){

    System.exit(0); 

    }

    }); 

    }

    Здесь tf и ta уже не локальные переменные, а переменные экземпляра, поскольку они используются и в конструкторе, и в методе actionPerformed о. Этот метод теперь — один из методов класса MyNotebook. Класс MyNotebook стал классом-обработчиком события ActionEvent — он реализует интерфейс ActionListener. В МвТОДе addActionListener () указывается аргумент this — класс сам слушает свои компоненты.

    Рассмотренная схема, кажется, проще и удобнее, но она предоставляет меньше возможностей. Если вы захотите изменить обработку, например заносить записи в поле ta по алфавиту или по времени выполнения заданий, то придется переписать и перекомпилировать класс MyNotebook.

    Еще один вариант — сделать обработчик вложенным классом. Это позволяет обойтись без переменных экземпляра и конструктора в классе-обработчике TextMove, как показано в листинге 12.3.

    Листинг 12.3. Обработка вложенным классом

    import Java.awt.*; 

    import j ava.awt.event.*;

    class MyNotebook extends Frame{ private TextField tf; 

    private TextArea ta; 

    MyNotebook(String title){

    super(title);

    tf = new TextField("Вводите текст", 50);

    add(tf, BorderLayout.NORTH);

    ta = new TextArea();

    ta.setEditable(false);

    add (tab-Panel p = new Panel();

    add(p, BorderLayout.SOUTH);

    Button b = new Button("Перенести");

    p.add(b);

    tf.addActionListener(new TextMove()); 

    b.addActionListener(new TextMove());

    setSizepOO, 200);

    setVisible(true); 

    public static void main(String[] args){

    Frame f = new MyNotebook(" Обработка ActionEvent");

    f.addWindowListener(new WindowAdapter(){

    public void windowClosing(WindowEvent ev){

    System.exit (0);

    }

    }); 

    }

    // Вложенный класс 

    class TextMove implements ActionListener{

    public void actionPerformed(ActionEvent ae){

    ta.appendftf.getText()+"\n"); 

    }

    }

    Наконец, можно создать безымянный вложенный класс, что мы и делали в этой и предыдущих главах, обрабатывая нажатие комбинации клавиш <Alt>+<F4> или щелчок кнопкой мыши по кнопке закрытия окна. При этом возникает событие типа windowEvent, для его обработки мы обращались к методу windowciosingo, реализуя его обращением к методу завершения приложения'System.exit (0). Но для этого нужно иметь суперкласс определяемого безымянного класса, такой как windowAdapter. Такими суперклассами могут быть классы-адаптеры, о них речь пойдет чуть ниже.

    Перейдем к детальному рассмотрению разных типов событий.

    Событие ActionEvent

    Это простое событие означает, что надо выполнить какое-то действие. При этом неважно, что вызвало событие: щелчок мыши, нажатие клавиши или что-то другое.

    В классе ActionEvent есть два полезных метода:

    • метод getActionCommand () возвращает в виде строки string надпись на кнопке Button , точнее, то, что установлено методом setActionCoramand (String s) класса Button , выбранный пункт списка List , или что-то другое, зависящее от компонента;
    • метод getModifiers() возвращает код клавиш <Alt>, <Ctrl>, <Meta> или <Shift> , если какая-нибудь одна или несколько из них были нажаты, в виде числа типа int ; узнать, какие именно клавиши были нажаты, можно сравнением со статическими константами этого класса ALT_MASK , CTRL_MASK, META_MASK, SHIFT_MASK.

    Примечание

    Клавиши <Meta> на PC-клавиатуре нет, ее действие часто назначается на клавишу <Esc> или левую клавишу <Alt>.

    Например:

    public void actionPerformed(ActionEvent ae){ 

    if (ae.getActionCommand() == "Open" &&

    (ae.getModifiers() | ActionEvent.ALT_MASK) != 0){ 

    // Какие-то действия 

    }

     

    -
    



    Copyright © vzlom-1.ru 2020-2021