0

我这里有一些代码可以像我想要的那样工作。它只是以秒为单位倒计时到我在代码中确定的特定日期。我正在使用Thread.currentThread().sleep(1000);当前时间更新 JLabel,直到日期。问题是 JLabel 不会像预期的那样每秒刷新一次。有时它每 2 秒更新一次,有时它需要整整 10 秒才能更新。我相信这与我如何调用我的方法有关,但我不太确定如何使它更有效率。

这是调用该方法以更新 Thread 内的 JLabel 的 main 方法:

public static void main(String args[])
{
    initUI();
    try
    {
        while(true)
        {
            Thread.currentThread().sleep(1000);
            getTime();
        }
    } catch(Exception e){System.out.println("An error has occured...");}
}

这里是main方法调用的方法调用的方法。此方法最终将秒剩余变量发送到第三种方法:

public static void getTime()
{
    Calendar c = Calendar.getInstance();
    // Gets abstract current time in ms
    long now = c.getTimeInMillis();

    c.set(Calendar.HOUR_OF_DAY, 0);
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);
    c.set(Calendar.MILLISECOND, 0);

    // Gets current time in ms
    long msPassed = now - c.getTimeInMillis();
    // There are 86,400,000 milliseconds in a day
    // Gets the seconds remaining in the day
    long secRemaining = (86400000 - msPassed) / 1000;

    //-----------------------------------------------------// 
    // Creates a new calendar for today
    Calendar cal = Calendar.getInstance();
    int currentDayOfYear = cal.get(Calendar.DAY_OF_YEAR);

    // Creates a calendar for November 20th, 2016
    Calendar aniv = new GregorianCalendar(2016,10,20);
    aniv.set(Calendar.MONTH, 10);
    aniv.set(Calendar.DAY_OF_MONTH, 20);
    int aniversary = aniv.get(Calendar.DAY_OF_YEAR);

    remaining = ((aniversary - currentDayOfYear) * 24 * 60 * 60) + secRemaining;
    setTextOnScreen(remaining);
}

最后,这是重写 JLabel 的方法(由上面的方法调用):

public static void setTextOnScreen(long num)
{
    text.setForeground(Color.GREEN);
    text.setLocation((int)width/2 - 150, 50);
    text.setFont(new Font("Monospaced", Font.BOLD, 48));
    text.setSize(300,150);

    text.setText("" + num);
    panel.add(text);
}

我不包括其余代码,因为它应该是无关紧要的,但是如果您也想看到它,请告诉我。

4

3 回答 3

3

两个问题:

  1. 您正在从后台线程调用text.setSomething()panel.add这不是您应该使用的 UI 线程。尝试使用SwingUtils.invokeLater()orSwingUtils.invokeAndWait()并调用触及那里的 UI 的代码。

  2. 在调用您的set方法后,您还应该调用text.invalidate()以发出 UI 组件需要更新的信号……否则 UI 线程不会注意到该组件需要重新测量和重新绘制。

于 2016-10-04T16:43:59.357 回答
1

您应该只更新事件循环中的 GUI 组件。如果您尝试在其他线程中更新它们,您可能会得到不可预知的结果。我建议使用摇摆定时器来执行在 GUI 事件循环中运行的周期性任务。

于 2016-10-04T16:43:50.673 回答
0

你可以尝试使用Timer

它有一个方法#scheduleAtFixedRate可以接受要执行的任务,开始执行它的时间,以及它应该运行任务的时间间隔。

将您的计划操作包装到一个类中,该类可扩展TimerTask以与此方法一起使用。

这是 Java 7 中此类的 javadocs https://docs.oracle.com/javase/7/docs/api/java/util/Timer.html

于 2016-10-04T16:48:12.700 回答