簡體   English   中英

Java Timer程序-Rubix多維數據集

[英]Java Timer Program - rubix cube

我正在嘗試為我的朋友制作一個rubix立方體計時器。 要啟動計時器,請按住空格鍵,然后放開它。 不過,我遇到了一個問題,當我按住空格鍵時,計時器將在任何時間啟動。 我希望能夠將其重置為0,但是每當我嘗試執行此操作時,一切都會出現故障。 誰能告訴我如何修復它,或者如何以更有效的方式做到這一點? 謝謝!

package dev.suns.rubix_timer;

import java.awt.Color;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Timer;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

public class RubixTimerMain extends JFrame {

private JPanel contentPane;
private JLabel labelTimer;
private Timer timer;

public RubixTimerMain() {
    createWindow();
}

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

private void createWindow() {

    // setUndecorated(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(Toolkit.getDefaultToolkit().getScreenSize());
    setLocationRelativeTo(null);
    setExtendedState(JFrame.MAXIMIZED_BOTH);
    contentPane = new JPanel();

    contentPane.setBackground(new Color(201, 77, 83));
    contentPane.setLayout(null);
    setContentPane(contentPane);

    addKeyListener(new KeyAdapter() {
        @Override
        public void keyReleased(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                startTimer();
            }
        }
    });

    JLabel lblMinimize = new JLabel("-");
    lblMinimize.setBounds(1835, -20, 16, 95);
    lblMinimize.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
            setState(JFrame.ICONIFIED);
        }

        @Override
        public void mouseEntered(MouseEvent e) {
            lblMinimize.setForeground(Color.BLACK);
        }

        @Override
        public void mouseExited(MouseEvent e) {
            lblMinimize.setForeground(Color.WHITE);
        }
    });
    lblMinimize.setForeground(Color.WHITE);
    lblMinimize.setFont(new Font("Segoe UI", Font.PLAIN, 40));
    contentPane.add(lblMinimize);

    JLabel lblX = new JLabel("X");
    lblX.setBounds(1873, 0, 24, 54);
    lblX.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
            System.exit(0);
        }

        @Override
        public void mouseEntered(MouseEvent e) {
            lblX.setForeground(Color.BLACK);
        }

        @Override
        public void mouseExited(MouseEvent e) {
            lblX.setForeground(Color.WHITE);
        }
    });

    lblX.setFont(new Font("Segoe UI", Font.PLAIN, 40));
    lblX.setHorizontalAlignment(SwingConstants.CENTER);
    lblX.setForeground(Color.WHITE);
    contentPane.add(lblX);

    labelTimer = new JLabel("0.0.0");
    labelTimer.setHorizontalAlignment(SwingConstants.CENTER);
    labelTimer.setFont(new Font("DINPro-Bold", Font.PLAIN, 200));
    labelTimer.setForeground(Color.WHITE);
    labelTimer.setBounds(371, 134, 1418, 653);
    contentPane.add(labelTimer);
    setVisible(true);
}

這是我的計時器代碼。 我試圖在幾個不同的地方將cal重置為0,但無法正常工作。

private void startTimer() {
    new Thread()
    {
        public void run()
        {
            while(true)
            {
            Calendar cal = new GregorianCalendar();
            int minutes = cal.get(Calendar.MINUTE);
            int seconds = cal.get(Calendar.SECOND);
            int milliseconds = cal.get(Calendar.MILLISECOND);
            labelTimer.setText(minutes + "." + seconds + "." + milliseconds);
            }
        }
    }.start();
}

}

一個問題可能是您沒有與EDT(事件調度線程)上的labelTimer進行交互。

在Swing中,與UI對象的所有交互都必須在此線程上進行。

如果您確保對setText的調用發生在SwingUtilities#invokeLater的調用內時會發生什么: https : SwingUtilities#invokeLater .Runnable)

為了能夠停止計時器線程,您需要使用某種方法在主線程和計時器線程之間進行通信。 RubixTimerMain類的同步成員變量可以做到這一點:

private Boolean isStopped = new Boolean(true);

然后,您可以添加兩種方法。 一個通過設置變量來停止計時器,另一個通過檢查變量的當前狀態來進行。

private void stopTimer(){
    synchronized(isStopped){
        isStopped = true;
    }
}

private boolean isTimerRunning(){
    boolean result = false;
    synchronized(isStopped){
        result = !isStopped;
    }
    return result;
}

您將需要像這樣更改空格鍵(在createWindow中)的偵聽器事件,以使其開始和停止計時:

addKeyListener(new KeyAdapter() {
    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            if (isTimerRunning()){
                stopTimer();
            } else {
                startTimer();
            }
        }
    }
});

最后,您需要調整線程函數,以便僅在stopped狀態變量為false時才運行線程函數。 請注意,它使用isTimerRunning方法,而不是直接訪問該變量。 通過首先將GregorianCalendar的值轉換為毫秒,然后從當前時間中減去記錄的開始時間,也可以解決顯示錯誤時間的錯誤。

private void startTimer() {
    new Thread()
    {
        public void run()
        {
            long timeStart = new GregorianCalendar().getTimeInMillis();
            synchronized(isStopped){
                isStopped = false;
            }

            while(isTimerRunning())
            {
                long timeNow = new GregorianCalendar().getTimeInMillis() - timeStart;
                long milliseconds = (timeNow % 1000);
                timeNow = (long) Math.floor(timeNow * 0.001f);
                long seconds = (timeNow % 60);
                timeNow = (long)Math.floor((float)timeNow / 60f);
                long minutes = timeNow;

                labelTimer.setText(minutes + "." + seconds + "." + milliseconds);
            }
        }
    }.start();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM