Статьи

Регистрация нескольких действий (или обработчиков) в JavaFX

Разработчики 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 .

С http://blogs.sun.com/jtc