Разработчики Java, особенно те, которые выполняют любой тип работы с графическим интерфейсом, в конечном итоге столкнутся с парадигмой программирования, основанной на событиях Java. Короче говоря, если программисты хотят воздействовать на какое-то событие, они связывают кусок кода в метод Java, обычно называемый обработчиком, и регистрируют обработчик с этим событием. Всякий раз, когда происходит это событие, код обработчика будет выполняться автоматически.
JavaFX предоставляет аналогичный механизм. Для простого примера приведенный ниже код определяет простой таймер в JavaFX с разрешением 1 секунда. Каждый раз, когда истекает секунда, будет выполняться функция, указанная в переменной экземпляра действия . Вот как это выглядит:
import javafx.animation.*;
public class SimpleTimer {
public def timeline = Timeline {
repeatCount: 5
interpolate: false
keyFrames: [
KeyFrame {
time: 1s
action: function () : Void {
println("tick");
}
}
]
}
}
Добавление функции run () , как показано ниже, в конец этого источника позволит вам запустить экземпляр этого таймера:
function run() : Void {
var s = SimpleTimer{};
s.timeline.playFromStart();
}
Вывод этого прогона выглядит следующим образом:
tick
tick
tick
tict
tick
Это все хорошо, если вам нужно всего лишь одно действие. Что если вы хотите выполнить несколько действий и / или динамически добавить или вычесть ряд действий? Мы можем улучшить наш предыдущий класс SimpleTimer для динамической регистрации и отмены регистрации обработчиков, используя преимущества двух функций JavaFX: последовательности и указатели функций .
Наш новый класс обеспечивает большую гибкость:
- Он определяет переменную экземпляра, называемую длительность , которая позволяет пользователю указать разрешение тактового импульса при создании объекта.
- Он определяет две дополнительные открытые функции с именами registerHandler () и unRegisterHandler (), которые принимают указатель функции (обработчик) в качестве аргумента. После регистрации обработчика функция будет включена в список обработчиков, которые будут выполняться каждый раз, когда истекает указанная продолжительность.
- Обработчик регистрируется путем вставки аргумента указателя функции во внутреннюю последовательность указателей функций, называемых обработчиками [] .
- Обработчик аналогичным образом отменяется путем удаления аргумента указателя на функцию из последовательности handlers [] .
- Переменная экземпляра действия, которая является частью экземпляра KeyFrame , теперь вызывает внутреннюю функцию runHandlers () . runHandlers () последовательно выполняет функции, найденные в последовательности handlers [] .
Вот новый класс:
import javafx.animation.*;
public class Timer {
/**
* User-definable: specifies the length of time for one cycle.
*/
public var duration = 100ms;
public def timeline = Timeline {
repeatCount: Timeline.INDEFINITE
interpolate: false
keyFrames: [
KeyFrame {
time: duration
action: runHandlers }
]
}
// Holds the list of handlers to run
protected var handlers: function() [];
/**
* Add the function, represented by the handler argument, to the list
* of handlers. These will run when the elapsed time, specified
* by the duration instance variable, expires.
*/
public function registerHandler(handler : function()) : Void {
for (func in handlers) {
if (handler == func) {
return; // handler already registered -- skip
}
}
insert handler into handlers;
}
/**
* Remove the function, represented by the handler argument, from
* the list of handlers.
*/
public function unRegisterHandler(handler : function()) : Void {
delete handler from handlers;
}
protected function runHandlers() : Void {
for (handler in handlers) {
handler();
}
}
}
Чтобы протестировать этот класс, мы добавим функцию run () на уровне сценария. Функция run () создает экземпляр Timer и регистрирует две функции-обработчика , mentmentTenthsRemaining () и processTicks () . Вот код:
function run() : Void {
var t = Timer {};
var tenthsRemaining = 100;
var decrementTenthsRemaining = function() : Void {
tenthsRemaining -= 1;
}
var processTick = function() : Void {
if (tenthsRemaining mod 10 == 0) {
println("seconds left: {tenthsRemaining / 10}");
}
if (tenthsRemaining == 0) {
t.timeline.stop();
}
};
t.registerHandler(decrementTenthsRemaining);
t.registerHandler(processTick);
t.timeline.play();
}
И это результат бега:
seconds left: 9
seconds left: 8
seconds left: 7
seconds left: 6
seconds left: 5
seconds left: 4
seconds left: 3
seconds left: 2
seconds left: 1
seconds left: 0
Бесстыдное продвижение: будьте в курсе последнего статуса нашей новой книги JavaFX под названием JavaFX: разработка многофункциональных интернет-приложений на jfxbook.com .