如何解决在 JavaFX 中的图表上显示间隙
我在 JavaFX 8 中使用 XYChart
,我想显示指定系列的空单元格的间隙。当我传递 null 值时,我得到了 NullPointerException
:
series.get(index).getData().add(new XYChart.Data<>(Key,null));
我还发现了描述此问题的错误 https://bugs.openjdk.java.net/browse/JDK-8092134,但我不知道它是否仍然存在。
有人知道如何解决这个问题吗?
最好的问候,
迈克尔
解决方法
很明显,此功能不包括在内..如果您非常渴望获得此行为,您可以尝试以下逻辑。
话虽如此,可以有很多更好的方法,但这个答案是让您初步了解如何使用图表的受保护方法调整当前实现。
这个想法是......一旦绘图子布局完成,我们重新计算渲染线路径的逻辑......并删除不需要的数据点。如前所述,这只是出于想法目的,如果您有更多数据系列,那么您可能需要相应地工作。
[UPDATE] : 如果您想要每个系列的路径/数据点,请将“.series”附加到“.chart-series-line”和“.data”样式类。
请查看以下演示:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.*;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.layout.VBox;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.PathElement;
import javafx.stage.Stage;
import java.util.*;
public class XYChartDemo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
VBox root = new VBox();
CategoryAxis xAxis = new CategoryAxis();
xAxis.setLabel("days");
NumberAxis yAxis = new NumberAxis();
yAxis.setLabel("USD");
// AS OF NOW THIS IS THE CORE POINT I AM RELYING ON !! YOU CAN THINK OF A BETTER APPROACH TO IDENTIFY THE GAP POINTS.
List<Integer> s0GapIndexes = Arrays.asList(3,7);
List<Integer> s1GapIndexes = Arrays.asList(4,8);
Map<Integer,List<Integer>> seriesGap = new HashMap<>();
seriesGap.put(0,s0GapIndexes);
seriesGap.put(1,s1GapIndexes);
XYChart.Series<String,Double> series0 = new XYChart.Series<>();
series0.getData().add(new Data<>("2000-01-01",13.2));
series0.getData().add(new Data<>("2000-01-02",10.1));
series0.getData().add(new Data<>("2000-01-03",14.1));
series0.getData().add(new Data<>("2000-01-04",0.0)); // gap (INDEX 3)
series0.getData().add(new Data<>("2000-01-05",6.3));
series0.getData().add(new Data<>("2000-01-06",9.82));
series0.getData().add(new Data<>("2000-01-07",12.82));
series0.getData().add(new Data<>("2000-01-08",0.0)); // gap (INDEX 7)
series0.getData().add(new Data<>("2000-01-09",4.82));
series0.getData().add(new Data<>("2000-01-10",8.82));
series0.getData().add(new Data<>("2000-01-11",8.82));
XYChart.Series<String,Double> series1 = new XYChart.Series<>();
series1.getData().add(new Data<>("2000-01-01",20.2));
series1.getData().add(new Data<>("2000-01-02",14.1));
series1.getData().add(new Data<>("2000-01-03",7.1));
series1.getData().add(new Data<>("2000-01-04",9.0));
series1.getData().add(new Data<>("2000-01-05",0.0)); // gap (INDEX 4)
series1.getData().add(new Data<>("2000-01-06",5.32));
series1.getData().add(new Data<>("2000-01-07",11.0));
series1.getData().add(new Data<>("2000-01-08",15.3));
series1.getData().add(new Data<>("2000-01-09",0.0)); // gap (INDEX 8)
series1.getData().add(new Data<>("2000-01-10",4.82));
series1.getData().add(new Data<>("2000-01-11",6.82));
CustomLineChart lineChart = new CustomLineChart(xAxis,yAxis,seriesGap);
lineChart.getData().addAll(series0,series1);
root.getChildren().addAll(lineChart);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
class CustomLineChart<X,Y> extends LineChart<X,Y> {
Map<Integer,List<Integer>> seriesGap;
public CustomLineChart(Axis<X> xAxis,Axis<Y> yAxis,Map<Integer,List<Integer>> seriesGap) {
super(xAxis,yAxis);
this.seriesGap = seriesGap;
}
@Override
protected void layoutPlotChildren() {
super.layoutPlotChildren();
updatePath();
updateDataPoints();
}
private void updatePath() {
seriesGap.forEach((seriesNo,gapIndexes) -> {
Path path = (Path) lookup(".chart-series-line.series" + seriesNo);
System.out.println(path);
if (!path.getElements().isEmpty()) {
int dataSize = getData().get(seriesNo).getData().size();
int pathEleSize = path.getElements().size();
// Just ensuring we are dealing with right path
if (pathEleSize == dataSize + 1) {
// Build a new path,by jumping the gap points
List<PathElement> newPath = new ArrayList<>();
newPath.add(path.getElements().get(0));
for (int i = 1; i < path.getElements().size(); i++) {
if (gapIndexes.contains(i - 1)) {
LineTo lt = (LineTo) path.getElements().get(i + 1);
newPath.add(new MoveTo(lt.getX(),lt.getY()));
} else {
newPath.add(path.getElements().get(i));
}
}
// Update the new path to the current path.
path.getElements().clear();
path.getElements().addAll(newPath);
}
}
});
}
private void updateDataPoints() {
Group plotContent = (Group) lookup(".plot-content");
seriesGap.forEach((seriesNo,gapIndexes) -> {
// Remove all data points at the gap indexes
gapIndexes.forEach(i -> {
Node n = lookup(".series" + seriesNo + ".data" + i);
if (n != null) {
plotContent.getChildren().remove(n);
}
});
});
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。