简体   繁体   中英

Spacing JavaFX LineCharts in GridPane

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!

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM