Java计时器程序 - rubix立方体

时间:2016-09-13 00:59:44

标签: java multithreading timer

我正在尝试为我的朋友制作一个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();
}

}

2 个答案:

答案 0 :(得分:0)

一个问题可能是您没有在EDT(事件调度线程)上与labelTimer进行交互。

在Swing中,与UI对象的所有交互都必须在此线程上进行。

如果您确保在setText SwingUtilities#invokeLater的调用中发生对 // alert($('#a').val()); // alert($('#b').val()); // alert($('#c').val()); // alert($('#d').val()); var x=0; $('#a1').click(function(){ $('#myTable1').append( '<tr><td><input class="form-control input-sm w3-input" id="aaa'+x+'" type="text"></td><td><input class="form-control input-sm w3-input" type="text" id="bbb'+x+'"></td><td><input class="form-control input-sm w3-input" id="ccc" type="text"></td><td><input class="form-control input-sm w3-input" id="ddd" type="text"></td></tr>' ); x=x+1; alert($('#aaa'+x).val()); alert($('#bbb'+x).val()); alert($('#ccc'+x).val()); alert($('#ddd'+x).val()); });的调用,会发生什么情况

答案 1 :(得分:0)

为了能够停止计时器线程,您需要在主线程和计时器线程之间进行一些通信。 RubixTimerMain类的synchronized成员变量可以这样做:

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();
            }
        }
    }
});

最后,您需要调整线程函数,使其仅在停止状态变量为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();
}