Вручную вызвать actionPerformed из javax.swing.Timer - PullRequest
0 голосов
/ 26 июня 2018

Следующий таймер работает отлично.

private static final Timer TICK_HOUR = new Timer(3600000, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // ...
    }
});

То, что я хочу сделать, это вызвать actionPerformed() вручную. Как мне этого добиться?


Читателям вопрос кажется неясным, я постараюсь объяснить подробнее.

Таймер выполняет некоторые процессы каждый час. Я хочу делать это в любое время, не вмешиваясь в процесс таймера.

Ответы [ 3 ]

0 голосов
/ 26 июня 2018

Внутри static-initializer -блок-хранилища ActionListener в переменной вместо передачи ее непосредственно в Timer:

private static final Timer TICK_HOUR;

static{
    ActionListener listener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            // ...
        }
    };

    TICK_HOUR =  = new Timer(3600000, listener);

    listener.actionPerformed(/* someEvent */);
}

Вы можете также сохранить переменную listener как статическую переменную уровня класса, а затем вызвать ее в другом месте из своего кода:

private static final ActionListener LISTENER = new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {
        // ...
    }
};

private static final Timer TICK_HOUR = new Timer(3600000, LISTENER);

А потом где-нибудь в вашем коде

LISTENER.actionPerformed(/* someEvent */);
0 голосов
/ 26 июня 2018

Краткий ответ ...

Гораздо более простым (и лучше разработанным) решением было бы вместо ...

private static final Timer TICK_HOUR = new Timer(3600000, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("OK");
    }
});

Вы должны выполнить работу, которую ActionListener выполняет ...

private static final Timer TICK_HOUR = new Timer(3600000, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        doReallyImportantWorkEveryHour();
    }
});

затем вы убираете Timer из уравнения, и вы можете позвонить doReallyImportantWorkEveryHour, когда захотите, и решить фундаментальную проблему

Длинный ответ

Итак, начнем с ...

private static final Timer TICK_HOUR = new Timer(3600000, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("OK");
    }
});

Создание Timer таким способом автоматически регистрирует ActionListener с помощью Timer.

Затем вы заявляете:

Я хочу вызвать метод actionPerformed () внутри ActionListener таймера вручную. Как мне этого добиться?

Что говорит о том, что вы хотите попробовать и сделать что-то вроде ...

private static final Timer TICK_HOUR = new Timer(3600000, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        TICK_HOUR.getActionListeners()[0].actionPerformed(null);
    }
});

Это может вызвать NullPointerException, но, что более важно, это окажет неблагоприятное влияние на производительность системы, так как ActionListener не будет знать, что оно не должно непрерывно все само по себе - в основном и бесконечный цикл.

Если, однако, вы хотели, преждевременно, запустить Timer s ActionListener s (вне любых зарегистрированных слушателей)

Тогда да, вы могли бы использовать ...

ActionEvent evt = new ActionEvent(
                TICK_HOUR, 
                0, 
                TICK_HOUR.getActionCommand(), 
                System.currentTimeMillis(),
                0);
for (ActionListener listener : TICK_HOUR.getActionListeners()) {
    listener.actionPerformed(evt);
}

но убедитесь, что вы звоните им из контекста EDT, так как это одна из гарантий, которую Timer дает.

"Более простым" решением может быть просто использование функциональности, которая уже предоставляется самим Timer ...

public class ManuallyTimer extends Timer {

    public ManuallyTimer(int delay, ActionListener listener) {
        super(delay, listener);
    }

    public void tigger() {
        ActionEvent evt = new ActionEvent(TICK_HOUR, 0, TICK_HOUR.getActionCommand());
        fireActionPerformed(new ActionEvent(this, 0, getActionCommand(),
                        System.currentTimeMillis(),
                        0));
    }
}
0 голосов
/ 26 июня 2018

Использование getActionListeners().

Возвращает массив всех прослушивателей действий, зарегистрированных в этом таймере.
Возвращает: все ActionListeners таймера или пустой массив, если в данный момент не зарегистрировано прослушивателей действий.

~ Java документ ~

TICK_HOUR.getActionListeners()[0].actionPerformed(null);

Это выдаст ArrayIndexOutOfBoundsException, если для таймера не зарегистрировано ActionListener. Так что лучше проверяйте длину массива перед использованием.

...