JavaFX 14,堆叠条形图不显示负值

huangapple go评论80阅读模式
英文:

JavaFX 14, Stacked Bar chart does not display negative values

问题

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();
    }
}

JavaFX 14,堆叠条形图不显示负值

None of the previous stack overflow questions on this issue are working in JavaFX14 (for me anyway), does anyone know of a solution?

Previous Questions:

  1. https://stackoverflow.com/questions/58426539/javafx13-stacked-bar-chart-negative-values-not-showing
  2. https://stackoverflow.com/questions/15410153/javafx-stackedbar-chart-issue
  3. https://stackoverflow.com/questions/32355323/javafx-stackedbarchart-bug
英文:

Example:

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&lt;String, Number&gt; series = new XYChart.Series&lt;String, Number&gt;();
series.getData().add(new XYChart.Data&lt;String, Number&gt;(0 + &quot;&quot;, 5));
series.getData().add(new XYChart.Data&lt;String, Number&gt;(1 + &quot;&quot;, -5));
series.getData().add(new XYChart.Data&lt;String, Number&gt;(2 + &quot;&quot;, 3));
series.getData().add(new XYChart.Data&lt;String, Number&gt;(3 + &quot;&quot;, -2));
StackedBarChart&lt;String, Number&gt; weightChangeChartBar = new StackedBarChart&lt;String, Number&gt;(xAxis, yAxis);
weightChangeChartBar.getData().addAll(series);
Scene scene = new Scene(weightChangeChartBar, 500, 500);
stage.setScene(scene);
stage.show();
}
}

Outcome:

JavaFX 14,堆叠条形图不显示负值

None of the previous stack overflow questions on this issue are working in JavaFX14 (for me anyway), does anyone know of a solution?

Previous Questions:

  1. https://stackoverflow.com/questions/58426539/javafx13-stacked-bar-chart-negative-values-not-showing
  2. https://stackoverflow.com/questions/15410153/javafx-stackedbar-chart-issue
  3. https://stackoverflow.com/questions/32355323/javafx-stackedbarchart-bug

答案1

得分: 1

**已解决**
必须覆盖 Bar Charts 行为以解决此错误必须将系列添加到 Bar Chart然后才能将数据添加到系列

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);
    }

    // 启动 JavaFX 应用程序
    @Override
    public void start(Stage stage) {

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

        XYChart.Series<String, Number> series = new XYChart.Series<String, Number>();

        // 修改行为以解决错误
        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");
                }
            }
        };

        // 添加系列
        barChart.getData().addAll(series);

        // 然后添加数据
        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();
    }
}
/* ====== 柱状图 =========================================================== */
/* TODO 对负值柱进行垂直翻转渐变 */
.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;
}
英文:

Solved it:
The Bar Charts behavior must be overridden to solve the bug, the series must be added to the Bar Chart, THEN data can be added to the series.

 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&lt;String, Number&gt; series = new XYChart.Series&lt;String, Number&gt;();
// modify behavior to counter bug
StackedBarChart&lt;String, Number&gt; barChart = new StackedBarChart&lt;String, Number&gt;(xAxis, yAxis) {
@Override
protected void dataItemAdded(XYChart.Series&lt;String,Number&gt; series, int itemIndex, XYChart.Data&lt;String,Number&gt; item) {
super.dataItemAdded(series, itemIndex, item);
Node bar = item.getNode();
double barVal = item.getYValue().doubleValue();
if (barVal &lt; 0) {
bar.getStyleClass().add(&quot;negative&quot;);
}   
}       
};
// add series
barChart.getData().addAll(series);
// THEN add data
series.getData().add(new XYChart.Data&lt;String, Number&gt;(0 + &quot;&quot;, 5));
series.getData().add(new XYChart.Data&lt;String, Number&gt;(1 + &quot;&quot;, -5));
series.getData().add(new XYChart.Data&lt;String, Number&gt;(2 + &quot;&quot;, 3));
series.getData().add(new XYChart.Data&lt;String, Number&gt;(3 + &quot;&quot;, -2));
Scene scene = new Scene(barChart, 500, 500);
stage.setScene(scene);
stage.show();
}
}

Negative nodes must also have separate CSS from the positive nodes.

/* ====== 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

得分: 0

以下是您要翻译的内容:

wyit's 回答 中的补丁对我不起作用,但它引导我朝着正确的方向前进;我必须覆盖 StackedBarChart 中的另一个方法。

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

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

/**
 * 修复 StackedBarChart 无法显示负数。
 */
public class PatchedStackedBarChart<X, Y> extends StackedBarChart<X, Y> {
    public PatchedStackedBarChart(@NamedArg("xAxis") Axis<X> xAxis, @NamedArg("yAxis") Axis<Y> yAxis) {
        super(xAxis, yAxis);
    }

    /**
     * 覆盖打破图形的方法,补丁以添加丢失的 "negative" CSS 类。
     */
    @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) {
            // 添加丢失的 CSS 类
            item.getNode().getStyleClass().add("negative");
        }
    }

    /**
     * 覆盖打破图形的方法,补丁以不覆盖样式。
     */
    @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();
                // 将 .setAll 更改为 .addAll 以避免覆盖样式
                bar.getStyleClass().removeIf(s -> s.matches("chart-bar|(series|data)\\d+"));
                bar.getStyleClass().addAll("chart-bar", "series" + i, "data" + j);
            }
        }
    }
}
英文:

The patch in wyit's answer didn't work for me, but it led me in the right direction; I had to override a different method in StackedBarChart.

The official implementation (GitHub) uses bar.getStyleClass().setAll(), which removes the negative CSS class from the bar, resulting in incorrect rendering.

The following Java class patches the problematic method in StackedBarChart.

/**
 * Fixes StackedBarChart can&#39;t display negative numbers.
 */
public class PatchedStackedBarChart&lt;X, Y&gt; extends StackedBarChart&lt;X, Y&gt; {
    public PatchedStackedBarChart(@NamedArg(&quot;xAxis&quot;) Axis&lt;X&gt; xAxis, @NamedArg(&quot;yAxis&quot;) Axis&lt;Y&gt; yAxis) {
        super(xAxis, yAxis);
    }

    /**
     * Override the method that breaks the graph, patch to add missing &quot;negative&quot; CSS class.
     */
    @Override
    protected void dataItemAdded(Series&lt;X, Y&gt; series, int itemIndex, Data&lt;X, Y&gt; item) {
        super.dataItemAdded(series, itemIndex, item);

        Number val = (Number) (item.getYValue() instanceof Number ? item.getYValue() : item.getXValue());
        if (val.doubleValue() &lt; 0) {
            // add missing CSS class
            item.getNode().getStyleClass().add(&quot;negative&quot;);
        }
    }

    /**
     * Override the method that breaks the graph, patch so it doesn&#39;t override styles.
     */
    @Override
    protected void seriesChanged(ListChangeListener.Change&lt;? extends Series&gt; c) {
        for (int i = 0; i &lt; getData().size(); i++) {
            List&lt;Data&lt;X, Y&gt;&gt; items = getData().get(i).getData();
            for (int j = 0; j &lt; items.size(); j++) {
                Node bar = items.get(j).getNode();
                // change .setAll to .addAll to avoid overriding styles
                bar.getStyleClass().removeIf(s -&gt; s.matches(&quot;chart-bar|(series|data)\\d+&quot;));
                bar.getStyleClass().addAll(&quot;chart-bar&quot;, &quot;series&quot; + i, &quot;data&quot; + j);
            }
        }
    }
}

huangapple
  • 本文由 发表于 2020年4月3日 22:51:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/61014553.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定