Механизм обратного вызова(callback) широко распространен в программировании. При обратном вызове программист задает действия, которые должны выполняться всякий раз, когда происходит некоторое событие. Например, можно задать действие, которое должно быть выполнено после щелчка на некоторой кнопке или при выборе определенного пункта меню. Мы рассмотрим простую ситуацию.
Пакет javax.swing содержит класс Timer, который можно использовать для отсчета интервалов времени. Например, если в программе предусмотрены часы, то с помощью класса Timer можно отсчитывать каждую секунду и обновлять циферблат часов.
Устанавливая таймер, мы задаем интервал времени и указываем, что должно произойти по его истечении.Как указать таймеру, что он должен делать? Во многих языках программирования задается имя функции, которую таймер должен периодически вызывать. Однако классы из стандартной библиотеки языка Java используют объектно-ориентированный подход. Программист должен передать таймеру объект некоторого класса. После этого таймер вызывает один из методов данного объекта. Передача объекта — более гибкий механизм, чем вызов функции, поскольку объект может нести дополнительную информацию.
Разумеется, таймер должен знать, какой метод он должен вызывать. Для этого таймеру нужно указать обьект класса, реализующего интерфейс ActionListener из пакета java.awt.event. Этот интерфейс выглядит следующим образом:
1 2 3 |
public interface ActionListener { void actionPerformed(ActionEvent event); } |
По истечении заданного интервала времени таймер вызывает метод actionPerformed().
Предположим, нам нужно каждый десять секунд выводить на экран сообщение о текущем времени, сопровождаемое звуковым сигналом. Для этого необходимо определить класс, реализующий интерфейс ActionListener, а затем поместить операторы, которые нужно выполнить, в тело метода actionPerformed().
1 2 3 4 5 6 7 |
class TimePrinter implement ActionListener { public void actionPerformed(ActionEvent event) { Date now = new Date(); System.out.println("Звонок, время: " + now); Toolkit.getDefaultToolKit().beep(); } } |
Обратите внимание на параметр ActionEvent метода actionPerformed(). Он содержит информацию о событии, например, об объекте, его породившем. В данной программе детальная информация о событии не важна, поэтому можно просто проигнорировать этот параметр.
Затем следуют создать объект данного класса и передать его конструктору класса Timer:
1 2 |
ActionListener listener = new TimePrinter(); Timer t = new Timer(1000, listener); |
Первый параметр конструктора Timer представляет собой интервал времени между точками отсчета, измеренный в миллисекундах. Сообщение должно выдаваться на экран каждые десять секунд. Второй параметр является объектом класса ActionListener.
Итак, запускаем таймер:
1 |
t.start(); |
Каждые десять секунд на экране будет появляться следующее сообщение, сопровождаемое звуковым сигналом:
Звонок, время: Wed May 15 00:22:37 PDT 2013
После запуска таймера программа выводит на экран окно с сообщением и ждет, пока пользователь не щелкнет на кнопке ОК, чтобы завершить работу, при этом на экран каждые десять секунд выводится текущее время.
Будьте терпеливы. После того как диалоговое окно с вопросом Завершить программу? отобразится на экране, первое сообщение таймера появится только через десять секунд.
Отмечу, что в дополнение к пакетам javax.swing.* и java.util.* программа импортирует класс javax.swing.Timer. Как идите, при импортировании указано имя класса. Это позволяет избежать неоднозначность. Дело в том, что существует класс java.util.Timer, который к нашей задаче отношения не имеет.
Вот код всей программы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.Timer; import javax.swing.JOptionPane; public class TimerTest { public static void main(String[] args) { ActionListener listener = new TimePrinter(); // Создание таймера, вызывающего обработчик каждые 10 секунд Timer t = new Timer(10000, listener); t.start(); JOptionPane.showMessageDialog(null, "Завершить программу"); System.exit(0); } } class TimePrinter implements ActionListener { public void actionPerformed(ActionEvent event) { Date now = new Date(); System.out.println("Звонок, время: " + now); Toolkit.getDefaultToolkit().beep(); } } |