0

ここには、希望どおりに機能するコードが少しあります。コードで決定した特定の日付までの秒単位のカウントダウンだけです。Thread.currentThread().sleep(1000);日付までの残りの現在の時刻で JLabel を更新するために使用しています。問題は、JLabel が想定どおりに毎秒更新されないことです。2 秒ごとに更新される場合もあれば、更新に 10 秒かかる場合もあります。メソッドの呼び出し方法に関係があると思いますが、より効率的にする方法がよくわかりません。

Thread 内の JLabel を更新するメソッドを呼び出すメイン メソッドは次のとおりです。

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 メソッドによって呼び出されるメソッドによって呼び出されるメソッドです。このメソッドは最終的に残りの秒数変数を 3 番目のメソッドに送信します。

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

2 つの問題:

  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 イベント ループで定期的なタスクを実行するには、swing Timer を使用することをお勧めします。

于 2016-10-04T16:43:50.673 に答える
0

あなたは使用してみることができますTimer

#scheduleAtFixedRate実行するタスク、実行を開始する時間、およびタスクを実行する間隔を受け入れるメソッドがあります。

スケジュールされたアクションを、TimerTaskこのメソッドで使用できるように拡張するクラスにラップします。

Java 7 のこのクラスの javadoc は次のとおりですhttps://docs.oracle.com/javase/7/docs/api/java/util/Timer.html

于 2016-10-04T16:48:12.700 に答える