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:
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:
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!
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.
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.