0

first post on here so please be gentle...

I am fairly new to JavaFX and have successfully set up quite a complicated GUI which reads a csv file in order to populate certain components within the GUI.

I'm using a timeline in the intialize function for the GUI Controller which fires a button every second on the GUI - the button calls a function which reads the csv file form disc.. all this is working fine.

When I quit/exit the GUI stage I want to stop the timeline from running... but can't seem to manage this...

I have a small function which loads the Stage and also has an event listener to detect when it's closed... what I'd like to do is be able to close the timeline at the commented line... in the try/catch section.

public void Show_MACD() throws IOException
{
Parent root = FXMLLoader.load(getClass().getResource("MACD Turbo.fxml"));   
    Scene scene = new Scene(root);
    Stage stage = new Stage(); 
    stage.setScene(scene);
    stage.setTitle("FX AlgoTrader MACD Turbo");
    stage.show();   
    JavaFX.thisstage=stage;
    stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
          @Override
          public void handle(WindowEvent we) {
          LoginController sp=new LoginController();
              try {
                  //how can I stop the timeline here? 
                  sp.Show_Products(); // this loads up another stage - a menu in fact
              } catch (IOException ex) {
                  Logger.getLogger(MACD_Controller.class.getName()).log(Level.SEVERE, null, ex);
              }
          }
      }); 
//System.out.println("running");
}

Here's the section in the initialize function where the timeline is set up and run from....(this is in the same class as the controller called 'MACD_Controller' which is also home to the 'Show_MACD' function which has a event listener for window close events.. that's kind of where I would like to stop the timeline ie when the window closes)

@Override
public void initialize(URL url, ResourceBundle rb) {

final Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) 
             {
             Refresh.fire(); //Refresh is a button on the GUI which calls the csv file
             }
        }));
    timeline.setCycleCount(Timeline.INDEFINITE);
    timeline.play();
}

I know I need to somehow create a reference to 'timeline' so that I can use the 'timeline.stop' function... I've tried all sorts of mumbo jumbo but I keep getting an NPE.

I know this is super basic but I'm a bit stuck..

Cheers Crispin

  • Is the `TimeLine` inside the `LoginController` ? – ItachiUchiha Aug 14 '14 at 12:22
  • Hi, no - the timeline is in the initialization function within the controller for the GUI - it's called MACD_Controller - the code snippet is above. So essentially the timeline is in the same class - I tried to use 'timeline.stop()' from the function called 'Show_MACD'(I used it in the commented section where is says 'how can I stop the timeline here?') but I got an NPE. So even after the stage is closed using the X in the top right hand corner of the stage - the timeline still runs in the background which is obviously no good in terms of CPU optimization etc. Thanks for replying btw. – Crispin Scruby Aug 14 '14 at 14:49
  • Perhaps a pattern from [passing parameters and fxml](http://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml) will help you here. – jewelsea Aug 14 '14 at 17:13
  • In the code you posted, `timeline` is a local variable in the `initialze` function. Are you sure you assigned it to a field of the controller class? – Tomas Mikula Aug 14 '14 at 17:57
  • Hi thanks for your comments. I read the passing parameters and fxml but the timeline is indeed a local variable and not part of the @FXML variables defined at the beginning of the class. Indeed the initialize function posted above does declare 'timeline' as local but I also tried declaring 'timeline' as a public variable at the beginning of the class... so I added 'public Timeline timeline' and then removed the 'final' attribute where the timeline is declared in the code above.. still get an NPE trying to declare 'timeline' globally. I can post the whole class but it's 800 lines :( – Crispin Scruby Aug 14 '14 at 19:13
  • Update: I declared a new global variable called 'tline' using 'public Timeline tline;' then I added a line of code after 'timeline.play' which is 'tline=timeline;'... then I added a line of code into the Window event handler ie the try statement which is 'tline.stop()'.. still get the NPE... clearly I don't understand something pretty major here.... rather embarassing as I've been coding (badly) for quite a long time. – Crispin Scruby Aug 14 '14 at 19:21
  • When is `show_MACD(...)` called? – James_D Aug 14 '14 at 19:34
  • Hi James, thanks for your reply - Show_MACD is called from another controller called 'ProductsController' - the call is a function with a couple of lines which are:- 'MACD Controller MACD=new MACD_Controller(); and then MACD.Show_MACD(); the previous stage is closed before 'Show_MACD' is called.... very interesting question... is the call sequence something to do with the issue do you think? – Crispin Scruby Aug 14 '14 at 19:42
  • You should really never instantiate controllers. The `FXMLLoader` instantiates a controller and injects values into it. If you instantiate your own, it's not connected to any view. You almost certainly need to read the link @jewelsea posted above and use techniques from there. – James_D Aug 15 '14 at 01:52
  • Thanks for your comments guys. I've read the Jewelsea link but I'm afraid I just don't get it... I didn't realize I was in some way instantiating my own controller - I just thought the Show_MACD code snippet which sets up the stage was the 'de facto' way to open a JavaFX window... I'm coming from Swing so this is pretty alien.. the odd thing is the application I've written works fine - I've got 4 fxml based interfaces designed in Scene Builder which are all stitched together and working well. I think my solution is to drop the timeline and use a refresh button. Dirty but it won't create NPEs! – Crispin Scruby Aug 15 '14 at 06:28
  • SOLVED FOLKS...I moved the timeline declaration out of the initialization function and declared it in the FXML variables at the top. Then I moved the timeline.setcycles... and timeline.play() lines form the initialization function into the Show_MACD function...after stage.show()- the timeline.stop() command now works in the Window Event handler inside the Show_MACD function. No more NPEs and the timeline stops. No need for any complicated mumbo jumbo declaring controllers and other instantiate whatnot. Long slog but I got there in the end. – Crispin Scruby Aug 16 '14 at 17:02

0 Answers0