【问题标题】:JavaFX 14, Stacked Bar chart does not display negative valuesJavaFX 14,堆积条形图不显示负值
【发布时间】:2020-07-15 18:43:48
【问题描述】:

示例:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;

public class Main extends Application {

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

    // Start the javafx application
    @Override
    public void start(Stage stage) {

        CategoryAxis xAxis = new CategoryAxis();
        NumberAxis yAxis = new NumberAxis();

        XYChart.Series<String, Number> series = new XYChart.Series<String, Number>();
        series.getData().add(new XYChart.Data<String, Number>(0 + "", 5));
        series.getData().add(new XYChart.Data<String, Number>(1 + "", -5));
        series.getData().add(new XYChart.Data<String, Number>(2 + "", 3));
        series.getData().add(new XYChart.Data<String, Number>(3 + "", -2));

        StackedBarChart<String, Number> weightChangeChartBar = new StackedBarChart<String, Number>(xAxis, yAxis);
        weightChangeChartBar.getData().addAll(series);

        Scene scene = new Scene(weightChangeChartBar, 500, 500);
        stage.setScene(scene);
        stage.show();
    }

}

结果:

之前关于这个问题的堆栈溢出问题都没有在 JavaFX14 中工作(无论如何对我来说),有人知道解决方案吗?

以前的问题:

  1. JavaFX:13 Stacked Bar Chart negative values not showing
  2. JavaFx StackedBar Chart Issue
  3. Javafx StackedBarChart bug

