How to go back at previous scene - javafx

I'm making 3 scenes in javafx scenebuilder.
Scene A: Edit Record -> Scene C
Scene B: View Record -> Scene C
Scene C: View Data
How can I go back to the previous scene(A or B) without creating a duplicate Scene C.
public void view(ActionEvent event) throws IOException{
Parent mainpanelForm = FXMLLoader.load(getClass().getResource("Scene A or Scene B file location"));
Scene mainpanelUI = new Scene(mainpanelForm);
Stage mainpanel = (Stage) ((Node)event.getSource()).getScene().getWindow();
mainpanel.setScene(mainpanelUI);
mainpanel.centerOnScreen();
mainpanel.setMaximized(true);
mainpanel.show();
}

Related

JavaFX - ScrollPane within GridPane

I want a ScrollPane in my application window which doesn't fill the whole scene, but only takes up part of it, because I want to place a button beneath it.
Like in this sketch: https://i.imgur.com/eUA7Af7.png
I tried using a GridPane, but I can only put Nodes as children of the GridPane, which doesn't work because the ScrollPane is not a Node.
public void start(Stage stage) throws Exception {
var root = new GridPane();
var scene = new Scene(root, 400, 400);
var scrollPane = new ScrollPane();
root.add(scrollPane, 0, 0); // Not possible
var button = new Button();
root.add(button, 0, 1);
stage.setScene(scene);
stage.show();
}
Slaw's comment:
javafx.scene.control.ScrollPane definitely is a javafx.scene.Node. The class hierarchy is: ScrollPane → Control → Region → Parent → Node

Switching scenes in JavaFX with ActionEvent

