可以不使用定时器

Possible not to use timer

大家好,我想问一下,是否可以不在 Java netbeans 中使用计时器来在我的 JLabel 上显示我的变量 "counter" 使用 while 循环的所有值。这是我的示例代码。

int counter = 0;

while (counter < 10)  {
    lblDisplay.setText("Completed " + Integer.toString(counter));
    try {
        Thread.sleep(1000);
        lblDisplay.setText("Completed " + Integer.toString(counter));
    } catch (InterruptedException ex) {
        Logger.getLogger(Increment.class.getName()).log(Level.SEVERE, null, ex);
    }
    counter++;
}

在使用 system.out.println 时显示了它,但在我的标签中没有显示。

是的,可以避免使用 Swing Timer 来实现这一点,但是如果您这样做了:

  • 您必须确保循环和 Thread.sleep(...) 在 Swing 事件线程之外的后台线程中 运行。如果您不这样做,您将冻结事件线程,从而冻结您的 GUI 并使其变得无用。
  • 然后您必须确保当您仅从后台线程进行 Swing 调用时,您会煞费苦心地将这些调用排队到 Swing 事件分派线程中。如果您不这样做,您将 运行 有导致偶尔很难调试线程错误的风险。

由于涉及的额外工作和出错的风险,您会发现仅使用 Swing 计时器 更简单、更安全。例如,您发布的代码看起来很有可能使整个 GUI/application 进入睡眠状态,因为它同时具有 while 循环和 Thread.sleep(...) 调用而不考虑线程。

例如,如果没有计时器,您的代码可能类似于(注意:代码未编译或测试):

new Thread(new Runnable() {
    public void run() {
        int counter = 0;

        while (counter < 10)  {
            lblDisplay.setText("Completed " + Integer.toString(counter));
            try {
                Thread.sleep(1000);
                final int finalCounter = counter;
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        lblDisplay.setText("Completed " + finalCounter);
                    }
                });
            } catch (InterruptedException ex) {
                Logger.getLogger(Increment.class.getName()).log(Level.SEVERE, null, ex);
            }
            counter++;
        }    
    }
}).start();

这比我喜欢的要复杂一些,而 Swing Timer 可能看起来像:

int delay = 1000;
new Timer(delay, new ActionListener() {
    private int count = 0;

    @Override
    public void actionPerformed(ActionEvent e) {
        if (count < 10) {
            lblDisplay.setText("Completed " + counter);
        } else {
            ((Timer) e.getSource()).stop(); // stop the Timer
        }
        counter++;
    }
}).start();

比之前的更简单、更安全。