【问题讨论】:

    标签: java javafx charts openjfx


    【解决方案1】:

    解决了: 必须覆盖条形图行为才能解决错误,必须将系列添加到条形图中,然后才能将数据添加到系列中。

     package example;
    
        import javafx.application.Application;
        import javafx.scene.Node;
        import javafx.scene.Scene;
        import javafx.scene.chart.CategoryAxis;
        import javafx.scene.chart.NumberAxis;
        import javafx.scene.chart.StackedBarChart;
        import javafx.scene.chart.XYChart;
        import javafx.stage.Stage;
    
        public class Main extends Application {
    
            public static void main(String[] args) {
                launch(args);
            }
    
            // Start the javafx application
            @Override
            public void start(Stage stage) {
    
                CategoryAxis xAxis = new CategoryAxis();
                NumberAxis yAxis = new NumberAxis();
    
                XYChart.Series<String, Number> series = new XYChart.Series<String, Number>();
    
                 // modify behavior to counter bug
                 StackedBarChart<String, Number> barChart = new StackedBarChart<String, Number>(xAxis, yAxis) {
                    @Override
                    protected void dataItemAdded(XYChart.Series<String,Number> series, int itemIndex, XYChart.Data<String,Number> item) {
                        super.dataItemAdded(series, itemIndex, item);
    
                        Node bar = item.getNode();
                        double barVal = item.getYValue().doubleValue();
    
                        if (barVal < 0) {
                            bar.getStyleClass().add("negative");
                        }   
                    }       
                };
    
                // add series
                barChart.getData().addAll(series);
    
                // THEN add data
                series.getData().add(new XYChart.Data<String, Number>(0 + "", 5));
                series.getData().add(new XYChart.Data<String, Number>(1 + "", -5));
                series.getData().add(new XYChart.Data<String, Number>(2 + "", 3));
                series.getData().add(new XYChart.Data<String, Number>(3 + "", -2));
    
    
                Scene scene = new Scene(barChart, 500, 500);
                stage.setScene(scene);
                stage.show();
            }
    
        }
    

    负节点还必须具有与正节点不同的 CSS。

    /* ====== BAR CHART =========================================================== */
    /* TODO flip gradient vertical for negative bars */
    .chart-bar {
        -fx-bar-fill: #22bad9;
        -fx-background-color: linear-gradient(derive(-fx-bar-fill,-30%), derive(-fx-bar-fill,-40%)),
                              linear-gradient(derive(-fx-bar-fill,80%), derive(-fx-bar-fill, 0%)),
                              linear-gradient(derive(-fx-bar-fill,30%), derive(-fx-bar-fill,-10%));
        -fx-background-insets: 0,1,2;
        -fx-background-radius: 5 5 0 0, 4 4 0 0, 3 3 0 0;
    }
    
    .negative.chart-bar {
       -fx-background-color: linear-gradient(to top, derive(-fx-bar-fill,-30%), derive(-fx-bar-fill,-40%)),
                              linear-gradient(to top, derive(-fx-bar-fill, 80%), derive(-fx-bar-fill,0%)),
                              linear-gradient(to top, derive(-fx-bar-fill,30%), derive(-fx-bar-fill,-10%));
       -fx-background-radius: 0 0 5 5, 0 0 4 4, 0 0 3 3;
    }
    .bar-chart:horizontal .chart-bar, .stacked-bar-chart:horizontal .chart-bar {
        -fx-background-color: linear-gradient(to left, derive(-fx-bar-fill,-30%), derive(-fx-bar-fill,-40%)),
                              linear-gradient(to left, derive(-fx-bar-fill,80%), derive(-fx-bar-fill, 0%)),
                              linear-gradient(to left, derive(-fx-bar-fill,30%), derive(-fx-bar-fill,-10%));
        -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
    }
    .bar-chart:horizontal .negative.chart-bar, .stacked-bar-chart:horizontal .negative.chart-bar {
        -fx-background-color: linear-gradient(to right, derive(-fx-bar-fill,-30%), derive(-fx-bar-fill,-40%)),
                              linear-gradient(to right, derive(-fx-bar-fill, 80%), derive(-fx-bar-fill, 0%)),
                              linear-gradient(to right, derive(-fx-bar-fill,30%), derive(-fx-bar-fill,-10%));
        -fx-background-radius: 5 0 0 5, 4 0 0 4, 3 0 0 3;
    }
    

    【讨论】:

      【解决方案2】:

      wyit's answer 中的补丁对我不起作用,但它引导我朝着正确的方向前进;我不得不在 StackedBarChart 中重写一个不同的方法。

      官方实现(GitHub)使用bar.getStyleClass().setAll(),将negative CSS类从bar中移除,导致渲染不正确。

      以下 Java 类修补 StackedBarChart 中的问题方法。

      /**
       * Fixes StackedBarChart can't display negative numbers.
       */
      public class PatchedStackedBarChart<X, Y> extends StackedBarChart<X, Y> {
          public PatchedStackedBarChart(@NamedArg("xAxis") Axis<X> xAxis, @NamedArg("yAxis") Axis<Y> yAxis) {
              super(xAxis, yAxis);
          }
      
          /**
           * Override the method that breaks the graph, patch to add missing "negative" CSS class.
           */
          @Override
          protected void dataItemAdded(Series<X, Y> series, int itemIndex, Data<X, Y> item) {
              super.dataItemAdded(series, itemIndex, item);
      
              Number val = (Number) (item.getYValue() instanceof Number ? item.getYValue() : item.getXValue());
              if (val.doubleValue() < 0) {
                  // add missing CSS class
                  item.getNode().getStyleClass().add("negative");
              }
          }
      
          /**
           * Override the method that breaks the graph, patch so it doesn't override styles.
           */
          @Override
          protected void seriesChanged(ListChangeListener.Change<? extends Series> c) {
              for (int i = 0; i < getData().size(); i++) {
                  List<Data<X, Y>> items = getData().get(i).getData();
                  for (int j = 0; j < items.size(); j++) {
                      Node bar = items.get(j).getNode();
                      // change .setAll to .addAll to avoid overriding styles
                      bar.getStyleClass().removeIf(s -> s.matches("chart-bar|(series|data)\\d+"));
                      bar.getStyleClass().addAll("chart-bar", "series" + i, "data" + j);
                  }
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-07
        • 2019-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-23
        相关资源
        最近更新 更多