Swing and Thread: repaint
import java.awt.Color; import java.awt.FlowLayout; import java.awt.Font; import java.lang.reflect.InvocationTargetException; import java.text.DecimalFormat; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; public class DigitalTimer extends JLabel { private volatile String timeText; private Thread internalThread; private volatile boolean noStopRequested; public DigitalTimer() { setBorder(BorderFactory.createLineBorder(Color.black)); setHorizontalAlignment(SwingConstants.RIGHT); setFont(new Font("SansSerif", Font.BOLD, 16)); setText("00000.0"); // use to size component setMinimumSize(getPreferredSize()); setPreferredSize(getPreferredSize()); setSize(getPreferredSize()); timeText = "0.0"; setText(timeText); noStopRequested = true; Runnable r = new Runnable() { public void run() { try { runWork(); } catch (Exception x) { x.printStackTrace(); } } }; internalThread = new Thread(r, "DigitalTimer"); internalThread.start(); } private void runWork() { long startTime = System.currentTimeMillis(); int tenths = 0; long normalSleepTime = 100; long nextSleepTime = 100; DecimalFormat fmt = new DecimalFormat("0.0"); Runnable updateText = new Runnable() { public void run() { setText(timeText); } }; while (noStopRequested) { try { Thread.sleep(nextSleepTime); tenths++; long currTime = System.currentTimeMillis(); long elapsedTime = currTime - startTime; nextSleepTime = normalSleepTime + ((tenths * 100) - elapsedTime); if (nextSleepTime < 0) { nextSleepTime = 0; } timeText = fmt.format(elapsedTime / 1000.0); SwingUtilities.invokeAndWait(updateText); } catch (InterruptedException ix) { // stop running return; } catch (InvocationTargetException x) { x.printStackTrace(); } } } public void stopRequest() { noStopRequested = false; internalThread.interrupt(); } public boolean isAlive() { return internalThread.isAlive(); } public static void main(String[] args) { JFrame f = new JFrame(); f.getContentPane().setLayout(new FlowLayout()); f.getContentPane().add(new DigitalTimer()); f.setSize(250, 100); f.setVisible(true); } }