0

So right now I am trying to write a program for displaying data in JavaFX LineCharts. My main panel is a BorderPane with some features on top/left/right/etc.. in the center of the panel I want to display the LineChart(s). At least 1 and a maximum of 4.

So I thought about setting a gridpane into the center of the main panel to achieve an outcome similar to this:

Sample Gridpane

My problem now is, when I try to add LineCharts to the GridPane (with .add(chart, 0, 0), the chart just wont match with the parent. The same if I continue to add more Charts. It turns out to be something like this:

Something like this

I looked up a lot of stuff on parent matching, but somehow I am not getting anywhere :/ I´d need to know the size of the "center" of the borderpane, then I could size the LineCharts accordingly. But I cant find it... maybe someone of you has a clue?

Cheers!

  • Could you get the width of said pane, divide that by two, and do the same with the height? A quick google found [this](http://stackoverflow.com/questions/12643125/getting-the-width-and-height-of-the-center-space-in-a-borderpane-javafx-2) – Taelsin Feb 13 '17 at 22:22
  • Yes I tried this, but the result is whether satisfying, nor very elegant. When I have 4 charts in the grid, I tried to set prefWidth/Height of everyone to half of the dimensions of the GridPane. Somehow the charts still have different sizes, starting with chart 1 being the biggest and chart 4 being the smallest :/ – hans_maulwurf Feb 16 '17 at 12:26

1 Answers1

0

You can add a listener to the GridPane for the size its children elements and update the layout constraints of the child nodes based upon the size of the child element list.

charts

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.ObservableList;
import javafx.geometry.*;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

import java.util.stream.IntStream;

public class GridViewer extends Application {
    @Override
    public void start(final Stage stage) throws Exception {
        ChartGrid grid = new ChartGrid();

        grid.getChildren().setAll(
                IntStream.range(1, 5)
                        .mapToObj(this::createLineChart)
                        .toArray(Chart[]::new)
        );

        stage.setScene(new Scene(grid));
        stage.show();
    }

    class ChartGrid extends GridPane {
        ChartGrid() {
            setHgap(5);
            setVgap(5);
            setPadding(new Insets(5));

            setPrefSize(500, 500);

            Bindings.size(getChildren()).addListener((observable, oldSize, newSize) -> {
                ObservableList<Node> nodes = getChildren();
                for (int i = 0; i < newSize.intValue(); i++) {
                    GridPane.setConstraints(
                            nodes.get(i),
                            i / 2, i % 2,
                            1, 1,
                            HPos.CENTER, VPos.CENTER,
                            Priority.ALWAYS, Priority.ALWAYS
                    );
                }
            });
        }
    }

    private Chart createLineChart(int idx) {
        NumberAxis xAxis = new NumberAxis();
        NumberAxis yAxis = new NumberAxis();
        LineChart<Number, Number> chart = new LineChart<>(xAxis, yAxis);
        chart.setTitle("Chart " + idx);
        chart.setMinSize(0, 0);

        return chart;
    }

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

Note: an important part of this solution is setting the minSize of the charts to 0:

chart.setMinSize(0, 0);

This is because if you size the available area of the GridPane smaller than the sum of the min size of the charts (which is not 0 by default), then the charts will start to be drawn overlapping each other, which is not what you want.

jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • Thanks a lot for your effort, this was exactly what I needed! Thanks! – hans_maulwurf Feb 16 '17 at 13:14
  • Just one more question on the population of the grid: I want to add/remove charts dynamically (==> not via .setAll stream). When I use grid.add(chart, 0, 0) eg., I have to specify row/column, so the outcome is the GridPane split in four squares, with one chart in the top left corner. This isn´t wrong per se, because everything fits perfectly when I have 4 charts overall. But with one chart, the chart should actually be displayed all over the GridPane. What way/methods do you reccommend to get this right? (I also tried .getChildren.add followed by .getChildren.set, yet same outcome as above) – hans_maulwurf Feb 17 '17 at 12:51