Here is an example. I used MVC
ideas from here and Passing Data
ideas from here.
This example has a Data Model
that simulates getting data from a database and passing it between subviews. DataModel
is created in the Main
and passed to the MainViewController
.
DataModel dataModel = new DataModel();
FXMLLoader rootLoader = new FXMLLoader(getClass().getResource("MainView.fxml"));
rootLoader.load();
MainViewController mainViewController = rootLoader.getController();
mainViewController.initModel(dataModel);
mainViewController.setSubSceneInitalNode();
After DataModel
is passed to MainViewController
, MainViewController
will pass it to the subview when it load subview.
Example loading the Orders
view
public void handleBtnOnActionOrders(ActionEvent actionEvent)
{
try
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("OrdersSubsene.fxml"));
loader.load();
OrdersSubseneController ordersSubseneController = loader.getController();
ordersSubseneController.initModel(dataModel);
spSubScene.getChildren().clear();
spSubScene.getChildren().add(ordersSubseneController.getVBoxRoot());
}
catch (IOException ex)
{
System.out.println(ex.toString());
}
}
Full Code
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
/**
* JavaFX App Sedrick(Sedj601)
*/
public class App extends Application {
@Override
public void start(Stage stage) throws IOException {
DataModel dataModel = new DataModel();
FXMLLoader rootLoader = new FXMLLoader(getClass().getResource("MainView.fxml"));
rootLoader.load();
MainViewController mainViewController = rootLoader.getController();
mainViewController.initModel(dataModel);
mainViewController.setSubSceneInitalNode();
Scene scene = new Scene(rootLoader.getRoot());
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
DataModel
package sed.test.dashboardfx;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author blj0011
*/
public class DataModel {
public List<String> simulateGetDataFromDatabase()
{
List<String> name = new ArrayList();
name.add("John Doe");
name.add("Jane Doe");
name.add("Kim Jackson");
name.add("James Jones");
return name;
}
}
Module-Info
module sed.test.dashboardfx {
requires javafx.controls;
requires javafx.fxml;
requires org.kordamp.ikonli.core;
requires org.kordamp.ikonli.javafx;
requires org.kordamp.ikonli.dashicons;
requires java.base;
opens sed.test.dashboardfx to javafx.fxml;
exports sed.test.dashboardfx;
}
MainViewController
import java.io.IOException;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
public class MainViewController {
@FXML private StackPane spSubScene;
@FXML private Button btnOverview;
private DataModel dataModel;
public void setSubSceneInitalNode()
{
btnOverview.fire();
}
public void handleBtnOnActionOverview(ActionEvent actionEvent)
{
try
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("OverviewSubscene.fxml"));
loader.load();
OverviewSubsceneController overviewSubsceneController = loader.getController();
overviewSubsceneController.initModel(dataModel);
spSubScene.getChildren().clear();
spSubScene.getChildren().add(overviewSubsceneController.getVBoxRoot());
}
catch (IOException ex)
{
System.out.println(ex.toString());
}
}
public void handleBtnOnActionOrders(ActionEvent actionEvent)
{
try
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("OrdersSubsene.fxml"));
loader.load();
OrdersSubseneController ordersSubseneController = loader.getController();
ordersSubseneController.initModel(dataModel);
spSubScene.getChildren().clear();
spSubScene.getChildren().add(ordersSubseneController.getVBoxRoot());
}
catch (IOException ex)
{
System.out.println(ex.toString());
}
}
public void handleBtnOnActionSettings(ActionEvent actionEvent)
{
try
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("SettingsSubscene.fxml"));
loader.load();
SettingsSubsceneController settingsSubsceneController = loader.getController();
settingsSubsceneController.initModel(dataModel);
spSubScene.getChildren().clear();
spSubScene.getChildren().add(settingsSubsceneController.getVBoxRoot());
}
catch (IOException ex)
{
System.out.println(ex.toString());
}
}
public void initModel(DataModel model)
{
if (this.dataModel != null) {
throw new IllegalStateException("Model can only be initialized once");
}
this.dataModel = model;
}
public void handleBtnExit(ActionEvent actionEvent)
{
Platform.exit();
}
}
MainView.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import org.kordamp.ikonli.javafx.FontIcon?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="720.0" prefWidth="1080.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sed.test.dashboardfx.MainViewController">
<children>
<HBox prefHeight="100.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
<children>
<VBox alignment="TOP_RIGHT" prefHeight="400.0" prefWidth="256.0" style="-fx-background-color: #05071F;">
<children>
<StackPane alignment="BOTTOM_CENTER" maxWidth="1.7976931348623157E308" prefHeight="175.0" prefWidth="200.0">
<padding>
<Insets bottom="5.0" />
</padding>
<children>
<FontIcon iconColor="WHITE" iconLiteral="dashicons-businessperson" iconSize="60" tabSize="0" />
</children>
</StackPane>
<Label fx:id="lblDisplayImageTitle" alignment="CENTER" maxWidth="1.7976931348623157E308" text="Current View" textFill="#e7e5e5">
<padding>
<Insets bottom="20.0" />
</padding>
</Label>
<Button fx:id="btnOverview" alignment="BASELINE_LEFT" graphicTextGap="22.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleBtnOnActionOverview" prefHeight="55.0" style="-fx-background-color: #05071F;" text="Overview" textFill="#e7e5e5">
<padding>
<Insets left="60.0" />
</padding>
<graphic>
<FontIcon iconColor="#fcf9f9" iconLiteral="dashicons-desktop" iconSize="25" />
</graphic>
</Button>
<Button fx:id="btnOrders" alignment="BASELINE_LEFT" graphicTextGap="22.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleBtnOnActionOrders" prefHeight="55.0" style="-fx-background-color: #05071F;" text="Orders" textFill="#e7e5e5">
<padding>
<Insets left="60.0" />
</padding>
<graphic>
<FontIcon iconColor="WHITE" iconLiteral="dashicons-list-view" iconSize="25" />
</graphic>
</Button>
<Button fx:id="btnSettings" alignment="BASELINE_LEFT" graphicTextGap="22.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleBtnOnActionSettings" prefHeight="55.0" style="-fx-background-color: #05071F;" text="Settings" textFill="#e7e5e5">
<padding>
<Insets left="60.0" />
</padding>
<graphic>
<FontIcon iconColor="WHITE" iconLiteral="dashicons-admin-settings" iconSize="25" />
</graphic>
</Button>
<StackPane prefHeight="150.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
<StackPane>
<children>
<Button maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleBtnExit" text="Exit">
<StackPane.margin>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</StackPane.margin>
</Button>
</children>
</StackPane>
</children>
</VBox>
<StackPane fx:id="spSubScene" style="-fx-background-color: #02030A;" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</children>
</VBox>
OrdersSubsceneController
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox;
/**
* FXML Controller class
*
* @author blj0011
*/
public class OrdersSubseneController {
private @FXML VBox vbRoot;
private @FXML ListView<String> listView;
private DataModel dataModel;
VBox getVBoxRoot()
{
return vbRoot;
}
public void initModel(DataModel model) {
if (this.dataModel != null) {
throw new IllegalStateException("Model can only be initialized once");
}
this.dataModel = model ;
listView.setItems(FXCollections.observableArrayList(model.simulateGetDataFromDatabase()));
}
}
OrdersSubscene.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="vbRoot" alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sed.test.dashboardfx.OrdersSubseneController">
<children>
<Label text="Orders Subscene" textFill="WHITE" />
<Label text="Use Passed Data in ListView!" textFill="WHITE" />
<ListView fx:id="listView" prefHeight="200.0" prefWidth="200.0" />
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>
OverviewSubsceneController
import java.util.StringJoiner;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
public class OverviewSubsceneController {
private @FXML VBox vbRoot;
private @FXML TextArea textArea;
private DataModel dataModel;
VBox getVBoxRoot()
{
return vbRoot;
}
public void initModel(DataModel model) {
if (this.dataModel != null) {
throw new IllegalStateException("Model can only be initialized once");
}
this.dataModel = model ;
StringJoiner stringJoiner = new StringJoiner(", ");
model.simulateGetDataFromDatabase().forEach(stringJoiner::add);
textArea.setText(stringJoiner.toString());
}
}
OverviewSubscene.fxml
package sed.test.dashboardfx;
import java.util.StringJoiner;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
public class OverviewSubsceneController {
private @FXML VBox vbRoot;
private @FXML TextArea textArea;
private DataModel dataModel;
VBox getVBoxRoot()
{
return vbRoot;
}
public void initModel(DataModel model) {
if (this.dataModel != null) {
throw new IllegalStateException("Model can only be initialized once");
}
this.dataModel = model ;
StringJoiner stringJoiner = new StringJoiner(", ");
model.simulateGetDataFromDatabase().forEach(stringJoiner::add);
textArea.setText(stringJoiner.toString());
}
}
SettingsSubsceneController
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.VBox;
public class SettingsSubsceneController {
private @FXML VBox vbRoot;
private @FXML ComboBox<String> comboBox;
private DataModel dataModel;
VBox getVBoxRoot()
{
return vbRoot;
}
public void initModel(DataModel model) {
if (this.dataModel != null) {
throw new IllegalStateException("Model can only be initialized once");
}
this.dataModel = model ;
comboBox.getItems().addAll(dataModel.simulateGetDataFromDatabase());
comboBox.getSelectionModel().selectFirst();
}
}
SettingsSubscene.fxml
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="vbRoot" alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sed.test.dashboardfx.SettingsSubsceneController">
<children>
<Label text="Settings Subscene" textFill="WHITE" />
<Label text="Use Passed Data in ComboBox" textFill="WHITE" />
<ComboBox fx:id="comboBox" prefWidth="150.0" />
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>
Output
