Java - 定时器代码应该放在文件的什么地方?

Java - Where to put Timer code in my file?

假设我有以下用于与时钟一起工作的 GUI 的框架(我可能导入了比我需要的更多的东西;我是从一个更大的文件创建的):

import java.util.*;
import javax.swing.*;
import java.awt.*;
import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.Timer;

public class clock extends JFrame implements ActionListener
{
    Container c;
    JLabel year, month, date, hour, minute, second;

    public clock(Calendar cal)
    {
        //set up GUI; initialize and add all 6 JLabels
    }

    public static void main(String args[])
    {
        Calendar current = Calendar.getInstance();
        clock c = new clock(current);
    }
}

我想让时钟每秒更新一次。据我了解,这是 [至少部分] 我需要的代码:

ActionListener listener = new ActionListener()
{
    public void actionPerformed(ActionEvent event)
    {
        cal.
        year.setText("year: " +cal.get(Calendar.YEAR));
        month.setText("month: " +cal.get(Calendar.MONTH));
        date.setText("date: " +cal.get(Calendar.DATE));
        hour.setText("hour: " +cal.get(Calendar.HOUR));
        minute.setText("minute: " +cal.get(Calendar.MINUTE));
        second.setText("second: " +cal.get(Calendar.SECOND));
    }
};

Timer timer = new Timer(500, listener);
timer.setInitialDelay(0);
timer.start();

第二个代码块是在构造函数中,还是在构造函数和 main 之外?我两种都试过了,每种都出现了不同的错误。我读过一些关于需要 @Override 才能工作的内容,但我对此并不熟悉。此外,这是我的计时器工作所需的全部代码,还是还有更多代码(如果有,是什么)?我在这里看到了一个时钟的例子,它基本上做了我想做的事情,但它使用了我从未学过的各种其他东西(runnabletry, catch, 等),所以如果可能的话,我想用我所知道的来做。

我意识到我可能需要将我的 Calendar 对象设置为全局对象以便 ActionListener 在该代码块超出构造函数时访问它。

编辑:我更新了 actionPerformed 方法以包括对日历的更新。我还提供了我遇到的错误(请注意,行号不正确,因为我的实际构造函数包含的行数比此处的骨架多得多):

当我将第二个代码块放入构造函数时:

clock.java:10: error: clock is not abstract and does not override abstract method actionPerformed(ActionEvent) in ActionListener
public class clock extends JFrame implements ActionListener
       ^

当我将第二个代码块放在构造函数之外时:

clock.java:59: error: <identifier> expected
    timer.setInitialDelay(0);
                         ^
clock.java:59: error: illegal start of type
    timer.setInitialDelay(0);
                          ^
clock.java:60: error: <identifier> expected
    timer.start();
               ^

EDIT2:这是我从 MadProgrammer 的解决方案中得到的例外情况:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at Clock.actionPerformed(clock.java:18)
    at javax.swing.Timer.fireActionPerformed(Timer.java:313)
    at javax.swing.Timer$DoPostEvent.run(Timer.java:245)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
    at java.awt.EventQueue.access0(EventQueue.java:97)
    at java.awt.EventQueue.run(EventQueue.java:709)
    at java.awt.EventQueue.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

EDIT3:来自@MadProgrammer 的更新解决方案的错误:

Clock.java:33: error: cannot find symbol
        setLayout(new FlowLayout());  
                  ^
  symbol:   class FlowLayout
  location: class Clock

这个...

clock.java:59: error: <identifier> expected
    timer.setInitialDelay(0);
                         ^
clock.java:59: error: illegal start of type
    timer.setInitialDelay(0);
                          ^
clock.java:60: error: <identifier> expected
    timer.start();

表示您正在导入错误 Timer。 Java有两个,java.util.Timerjavax.swing.Timer,就是你要的

通常,出于这个原因我不使用通配符导入,但是我的 IDE 的自动导入功能也使用绝对导入。

但你也可以使用

import javax.swing.Timer;

或使用绝对声明,如...

javax.swing.Timer timer = new javax.swing.Timer(500, listener);

取决于您的需要(使用 java.util.Datejava.sql.Date 时,您通常会在这里结束:P)

这个...

clock.java:10: error: clock is not abstract and does not override abstract method actionPerformed(ActionEvent) in ActionListener
public class clock extends JFrame implements ActionListener

表示您尚未实现 ActionListener 接口协定的要求。在您的情况下,我认为您实际上并不需要它,因为您正在内部制作自己的 ActionListener

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Clock extends JFrame {

    JLabel year, month, date, hour, minute, second;

    public Clock(Calendar cal) {
        ActionListener listener = new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                cal.setTime(new Date());
                updateTime(cal);
            }
        };

        year = new JLabel();
        month = new JLabel();
        date = new JLabel();
        hour = new JLabel();
        minute = new JLabel();
        second = new JLabel();

        setLayout(new FlowLayout());

        add(year);
        add(month);
        add(date);
        add(hour);
        add(minute);
        add(second);

        updateTime(cal);

        javax.swing.Timer timer = new javax.swing.Timer(500, listener);
        timer.setInitialDelay(0);
        timer.start();
    }

    protected void updateTime(Calendar cal) {
        year.setText("year: " + cal.get(Calendar.YEAR));
        month.setText("month: " + cal.get(Calendar.MONTH));
        date.setText("date: " + cal.get(Calendar.DATE));
        hour.setText("hour: " + cal.get(Calendar.HOUR));
        minute.setText("minute: " + cal.get(Calendar.MINUTE));
        second.setText("second: " + cal.get(Calendar.SECOND));
    }

    public static void main(String args[]) {
        new Clock();
    }

    public Clock() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                Calendar current = Calendar.getInstance();
                Clock frame = new Clock(current);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}