Issue
I want to make it so that when a button is pressed, different windows are displayed, and for this I need conditions. I don't want to create many methods for each button This code doesn't work:
@Override
public void buttonOnAction(ActionEvent event){
if(btnReaders.isPressed()){
btnReaders.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent e) {
Parent parent = null;
try {
parent = FXMLLoader.load(getClass().getResource("readersMenu.fxml"));
} catch (IOException ex) {
ex.printStackTrace();
}
Scene scene = new Scene(parent);
Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow();
window.setScene(scene);
window.show();
}
});
}
else if(btnDashboard.isPressed()){
btnDashboard.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent e) {
Parent parent = null;
try {
parent = FXMLLoader.load(getClass().getResource("librarianMenu.fxml"));
} catch (IOException ex) {
ex.printStackTrace();
}
Scene scene = new Scene(parent);
Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow();
window.setScene(scene);
window.show();
}
});
}
}
Solution
Here is an example of a parameterized event handler that will open the selected FXML in a new scene that will be set for the same stage containing the source node of the event.
- When the event handler is created, the application stores, in the event handler, the name of the FXML resource to be loaded.
- The event handler is assigned to a button action.
- When the button is actioned, the event handler loads a new FXML into a new scene and attaches that scene to the window that the button is defined in.
Example App
For this example, FXML files should be in the same location as the package containing the SceneSelector application.
SceneSelector.java
import javafx.application.Application;
import javafx.event.*;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.Objects;
public class SceneSelector extends Application {
@Override
public void start(Stage stage) {
Button sceneAButton = new Button("Scene A");
sceneAButton.setOnAction(
new SceneChangeEventHandler(
"sceneA.fxml"
)
);
Button sceneBButton = new Button("Scene B");
sceneBButton.setOnAction(
new SceneChangeEventHandler(
"sceneB.fxml"
)
);
Pane layout = new HBox(10,
sceneAButton,
sceneBButton
);
layout.setPadding(new Insets(10));
layout.setPrefSize(200, 150);
stage.setScene(
new Scene(layout)
);
stage.show();
}
class SceneChangeEventHandler implements EventHandler<ActionEvent> {
private final String fxmlResourceName;
public SceneChangeEventHandler(String fxmlResourceName) {
this.fxmlResourceName = fxmlResourceName;
}
@Override
public void handle(ActionEvent event) {
try {
Stage stage = (Stage) ((Node) event.getSource())
.getScene()
.getWindow();
changeScene(stage, fxmlResourceName);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void changeScene(
Stage stage,
String fxmlResourceName
) throws IOException {
Parent parent = FXMLLoader.load(
Objects.requireNonNull(
getClass().getResource(
fxmlResourceName
)
)
);
Scene scene = new Scene(parent);
stage.setScene(scene);
stage.setTitle(fxmlResourceName);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
sceneA.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<StackPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
prefHeight="150.0" prefWidth="200.0" style="-fx-background-color: lemonchiffon;"/>
sceneB.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<StackPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
prefHeight="150.0" prefWidth="200.0" style="-fx-background-color: azure;"/>
Answered By - jewelsea