Aligning the X axes of several XYCharts

后端 未结 2 591
时光取名叫无心
时光取名叫无心 2021-01-21 11:36

I have two XYCharts that I want to display vertically aligned.

The two graphs share the same x axis, but they use different data sets, which values are not

相关标签:
2条回答
  • 2021-01-21 12:09

    Get rid of the GridPane code and replace it with:

    VBox vBox = new VBox(lineChart1, lineChart2);
    Scene scene = new Scene(vBox, 800, 600);
    

    Full code:

    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.chart.CategoryAxis;
    import javafx.scene.chart.LineChart;
    import javafx.scene.chart.NumberAxis;
    import javafx.scene.chart.XYChart;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    /**
     *
     * @author blj0011
     */
    public class JavaFXApplication139 extends Application
    {
    
        @Override
        public void start(Stage primaryStage)
        {
            primaryStage.setTitle("Line Chart Sample");
            final CategoryAxis xAxis1 = new CategoryAxis();
            final NumberAxis yAxis1 = new NumberAxis();
            xAxis1.setLabel("Month");
            final LineChart<String, Number> lineChart1
                    = new LineChart<>(xAxis1, yAxis1);
    
            final CategoryAxis xAxis2 = new CategoryAxis();
            xAxis2.setLabel("Month");
            final NumberAxis yAxis2 = new NumberAxis();
            final LineChart<String, Number> lineChart2
                    = new LineChart<>(xAxis2, yAxis2);
    
            lineChart1.setTitle("Charts");
            lineChart1.setLegendVisible(false);
            lineChart1.getYAxis().setTickLabelRotation(270);
            lineChart2.setLegendVisible(false);
            lineChart2.getYAxis().setTickLabelRotation(270);
    
            XYChart.Series series1 = new XYChart.Series();
            series1.setName("Portfolio 1");
    
            series1.getData().add(new XYChart.Data("Jan", 23));
            series1.getData().add(new XYChart.Data("Feb", 14));
            series1.getData().add(new XYChart.Data("Mar", 15));
            series1.getData().add(new XYChart.Data("Apr", 24));
            series1.getData().add(new XYChart.Data("May", 34));
            series1.getData().add(new XYChart.Data("Jun", 36));
            series1.getData().add(new XYChart.Data("Jul", 22));
            series1.getData().add(new XYChart.Data("Aug", 45));
            series1.getData().add(new XYChart.Data("Sep", 43));
            series1.getData().add(new XYChart.Data("Oct", 17));
            series1.getData().add(new XYChart.Data("Nov", 29));
            series1.getData().add(new XYChart.Data("Dec", 25));
    
            XYChart.Series series2 = new XYChart.Series();
            series2.setName("Portfolio 2");
            series2.getData().add(new XYChart.Data("Jan", 330000));
            series2.getData().add(new XYChart.Data("Feb", 340000));
            series2.getData().add(new XYChart.Data("Mar", 250000));
            series2.getData().add(new XYChart.Data("Apr", 440000));
            series2.getData().add(new XYChart.Data("May", 390000));
            series2.getData().add(new XYChart.Data("Jun", 160000));
            series2.getData().add(new XYChart.Data("Jul", 550000));
            series2.getData().add(new XYChart.Data("Aug", 540000));
            series2.getData().add(new XYChart.Data("Sep", 480000));
            series2.getData().add(new XYChart.Data("Oct", 270000));
            series2.getData().add(new XYChart.Data("Nov", 370000));
            series2.getData().add(new XYChart.Data("Dec", 290000));
    
            lineChart1.getData().addAll(series1);
            lineChart2.getData().addAll(series2);
    
            VBox vBox = new VBox(lineChart1, lineChart2);
            Scene scene = new Scene(vBox, 800, 600);
    
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args)
        {
            launch(args);
        }
    
    }
    

    0 讨论(0)
  • 2021-01-21 12:12

    Here's a quick shot on a specialized Layout that

    • only cares about children that are of type XYChart
    • lays them out vertically with a configurable spacing between them
    • sizes the yAxis width to its prefWidth, note that we need to pass-in the actual height of the axis (vs. the typical -1) ... took me a while ..
    • aligns each horizontally such that the xAxis are aligned and the yAxis has enough space for its labels

    It's not production quality, just for starters on how to do it :)

    /**
     * Lays out XYCharts vertically such that their x-axis are aligned and
     * there's enough space to fully show the labels of all y-axis.
     *   
     * @author Jeanette Winzenburg, Berlin
     */
    public class VChartBox extends Pane {
    
        protected void layoutChildren() {
            Insets insets = getInsets();
            double width = getWidth();
            double height = getHeight();
            // not entirely certain when to apply all the snaps, this is 
            // simply copied from vbox 
            double top = snapSpaceY(insets.getTop());
            double left = snapSpaceX(insets.getLeft());
            double bottom = snapSpaceY(insets.getBottom());
            double right = snapSpaceX(insets.getRight());
            double space = snapSpaceY(getSpacing());
    
            double availableWidth = snapSpaceX(width - left - right);
            List<XYChart> charts = getCharts();
            if (charts.isEmpty()) return;
            double heightPerChart = height / charts.size() - space;
            OptionalDouble maxYAxisWidth = charts.stream()
                    .filter(chart -> chart.getYAxis() != null)
                    .mapToDouble(chart -> chart.getYAxis().prefWidth(heightPerChart))
                    .max();
            double maxYWidth = maxYAxisWidth.orElse(0);
            double remainingWidth = availableWidth - maxYWidth;
            for (XYChart c : charts) {
                Axis axis = c.getYAxis();
                double axisWidth = axis != null ? axis.prefWidth(heightPerChart) : 0;
                double axisOffset = maxYWidth - axisWidth;
                double xOffset = axisOffset + left;
                double chartWidth = remainingWidth + axisWidth;
                c.resizeRelocate(xOffset, top, chartWidth, heightPerChart);
                top += snapSpaceY(c.getHeight() + getSpacing());
            }
        }
    
        protected List<XYChart> getCharts() {
            return getChildren().stream().filter(child -> child instanceof XYChart)
                    .map(chart -> (XYChart) chart).collect(toList());
        }
    
        // properties
        /**
         * The amount of vertical space between each child in the vbox.
         * 
         * @return the amount of vertical space between each child in the vbox
         */
        public final DoubleProperty spacingProperty() {
            if (spacing == null) {
                spacing = new SimpleDoubleProperty(this, "spacing", 20) {
                    @Override
                    public void invalidated() {
                        requestLayout();
                    }
    
                };
            }
            return spacing;
        }
    
        private DoubleProperty spacing;
    
        public final void setSpacing(double value) {
            spacingProperty().set(value);
        }
    
        public final double getSpacing() {
            return spacing == null ? 0 : spacing.get();
        }
    
        @SuppressWarnings("unused")
        private static final Logger LOG = Logger
                .getLogger(VChartBox.class.getName());
    }
    
    0 讨论(0)
提交回复
热议问题