JavaFX,将setStyle应用于ObservableList中的所有LineCharts

时间:2015-05-05 14:32:56

标签: javafx-2 observablecollection linechart

我有ObservableList<LineChart> backCharts。我还有类StackChartSeries来比较数据的规模。根据这一点,我添加了新的比例图和新的比例图或添加系列到现有的背景图。 将样式应用于图表必须适用于指定比例的每个图表。但它只适用于指定比例的第一个图表。

下一个代码:

    public class StackChart extends StackPane {

    private  LineChart baseChart;
    private final ObservableList<LineChart> backCharts = FXCollections.observableArrayList();

    private final double yAxisWidth = 60;
    private final AnchorPane details;

    private final double yAxisSeparation = 20;
    private double strokeWidth = 0.5;
    private int size = 0;

    public StackChart(LineChart baseChart) {
        this(baseChart, null);
    }

    public StackChart(LineChart baseChart, Double strokeWidth) {
        if (strokeWidth != null) {
            this.strokeWidth = strokeWidth;
        }
        this.baseChart = baseChart;
        baseChart.setCreateSymbols(false);
        baseChart.setLegendVisible(false);
        baseChart.getXAxis().setAutoRanging(false);
        baseChart.getXAxis().setAnimated(false);
        baseChart.getXAxis().setStyle("-fx-font-size:" + 18);
        baseChart.getYAxis().setAnimated(false);
        baseChart.getYAxis().setStyle("-fx-font-size:" + 18);

        setFixedAxisWidth(baseChart);
        setAlignment(Pos.CENTER_LEFT);

        backCharts.addListener((Observable observable) -> rebuildChart());

        details = new AnchorPane();
        bindMouseEvents(baseChart, this.strokeWidth);

        rebuildChart();
    }

    private void bindMouseEvents(LineChart baseChart, Double strokeWidth) {
        getChildren().add(details);
        details.prefHeightProperty().bind(heightProperty());
        details.prefWidthProperty().bind(widthProperty());
        details.setMouseTransparent(true);

        setOnMouseMoved(null);
        setMouseTransparent(false);

        final Axis xAxis = baseChart.getXAxis();
        final Axis yAxis = baseChart.getYAxis();

        final Line xLine = new Line();
        final Line yLine = new Line();
        yLine.setFill(Color.GRAY);
        xLine.setFill(Color.GRAY);
        yLine.setStrokeWidth(strokeWidth/2);
        xLine.setStrokeWidth(strokeWidth/2);
        xLine.setVisible(false);
        yLine.setVisible(false);

        final Node chartBackground = baseChart.lookup(".chart-plot-background");
        for (Node n: chartBackground.getParent().getChildrenUnmodifiable()) {
            if (n != chartBackground && n != xAxis && n != yAxis) {
                n.setMouseTransparent(true);
            }
        }
        chartBackground.setCursor(Cursor.CROSSHAIR);
        chartBackground.setOnMouseEntered((event) -> {
            chartBackground.getOnMouseMoved().handle(event);
            xLine.setVisible(true);
            yLine.setVisible(true);
            details.getChildren().addAll(xLine, yLine);
        });
        chartBackground.setOnMouseExited((event) -> {
            xLine.setVisible(false);
            yLine.setVisible(false);
            details.getChildren().removeAll(xLine, yLine);
        });
        chartBackground.setOnMouseMoved(event -> {
            double x = event.getX() + chartBackground.getLayoutX();
            double y = event.getY() + chartBackground.getLayoutY();

            xLine.setStartX(65);
            xLine.setEndX(details.getWidth()-10);
            xLine.setStartY(y+5);
            xLine.setEndY(y+5);

            yLine.setStartX(x+5);
            yLine.setEndX(x+5);
            yLine.setStartY(12);
            yLine.setEndY(details.getHeight()-28);
        });
    }

    private void setFixedAxisWidth(LineChart chart) {
        chart.getYAxis().setPrefWidth(yAxisWidth);
        chart.getYAxis().setMaxWidth(yAxisWidth);
    }

    private void rebuildChart() {
        getChildren().clear();

        getChildren().add(resizeBaseChart(baseChart));
        for (LineChart lineChart : backCharts) {
            getChildren().add(resizeBackgroundChart(lineChart));
        }
        getChildren().add(details);
    }

    private Node resizeBaseChart(LineChart lineChart) {
        HBox hBox = new HBox(lineChart);
        hBox.setAlignment(Pos.CENTER_LEFT);
        hBox.prefHeightProperty().bind(heightProperty());
        hBox.prefWidthProperty().bind(widthProperty());

        lineChart.minWidthProperty().bind(widthProperty().subtract((yAxisWidth+yAxisSeparation)*backCharts.size()));
        lineChart.prefWidthProperty().bind(widthProperty().subtract((yAxisWidth+yAxisSeparation)*backCharts.size()));
        lineChart.maxWidthProperty().bind(widthProperty().subtract((yAxisWidth+yAxisSeparation)*backCharts.size()));

        return lineChart;
    }

    private Node resizeBackgroundChart(LineChart lineChart) {
        HBox hBox = new HBox(lineChart);
        hBox.setAlignment(Pos.CENTER_LEFT);
        hBox.prefHeightProperty().bind(heightProperty());
        hBox.prefWidthProperty().bind(widthProperty());
        hBox.setMouseTransparent(true);

        lineChart.minWidthProperty().bind(widthProperty().subtract((yAxisWidth + yAxisSeparation) * backCharts.size()));
        lineChart.prefWidthProperty().bind(widthProperty().subtract((yAxisWidth + yAxisSeparation) * backCharts.size()));
        lineChart.maxWidthProperty().bind(widthProperty().subtract((yAxisWidth + yAxisSeparation) * backCharts.size()));

        lineChart.translateXProperty().bind(baseChart.getYAxis().widthProperty());
        lineChart.getYAxis().setTranslateX((yAxisWidth + yAxisSeparation) * backCharts.indexOf(lineChart));

        return hBox;
    }

    private LineChart prepareLineChart(String seriesName){
        NumberAxis yAxis = new NumberAxis();
        NumberAxis xAxis = new NumberAxis();

        // xAxis
        xAxis.setAutoRanging(false);
        xAxis.setVisible(false);
        xAxis.setOpacity(0.0);
        xAxis.lowerBoundProperty().bind(((NumberAxis) baseChart.getXAxis()).lowerBoundProperty());
        xAxis.upperBoundProperty().bind(((NumberAxis) baseChart.getXAxis()).upperBoundProperty());
        xAxis.tickUnitProperty().bind(((NumberAxis) baseChart.getXAxis()).tickUnitProperty());

        // yAxis
        yAxis.setSide(Side.RIGHT);
        yAxis.setLabel(seriesName);

        // create chart
        LineChart lineChart = new LineChart(xAxis, yAxis);
        lineChart.setAnimated(false);
        lineChart.setLegendVisible(false);

        setFixedAxisWidth(lineChart);

        return lineChart;
    }

    public void addSeries(List<StackChartSeries> series){
        Collections.sort(series, (x, y) -> (int) (x.getMaxY() - y.getMaxY()));

        LineChart lineChart = null;
        size = series.size();

        for (int i = 0; i < size; i++) {
            if (i == 0 || series.get(i).getMaxY() / series.get(i-1).getMaxY() >= 10
                    || series.get(i).getMaxY() / series.get(i-1).getMaxY() <= 0.1
                    || Math.abs(series.get(i).getMaxY() - series.get(i-1).getMaxY()) >= 900
                    )   {
                lineChart = prepareLineChart("Scale" + i);
                //new chart with new scale
                backCharts.add(lineChart);
            }
            lineChart.getData().add(series.get(i).getSeries());
        }
        int j = 0;
        for (LineChart chart : backCharts) {
            styleBackChart(chart);
            //HERE
            setLineStyle(chart, j+3);
        }
    }

    private void styleBackChart(LineChart lineChart) {
        setStyle(lineChart);

        Node contentBackground = lineChart.lookup(".chart-content").lookup(".chart-plot-background");
        contentBackground.setStyle("-fx-background-color: transparent;");//

        lineChart.setVerticalZeroLineVisible(false);
        lineChart.setHorizontalZeroLineVisible(false);
        lineChart.setVerticalGridLinesVisible(false);
        lineChart.setHorizontalGridLinesVisible(false);
        lineChart.setCreateSymbols(false);
        lineChart.getXAxis().setStyle("-fx-font-size:" + 18);
        lineChart.getYAxis().setStyle("-fx-font-size:" + 18);
        }

    private void setStyle(LineChart chart) {
        chart.getYAxis().lookup(".axis-label").setStyle("-fx-font-size: 24;");
        Node seriesLine = chart.lookup(".chart-series-line");
        seriesLine.setStyle("-fx-stroke-width: " + strokeWidth + ";");
    }

    public Node getLegend() {
        HBox hbox = new HBox();

        final CheckBox baseChartCheckBox = new CheckBox(baseChart.getYAxis().getLabel());
        baseChartCheckBox.setSelected(true);
        baseChartCheckBox.setDisable(true);
        baseChartCheckBox.getStyleClass().add("readonly-checkbox");
        baseChartCheckBox.setOnAction(event -> baseChartCheckBox.setSelected(true));
        hbox.getChildren().add(baseChartCheckBox);

        for (final LineChart lineChart : backCharts) {
            CheckBox checkBox = new CheckBox(lineChart.getYAxis().getLabel());
            checkBox.setSelected(true);
            checkBox.setOnAction(event -> {
                if (backCharts.contains(lineChart)) {
                    backCharts.remove(lineChart);
                } else {
                    backCharts.add(lineChart);
                }
            });
            hbox.getChildren().add(checkBox);
        }

        hbox.setAlignment(Pos.CENTER);
        hbox.setSpacing(20);
        hbox.setStyle("-fx-padding: 0 10 20 10");

        return hbox;
    }

    private void setLineStyle (LineChart chart, Integer k)   {
        Node seriesLine = chart.lookup(".chart-series-line");
        seriesLine.setStyle(" -fx-stroke-dash-array: " + k + " 5 15 5;");
    }
}

StackChartSeries.java:

import javafx.scene.chart.XYChart;
import org.apache.commons.lang.ArrayUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.Optional;

public class StackChartSeries {
    private XYChart.Series series;
    private final double[] xValues;
    private final double[] yValues;
    private Optional<Double> maxY;

    public StackChartSeries(double[] xValues, double[] yValues) {
        this.xValues = xValues;
        this.yValues = yValues;
    }

    public XYChart.Series getSeries() {
        return series != null ? series : (series = prepareSeries(xValues, yValues));
    }

    private static XYChart.Series<Number, Number> prepareSeries( double[] xValues, double[] yValues)   {
        XYChart.Series<Number, Number> series = new XYChart.Series<>();
        for (int i = 0; i < yValues.length; i++){
            series.getData().add(new XYChart.Data(xValues[i], yValues[i]));
        }
        return series;
    }

    public double getMaxY(){
        if (maxY != null){
            return maxY.get();
        }
        else {
            Double d = C?ollections.max(Arrays.asList(ArrayUtils.toObject(yValues)));
            maxY = Optional.of(d);
            return maxY.get();
        }
    }

    public double[] getXValues() {
        return xValues;
    }

    public double[] getYValues() {
        return yValues;
    }
}

0 个答案:

没有答案