Search code examples
javaswingtimerrestart

Restart timer if mouse is moving


I want to restart my program, if the mouse is not moving for 2 minutes. I tried to set a timer and restart it everytime the mouse moves, but nothing worked so far. Is there someone who can help me with this problem?

frame.addMouseMotionListener(new MouseAdapter() {
        public void mouseMoved(MouseEvent e) {
            timer.cancel();
            timer.purge();
            timer = new Timer();
            timer.schedule(new TimerTask() {
                public void run() {
                    frame.dispose();
                    try {
                        MyWeb neu = new MyWeb();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }, 5000);
        }
    });

Solution

  • Swing Timer

    You want to use a Swing Timer (javax.swing.Timer) rather than a common Timer (java.util.Timer). See the Oracle Tutorial.

    Automatic threading

    The Swing Timer is special in that it automatically handles the timer ticking on a background, and when eventually fired, the timer automatically handles running your task on the main GUI thread of Swing. So you need not concern yourself with the details of threading.

    It is very very very important to never access your GUI widgets on a background thread. You may get away with it, or you may drastically disrupt your app. The Swing Timer was invented to handle the chore of counting down on a background thread yet switching back to the GUI thread to run the task’s code.

    TimerTask to shutdown your app

    Write your work to be done on firing of the timer as a java.util.TimerTask.

    Algorithm

    A Swing Timer can fire once or repeatedly. You want to fire once. Upon firing, shutdown your app.

    Set up the timer when your app launches. Store a reference to that timer on your app. Configure the timer for your desired 2 minute countdown. Every time the mouse moves, call restart on the Swing Timer. So the 2 minute countdown keeps getting set back to 2 minutes. Your app may run for hours, with the 2 minute timer getting reset over and over and over again.

    launch timer (2 mins) →  on mouse move  ↓ → timer fires → shutdown app
                          ↑ ← restart timer ←
    

    Shutdown versus restart

    When the countdown expires, I am not sure if you meant to shutdown, relaunch, or merely re-initialize some state within your app. If the last one (re-init state), set your timer to fire repeatedly rather than once. The rest of the approach remains the same.

    Possible optimization

    I do not know for certain, but I suspect resetting the timer on every mouse movement might be overkill, and might cost a bit of performance. Profile to see for yourself. If there does seem to be significant cost, just track the last time you reset the timer. To track that moment, use an Instant object. Call Instant.now() to capture the current moment on every mouse movement. Calculate the elapsed time with Duration.between. When the duration exceeds an arbitrary limit, say 5 seconds, restart the Swing timer, and update the “when timer last restarted” Instant you store. Instant.now captures the current moment in a resolution of milliseconds in Java 8 and a resolution of microseconds in Java 9 and later. (An Instant actually holds nanoseconds, but conventional computer clocks cannot run that fine.)