This is my revised code of Stopwatch:
package com.zm0617;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.event.*;
public class MultiThreadedStopwatchController implements StopwatchController,
StopwatchState {
private volatile static boolean isStarted;
public MultiThreadedStopwatchController() {
isStarted = false;
}
public void stop() {
isStarted = false;
}
public void start() {
isStarted = true;
}
public void toggle() {
if (isStarted) {
isStarted = false;
} else {
isStarted = true;
}
}
public boolean isStarted() {
return isStarted;
}
}
interface StopwatchState {
boolean isStarted();
}
interface StopwatchController {
void stop();
void start();
void toggle();
boolean isStarted();
}
class Clock implements Runnable {
private StopwatchState state;
static int hr = 0;
static int min = 0;
static int sec = 0;
static double milisec = 0;
static int rotation = 0;
static long time1 = 0;
static long time2 = 0;
public Clock(StopwatchState state) {
this.state = state;
}
@Override
public void run() {
while (true) {
time1 = System.currentTimeMillis();
while (state.isStarted()) {
if (!state.isStarted()) {
break;
}
if (rotation == 0) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
Thread.interrupted(); // interrupt state to false
break;
}
time2 = System.currentTimeMillis();
plus((int) time2 - (int) time1);
rotation++;
} else if (rotation == 1) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
Thread.interrupted(); // interrupt state to false
break;
}
time1 = System.currentTimeMillis();
plus((int) time1 - (int) time2);
rotation--;
}
}
if (Stopwatch.resets()) {
hr = 0;
min = 0;
sec = 0;
milisec = 0;
}
}
}
public static void plus(int i) {
milisec += i;
if (milisec >= 1000) {
milisec -= 1000;
sec++;
}
if (sec >= 60) {
sec -= 60;
min++;
}
if (min >= 60) {
min -= 60;
hr++;
}
}
public static String getHr() {
return toStringHMS(hr);
}
public static String getMin() {
return toStringHMS(min);
}
public static String getSec() {
return toStringHMS(sec);
}
public static String getMilisec() {
return toStringM(milisec);
}
public static String toStringHMS(Integer i) {
String s = i.toString();
if (s.length() == 1) {
s = "0" + s;
}
return s;
}
public static String toStringM(Double d) {
Integer i = (int) Math.round(d);
String s = i.toString();
if (s.length() == 1) {
s = "00" + s;
} else if (s.length() == 2) {
s = "0" + s;
}
return s;
}
}
class Stopwatch extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private static StopwatchController controller;
final static MultiThreadedStopwatchController stopwatchController =
new MultiThreadedStopwatchController();
static Clock clock = new Clock(stopwatchController);
static Thread t = new Thread(clock);
private JPanel contentPane;
private static JTextField hr;
private static JTextField min;
private static JTextField sec;
private static JLabel milisec;
private static JButton start;
static boolean breset = false;
static boolean frameDone = false;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Stopwatch frame = new Stopwatch(stopwatchController);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.start();
while (true) {
if (frameDone) {
if (controller.isStarted()) {
start.setText("Stop");
} else {
start.setText("Start");
}
hr.setText(Clock.getHr());
min.setText(Clock.getMin());
sec.setText(Clock.getSec());
milisec.setText(Clock.getMilisec());
}
System.out.print("");
}
}
/**
* Create the frame.
*/
public Stopwatch(final StopwatchController controller) {
Stopwatch.controller = controller;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 200, 110);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
hr = new JTextField();
hr.setEditable(false);
hr.setText("00");
contentPane.add(hr);
hr.setColumns(3);
JLabel colona = new JLabel(":");
contentPane.add(colona);
min = new JTextField();
min.setEditable(false);
min.setText("00");
contentPane.add(min);
min.setColumns(3);
JLabel colonb = new JLabel(":");
contentPane.add(colonb);
sec = new JTextField();
sec.setEditable(false);
sec.setText("00");
contentPane.add(sec);
sec.setColumns(3);
milisec = new JLabel("000");
milisec.setFont(new Font("Tahoma", Font.PLAIN, 8));
contentPane.add(milisec);
JButton reset = new JButton("Reset");
reset.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent arg0) {
if (!controller.isStarted()) {
breset = true;
}
}
});
contentPane.add(reset);
start = new JButton("Start");
start.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
controller.toggle();
}
});
contentPane.add(start);
frameDone = true;
}
public static boolean resets() {
if (breset) {
breset = false;
t.interrupt();
return true;
} else {
return false;
}
}
}