JavaFX: не отображаются отрицательные значения 13 столбчатой ​​диаграммы с накоплением - PullRequest
0 голосов
/ 17 октября 2019

Код ниже (jdk-13, javafx-sdk-13, Apache Netbeans 11.1) фактически работает, но я думаю, что делаю что-то не так.

а) Мне действительно нужны две серии, чтобы показать положительные и отрицательные значения в разных цветах?

б) Почему я должен добавить каждую серию дважды с противоположными значениями, чтобы показать их?

В соответствии со ссылкой это должно быть возможно с классом стиля "негативный": "Если значение данныхотрицательный, добавлен «отрицательный» класс стилей, например, .negative.chart-bar. »

Но я не могу заставить это работать.

BarChart, который я не люблю использовать, потому что мое реальное приложение имеет более 100 значений, а полосы становятся слишком тонкими. Кроме того, столбцы не отцентрированы должным образом.

Решения в этом примере я могу использовать для своего реального приложения, но, может быть, есть правильный способ сделать это?

    /*

    package hellofx;

    import static javafx.application.Application.launch;
    import java.util.Arrays;
    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.event.ActionEvent;
    import javafx.geometry.Insets;
    import javafx.geometry.Pos;
    import javafx.scene.Scene;
    import javafx.scene.chart.BarChart;
    import javafx.scene.chart.CategoryAxis;
    import javafx.scene.chart.NumberAxis;
    import javafx.scene.chart.StackedBarChart;
    import javafx.scene.chart.XYChart;
    import javafx.scene.control.Button;
    import javafx.scene.control.TabPane;
    import javafx.scene.control.Tab;
    import javafx.scene.control.Label;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;

    /**
     * Sample application to check stacked bar chart issues.
     * Problem 1: How to show negative values in a stacked bar chart.
     * Problem 2: How to show negative values as different colours.
     * Problem 3: (Solved) How to show different positive values for 1st series 
     *              in different charts.
     * Different tabs show the different approaches.
     * @author frank.meier
     */

    public class HelloFX extends Application{

        /**
         * @param args the command line arguments
         */

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

        private static final int NUMCAT = 20;  
        private static final double MAX = 10;
        private static final double MIN = -10;
        @Override 
        public void start(Stage primaryStage){

        Insets insets = new Insets(10,10,10,10);
        // Define Button
        Button btnUpdate = new Button();
        btnUpdate.setMinSize(100, 10);
        btnUpdate.setText("Update Chart");

        // Define Category Labels (xAxis)
        CategoryAxis xAxisPosNeg = new CategoryAxis();
        CategoryAxis xAxisPos = new CategoryAxis();
        CategoryAxis xAxisBar = new CategoryAxis();
        String[] categoryLabels = new String[NUMCAT];

        for(int i = 0;i < NUMCAT;i++){
            categoryLabels[i] = String.valueOf(i+1);
        }
        // Assign xAxis Labels    
        xAxisPosNeg.setCategories(FXCollections.<String>
                observableArrayList(Arrays.asList(categoryLabels)));
        xAxisPos.setCategories(FXCollections.<String>
                observableArrayList(Arrays.asList(categoryLabels)));
        xAxisBar.setCategories(FXCollections.<String>
                observableArrayList(Arrays.asList(categoryLabels)));

        // Define Value Axis (yAxis)
        NumberAxis yAxisPosNeg = new NumberAxis();
        yAxisPosNeg.setLowerBound(MIN);
        yAxisPosNeg.setUpperBound(MAX);

        NumberAxis yAxisPos = new NumberAxis();
        yAxisPos.setLowerBound(MIN);
        yAxisPos.setUpperBound(MAX);

        NumberAxis yAxisBar = new NumberAxis();
        yAxisBar.setLowerBound(MIN);
        yAxisBar.setUpperBound(MAX);

        // Define Chart and Series
        StackedBarChart<String,Number> sbcPosNeg = new StackedBarChart<>(xAxisPosNeg,yAxisPosNeg);
        XYChart.Series<String,Number> seriesPNPos = new XYChart.Series<>();
        XYChart.Series<String,Number> seriesPNNeg = new XYChart.Series<>();
        sbcPosNeg.setId("stacked-bar-chart-pos-neg");

        StackedBarChart<String,Number> sbcPosOnly = new StackedBarChart<>(xAxisPos,yAxisPos);
        XYChart.Series<String,Number> seriesPOPos = new XYChart.Series<>();
        sbcPosOnly.setId("stacked-bar-chart-pos-only");

        BarChart<String,Number> sbcBar = new BarChart<>(xAxisBar,yAxisBar);
        XYChart.Series<String,Number> seriesBar = new XYChart.Series<>();
        sbcBar.setId("bar-chart-pos-neg");

        // Configure Chart
        sbcPosNeg.setAnimated(false);
        yAxisPosNeg.setAutoRanging(false);
        sbcPosNeg.setCategoryGap(1);

        sbcPosOnly.setAnimated(false);
        yAxisPos.setAutoRanging(false);
        sbcPosOnly.setCategoryGap(1);

        sbcBar.setAnimated(false);
        yAxisBar.setAutoRanging(false);
        sbcBar.setCategoryGap(1);

        // Button Click Event
        btnUpdate.setOnAction((ActionEvent e) -> {
            updateSeries(categoryLabels,seriesPNPos,seriesPNNeg,seriesPOPos,seriesBar);
        });

        // Calculate Values for Chart
        updateSeries(categoryLabels,seriesPNPos, seriesPNNeg,seriesPOPos,seriesBar);
        sbcPosNeg.getData().addAll(seriesPNPos, seriesPNNeg);
        sbcPosOnly.getData().addAll(seriesPOPos);
        sbcBar.getData().addAll(seriesBar);

        // Define Scene Layout and Show
        VBox vboxTab1 = new VBox(sbcPosOnly);
        VBox vboxTab2 = new VBox(sbcBar);
        VBox vboxTab3 = new VBox(sbcPosNeg);

        vboxTab1.setPadding(insets);
        vboxTab1.setAlignment(Pos.CENTER);
        vboxTab2.setPadding(insets);
        vboxTab2.setAlignment(Pos.CENTER);
        vboxTab3.setPadding(insets);
        vboxTab3.setAlignment(Pos.CENTER);

            TabPane tabPane = new TabPane();
            Tab tab1 = new Tab("SBC: Pos.only",          vboxTab1);
            Tab tab2 = new Tab("BC: Gap too large",  vboxTab2);
            Tab tab3 = new Tab("SBC: Works, but why?",                         vboxTab3);
            tabPane.getTabs().addAll(tab1,tab2,tab3);

            VBox vbox = new VBox(new Label("Bar Charts Tests"));
            vbox.setMinSize(200, 400);
            vbox.setPadding(insets);
            vbox.setAlignment(Pos.CENTER);

            vbox.getChildren().addAll(tabPane,btnUpdate);

            Scene scene = new Scene(vbox);
            Stage stage = new Stage();
            stage.setScene(scene);
            scene.getStylesheets().add("helloFX/Chart.css");
            stage.show();
                }  // End Start

        /**
         * Calculates Series values randomly for each category label
         * @param cat           Category String Array
         * @param seriesPos     Series<String,Number>
         * @param seriesNeg     Series<String,Number>
         * @param seriesPosOnly Series<String,Number>
         */
        private static void updateSeries (String[] cat,
                XYChart.Series<String,Number> seriesPos,
                XYChart.Series<String,Number> seriesNeg,
                XYChart.Series<String,Number> seriesPosOnly,
                XYChart.Series<String,Number> seriesBar)
        {

            seriesPos.getData().clear();
            seriesNeg.getData().clear();
            seriesPosOnly.getData().clear();
            seriesBar.getData().clear();

            for(String cat1:cat){

                double v = ((Math.random()*(MAX-MIN))+MIN);
                if(v < 0){
                    // This series is used to add only negative values
                    // but value has to be added and substracted again. Why?
                    seriesNeg.getData().add(new XYChart.Data<>(cat1,v));
                    seriesNeg.getData().add(new XYChart.Data<>(cat1,-v)); 
                }
                else if (v >= 0){
                    seriesPos.getData().add(new XYChart.Data<>(cat1,v));
                    seriesPos.getData().add(new XYChart.Data<>(cat1,-v));
                }   // End  else if
                //
                // This series only shows positive Values.Why?
                seriesPosOnly.getData().add(new XYChart.Data<>(cat1,v));
                // If this line is uncommented negative values are shown also
                // but how can negative values be colored differently ?
                //seriesPosOnly.getData().add(new XYChart.Data<>(cat1,-v));

                // Bar chart shows negative values also, but the gap is too large.
                seriesBar.getData().add(new XYChart.Data<>(cat1,v));
            }    // End iterate for categories

        }   // End Method updateSeries

    } // End Class

И вотCSS:

#stacked-bar-chart-pos-neg .default-color0.chart-bar{
    -fx-bar-fill : red;
}

#stacked-bar-chart-pos-neg .default-color1.chart-bar{
    -fx-bar-fill : blue;
}

#stacked-bar-chart-pos-only .default-color0.chart-bar{
    -fx-bar-fill : green;
}

#stacked-bar-chart-pos-only .default-color0.negative.chart-bar {
    -fx-bar-fill : yellow;
}

#bar-chart-pos-neg .default-color0.chart-bar {
    -fx-bar-fill : lightgreen;
    -fx-bar-gap : 0;
}

#bar-chart-pos-neg .default-color0.chart-bar.negative {
    -fx-bar-fill : yellow;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...