0

I have a Timer that works like this:

public void startTourButton(ActionEvent event) {
new Timer ().schedule(
        new TimerTask () {

            public void run(){          
                     System.out.println("Going to do something here");
            }

        }, 0, 5000);

 }

I am trying to cancel the Timerfrom a different event here:

public void stopTourButton(ActionEvent event) {
Timer.cancel();
   }

I get an error

Cannot make a static reference to the non-static method cancel() from the type Timer

How can I fix this?

Display Name
  • 405
  • 6
  • 26
  • Create a variable `Timer myTimer = new Timer()`, then call the `cancel` method on that timer: `myTimer.cancel();` – Randy Aug 16 '16 at 13:08
  • 2
    You need to _assign_ `new Timer` _instance_ to a _variable_. You then then need use _that_ instance and call `cancel()` on it. In short, you need to read about instance vs `static` methods and what the `new` keyword does. – Boris the Spider Aug 16 '16 at 13:08
  • Note that as you seem to be using Swing, you likely need to use [other `Timer`](https://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html) if you want to interact with Swing components. – Boris the Spider Aug 16 '16 at 13:28
  • I was using swing but i have re-written my application in JavaFX now. Out of interest what makes it appear that i am using swing? – Display Name Aug 16 '16 at 13:34
  • [`ActionEvent`](https://docs.oracle.com/javase/7/docs/api/java/awt/event/ActionEvent.html). But now that you mention it, it could also be [`ActionEvent`](https://docs.oracle.com/javase/8/javafx/api/javafx/event/ActionEvent.html). In the case of JavaFX, consider a [different approach](https://stackoverflow.com/questions/9966136/javafx-periodic-background-task). – Boris the Spider Aug 16 '16 at 13:35
  • Ah ok `javafx.event.ActionEvent` – Display Name Aug 16 '16 at 13:38
  • I also looked at `javafx.concurrent` `Task`. Is there anywhere i can go to compare the Pros and Cons or each method? I stuck with `Timer` as thats how it was in my old Swing application. – Display Name Aug 16 '16 at 13:43
  • The main issue is that you should **never** access UI components from any thread other than the UI thread. The two approaches I linked execute the given task on the UI thread; any other approach (including your `Timer`) execute on _another_ thread. This can cause random and unexpected issues as it violates the concurrency requirements of these frameworks. – Boris the Spider Aug 16 '16 at 13:46

2 Answers2

3

Save the timer as a class member so you can cancel it later

class YourClass {

    Timer timer;

    public void startTourButton(ActionEvent event) {
        if (timer == null) {
            timer = new Timer();
        }
        timer.schedule(
            new TimerTask () {    
                public void run(){          
                    System.out.println("Going to do something here");
                }   
            }, 0, 5000);
        }
    }

    public void stopTourButton(ActionEvent event) {
        timer.cancel();
        timer = null;
    }
}
Boris the Spider
  • 59,842
  • 6
  • 106
  • 166
ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
1

First declare a variable, then instantiate it, then use that as reference:

Timer myTimer;    

public void startTourButton(ActionEvent event) {
     myTimer = new Timer ().schedule(
         new TimerTask () {

              public void run(){          
                   System.out.println("Going to do something here");
              }

         }, 0, 5000);
 }

public void stopTourButton(ActionEvent event) {
    myTimer.cancel();
}
Randy
  • 9,419
  • 5
  • 39
  • 56