Gerhard Laib
Gerhard Laib

Reputation: 53

How can I have multiple SplitPanes including children with javaFX?

My structure:

AnchorPane
 | 
 ScrollPane
  |
  FlowPane
   |
   SplitPane
    |
    StackedBarChart
    TableView

How can I, duplicate my SplitPane with its children for a unknown numbers of duplicates?

How can i set for each copy new variable names?

In Scene Builder i right click on SplitPane and select Duplicate. But, the problem is the number of duplicates is not available before writting the program and is not known until runtime.

Upvotes: 2

Views: 1402

Answers (2)

ItachiUchiha
ItachiUchiha

Reputation: 36792

The best approach for this would be to create a separate FXML for SplitPane, load it as many times as you want and add it to your FlowPane.

Let us call the new fxml as split.fxml. A controller for the fxml called as SplitController

Then,we will load this fxml as many times as required, get the root and add it to the FlowPane, which is now present in a separate fxml.

Let us call the main fxml as container.fxml. A controller for the fxml called as ContainerController

Answering some of your questions :

How can I, duplicate my SplitPane with its children for a unknown numbers of duplicates?

Just load the fxml as many times you need.

How can i set for each copy new variable names?

You have the controller, you can identify it with a variable. You may also set a class or id to the splitpane.

The complete code...

split.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.chart.StackedBarChart?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>

<SplitPane fx:id="splitPane" dividerPositions="0.25" prefHeight="363.0" prefWidth="773.0" fx:controller="SplitController"  xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
    <items>
        <TableView fx:id="tableView" prefHeight="458.0" prefWidth="251.0">
            <columns>
                <TableColumn prefWidth="75.0" text="C1" />
                <TableColumn prefWidth="75.0" text="C2" />
            </columns>
        </TableView>
        <StackedBarChart fx:id="stackedBarChart" prefHeight="210.0" prefWidth="107.0">
            <xAxis>
                <CategoryAxis fx:id="categoryAxis" side="BOTTOM" label="Year" />
            </xAxis>
            <yAxis>
                <NumberAxis fx:id="numberAxis" side="LEFT" label="Value"/>
            </yAxis>
        </StackedBarChart>
    </items>
</SplitPane>

SplitController.java

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TableView;

import java.net.URL;
import java.util.ResourceBundle;

public class SplitController implements Initializable{

    @FXML
    private SplitPane splitPane;

    @FXML
    private StackedBarChart<String, Number> stackedBarChart;

    @FXML
    private TableView<String> tableView;

    @FXML
    private CategoryAxis categoryAxis;

    @FXML
    private NumberAxis numberAxis;

    private ObservableList<String> tableList;

    private ObservableList<Integer> chartValueList = FXCollections.observableArrayList();

    public void setTableList(ObservableList<String> tableList) {
        this.tableList = FXCollections.observableList(tableList);
    }

    public void setChartValueList(ObservableList<Integer> chartValueList) {
        this.chartValueList = FXCollections.observableList(chartValueList);
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }

    public void setChart(){
        XYChart.Series<String,Number> series1 = new XYChart.Series();

        series1.getData().add(new XYChart.Data("January", chartValueList.get(0)));
        series1.getData().add(new XYChart.Data("February", chartValueList.get(1)));
        series1.getData().add(new XYChart.Data("March", chartValueList.get(2)));
        series1.getData().add(new XYChart.Data("April", chartValueList.get(3)));

        XYChart.Series<String,Number> series2 = new XYChart.Series();

        series2.getData().add(new XYChart.Data("January", chartValueList.get(0)));
        series2.getData().add(new XYChart.Data("February", chartValueList.get(1)));
        series2.getData().add(new XYChart.Data("March", chartValueList.get(2)));
        series2.getData().add(new XYChart.Data("April", chartValueList.get(3)));

        stackedBarChart.getData().addAll(series1, series2);
    }
}

container.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.FlowPane?>

<BorderPane xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ContainerController">
   <center>
        <ScrollPane fx:id="scrollPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" BorderPane.alignment="CENTER">
            <content>
                <FlowPane fx:id="flowPane" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="353.0" prefWidth="745.0">

                </FlowPane>
            </content>
        </ScrollPane>
   </center>
</BorderPane>

ContainerController.java

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.FlowPane;

import java.io.IOException;
import java.net.URL;
import java.util.Random;
import java.util.ResourceBundle;

public class ContainerController implements Initializable{

    @FXML
    private AnchorPane anchorPane;

    @FXML
    private ScrollPane scrollPane;

    @FXML
    private FlowPane flowPane;

    private final int NUMBER_OF_COPIES = 5;
    private final int NUMBER_OF_ROWS = 10;
    private ObservableList<String> tableList = FXCollections.observableArrayList();
    private ObservableList<Integer> chartValueList = FXCollections.observableArrayList();


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        try {
            for(int i=0; i<NUMBER_OF_COPIES; i++) {
                FXMLLoader loader = new FXMLLoader(getClass().getResource("/split.fxml"));
                SplitPane pane = loader.load();
                SplitController controller = loader.getController();
                fillChartValueList();
                controller.setChartValueList(chartValueList);
                controller.setChart();
                flowPane.getChildren().add(pane);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void fillChartValueList(){

        // clear previous values
        chartValueList.clear();

        Random rand = new Random();
        int min = 1000;
        int max = 8000;


        for(int i=0; i<NUMBER_OF_ROWS; i++) {
            int randomNum = rand.nextInt((max - min) + 1) + min;
            chartValueList.add(randomNum);
        }
    }
}

Main.java - to load the container, set it to a stage and show

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class Main extends Application {

    public Main() {
        super();
    }

    @Override
    public void start(Stage primaryStage) throws IOException{

        FXMLLoader loader = new FXMLLoader(getClass().getResource("/container.fxml"));
        Parent parent = loader.load();
        ContainerController controller = loader.getController();

        Scene scene = new Scene(parent, 600, 600);
        Stage stage = new Stage();
        stage.setScene(scene);
        stage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }
}

Screenshot

enter image description here

Note - The TableView is empty as I didn't consider it important to fill it, as per the question.

Upvotes: 2

Gerhard Laib
Gerhard Laib

Reputation: 53

That works:

    SplitPane sp=new SplitPane(splitPane);
    sp.setId(machine);
    flowPane.getChildren().add(new SplitPane(sp));

Upvotes: 0

Related Questions