Hello I am having an JavaFX app with few controllers and I have 2 options to get back to previous screen. User can click button 'leave' or after finishing some tasks on this screen will be moved to previous automatically. I have problem here because I've created method wiut fxml annotation which takes ActionEvent object as parameter and is called when user click button and when user will finish tasks and should be moved automatically to previous screen I cannot call this method because I dont this object, it's created when an action - click in this case is made. How can I make it possible for both 'exit' options?
So here is my method which is used 'onAction' for my button:
#FXML
private void leaveRoomAction(ActionEvent event) {
try {
removePlayerFromRoom();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("LobbyView.fxml"));
Parent root = (Parent) loader.load();
LobbyController lobbyController = (LobbyController)loader.getController();
lobbyController.setClientThread(client);
lobbyController.setNameAndBalance(client.getPlayer().getName());
Scene scene = new Scene(root);
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
stage.setScene(scene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
And later in other part of programe:
if(isFinished()){
//here I want write leaving this screen and getting back to previous
}
First, find another way to get a reference to the Stage. Since you almost certainly have a reference to some node in the scene in your controller, you can replace
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
with
Stage stage = (Stage) anyNode.getScene().getWindow();
where anyNode is just something you have injected into the controller.
Now you don't need the parameter at all, so you can just remove it. I.e. you end up with
#FXML
private Node anyNode ; // probably a more specific type than Node.
#FXML
private void leaveRoomAction() {
try {
removePlayerFromRoom();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("LobbyView.fxml"));
Parent root = (Parent) loader.load();
LobbyController lobbyController = (LobbyController)loader.getController();
lobbyController.setClientThread(client);
lobbyController.setNameAndBalance(client.getPlayer().getName());
Scene scene = new Scene(root);
Stage stage = anyNode.getScene().getWindow();
stage.setScene(scene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
And now you can just call the method:
if ( isFinished() ) {
leaveRoomAction()
}

JavaFX + Scene Builder how switch scene

I'm working with JavaFx and Scenebuilder and want create a local app for myself called "Taskplanner" in eclipse.
I created a new Stage and set it with a Scene (see Main.java). But not sure how to set a new Scene in the old stage (see Controller.java). Didnt also not find out if it is possible pass the signInButtonClicked()-Methode the "Stage primaryStage" over Scene Builder
Can anybody help ?
Controller.java:
#FXML
Button btnSignIn;
#FXML
public void signInButtonClicked() throws Exception
{
//Here I want call the new Scene(SignInGUI.fxml) in my old Stage
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("../view/SignInGUI.fxml"));
}
Main.java:
#Override
public void start(Stage primaryStage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("../view/LoginGUI.fxml"));
primaryStage.setTitle("Taskplanner");
primaryStage.setScene(new Scene(root,500,500));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
You can get a reference to the Scene and Window from your button reference. From there, it's up to you to decide how to you want to show the new view.
Here's how you get those references:
Scene scene = btnSignIn.getScene();
Window window = scene.getWindow();
Stage stage = (Stage) window;
You can change the view by changing the root of your Scene:
FXMLLoader loader = ... // create and load() view
btnSignIn.getScene().setRoot(loader.getRoot());
Or you can change the entire Scene:
FXMLLoader loader = ... // create and load() view
Stage stage = (Stage) btnSignIn.getScene().getWindow();
Scene scene = new Scene(loader.getRoot());
stage.setScene(scene);

A code I don't understand about switching scenes in JavaFX and SceneBuilder

Ater some googling, I figured that I can change scenes while remaining in the same stage by assigning this method to a button:
Parent root = FXMLLoader.load(getClass().getResource("view/bambam"));
Stage stage= (Stage) ((Node) event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
I don't understand the second line though. What does the stage and node in parenthesis mean? Is it some type of casting? Does it refer to the "primary" stage somehow? I'll be very thankful if someone could fully explain this line or tell me what material I've missed.
The syntax in which the type is placed in parentheses ahead of the expression is a downcast, which is explained nicely here and here. If you expand the code, it might be clearer:
Parent root = FXMLLoader.load(getClass().getResource("view/bambam"));
// get the source of the event
Object eventSource = event.getSource();
// the event only knows its source is some kind of object, however, we
// registered this listener with a button, which is a Node, so we know
// the actual runtime type of the source must be Button (which is a Node)
// So tell the compiler we are confident we can treat this as a Node:
Node sourceAsNode = (Node) eventSource ;
// get the scene containing the Node (i.e. containing the button):
Scene oldScene = sourceAsNode.getScene();
// get the window containing the scene:
Window window = oldScene.getWindow();
// Again, the Scene only knows it is in a Window, but we know we specifically
// put it in a stage. So we can downcast the Window to a Stage:
Stage stage = (Stage) window ;
// Equivalently, just omitting all the intermediate variables:
// Stage stage= (Stage) ((Node) event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
IMHO this is pretty badly written code. Firstly, downcasting to some extent sidesteps the usual compile-time type checks, relying on our own analysis of our coding logic to avoid runtime exceptions. Thus it is good practice to avoid it when possible.
In this case, you state that this code is part of a handler registered with a button. Therefore, the source of the event is the button. So, instead of going through all those steps to get back a reference to the button, we can just use an existing reference. In other words, you have something like:
button.setOnAction(event -> {
Parent root = FXMLLoader.load(getClass().getResource("view/bambam"));
Stage stage= (Stage) ((Node) event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
});
Here ((Node) event.getSource()) must be the button, so you can immediately simplify to
button.setOnAction(event -> {
Parent root = FXMLLoader.load(getClass().getResource("view/bambam"));
Stage stage = (Stage) button.getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
});
Secondly, there's really no need to replace the Scene at all: why not just replace the root of the existing Scene? For this you can do
button.setOnAction(event -> {
Parent root = FXMLLoader.load(getClass().getResource("view/bambam"));
Scene scene = button.getScene();
scene.setRoot(root);
});
(clearly the Stage is already showing, since the user clicked on the button, so stage.show() is redundant).
If you prefer, you can simplify that to
button.setOnAction(event -> {
Parent root = FXMLLoader.load(getClass().getResource("view/bambam"));
button.getScene().setRoot(root);
});
or even just
button.setOnAction(event ->
button.getScene().setRoot(FXMLLoader.load(getClass().getResource("view/bambam"))));

JavaFX: Set textfield value before showing window

I'm creating a new modal dialog from the main controller class. How do I set some textfield values in the dialog before it is displayed?
URL url = getClass().getResource("SeedNodeForm.fxml");
Stage stage = new Stage();
stage.setTitle("Seed Node Information");
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(((Node) event.getSource()).getScene().getWindow());
stage.initStyle(StageStyle.UTILITY);
Parent root = FXMLLoader.load(url);
stage.setScene(new Scene(root));
stage.centerOnScreen();
textfield1.setValue("foo!");
textfield2.setValue("foo2");
stage.showAndWait();
Thank you Uluk Biy - your link led me to the answer which is:
// get the controller from the loader
SeedNodeFormController c = (SeedNodeFormController) fxmlLoader.getController();
// call setter in controller routine to set needed values
c.setSeedNode(value);

Resources