Javafx: Change scene in setOnAction


Question

I'm building a JavaFX application with multiple Scenes. I have a problem with scope of variable when changing scenes within setOnAction event. This is my code:

Stage myStage;

public Scene logInScene(){
   ... all the buttons / textFields

   createAccountButton.setOnAction(new EventHandler<ActionEvent>(){
        public void handle(ActionEvent t){
              **this.getStage().allScene(createAccountPane1);**
        }
   }
}

public Stage getStage(){
      return this.myStage;
}

public void allScene(Pane p){
      this.myStage.setScene(p);
}

I'm getting an error within the setOnAction function. "Cannot Find Symbol" getStage(). I know this must be a scope problem and it doesn't recognize any variables / functions outside of that scope. How do I make it so that I can change within? I've tried passing through the variable but that will just make my code messy and I wish there was a simpler way. Thanks guys!

1
2
7/16/2014 7:54:53 PM

Accepted Answer

Your code works as long as you keep consistency:

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Test extends Application{
    private Stage stage;
    @Override
    public void start(Stage primaryStage) throws Exception {
        stage = primaryStage;
        Scene scene = logInScene();
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    public Scene logInScene(){
        Pane root = new Pane();
        Button createAccountButton = new Button("create account");
        createAccountButton.setOnAction(new EventHandler<ActionEvent>(){
            public void handle(ActionEvent t){
                  stage.setScene(CreateAccountScene());
            }
       });
        root.getChildren().add(createAccountButton);
        return new Scene(root);
    }
    protected Scene CreateAccountScene() {
        VBox root = new VBox();
        Label userLabel = new Label("Insert the username:");
        final TextField userField = new TextField();
        Button createAccountButton = new Button("create account");
        createAccountButton.setOnAction(new EventHandler<ActionEvent>(){
            public void handle(ActionEvent t){
                  System.out.println("Account for user " + userField.getText() + " was created succesfully");
            }
       });
        root.getChildren().addAll(userLabel,userField,createAccountButton);
        return new Scene(root);
    }
    public static void main(String[] args) {
        launch(args);
    }

}
3
7/16/2014 9:57:36 PM

This question has already been solved, but I think it's worth clarifying that your line fails because the this keyword refers to the anonymous EventHandler you are implementing. In Java, you reference the outer class instance with OuterClass.this. So OuterClass.this.getStage().allScene(createAccountPane1); will work.

If you are looking for a prettier solution, some coders like to define a local variable that points to the outer class instance:

final OuterClass self = this;
createAccountButton.setOnAction(new EventHandler<ActionEvent>(){
        public void handle(ActionEvent t){
              self.getStage().allScene(createAccountPane1);
        }
}

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon