手动调用javax.swing.Timer的actionPerformed

时间:2018-06-26 18:09:54

标签: java swing timer actionlistener

以下计时器工作正常。

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

我想做的是手动调用actionPerformed()。我该如何实现?


这个问题对于读者来说似乎不清楚,我将尽力解释。

计时器每小时进行一些处理。我想在不干扰计时器过程的情况下随时执行此操作。

3 个答案:

答案 0 :(得分:1)

在变量中的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 */);

答案 1 :(得分:1)

简短答案...

一个更简单(设计更好)的解决方案将代替...

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

您然后说:

  

我想做的是在计时器的ActionListener中手动调用actionPerformed()方法。我该如何实现?

建议您尝试做类似...

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));
    }
}

答案 2 :(得分:0)

使用getActionListeners()

  

返回在此计时器上注册的所有动作侦听器的数组。
  返回值:   所有计时器的ActionListener,如果当前未注册任何动作侦听器,则为空数组。

  ~Java doc~

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

如果没有ArrayIndexOutOfBoundsException注册到计时器,则会抛出ActionListener。因此,最好在使用前检查数组的长度。