在JavaFX图表中添加一行

我在JavaFX中的定义位置添加一行有问题。 该行必须是一个常量行,如下所示: 如何在JavaFX图表中添加值标记?

我的问题是,我的布局定义有点复杂。 看一看:

图表

重要的部分是顶部的那个。 我希望在y = 60行上有这条线。 RadioBoxes的左侧部分是VBox。 带有(Scatter-)图表的部分是StackPane(因为我希望它填充宽度的其余部分)。 StackPane内部是图表和组。 该集团唯一的子女就是这条线。

我认为问题是,StackPane将集团的中心放在图表上方。 但我无法得到布局的组合,其中1.拉伸图表2.将线条设置在图表3上方。不会使线条居中

我尝试了很多组合,但我无法按照我想要的方式得到它。 有人有想法吗?!

不幸的是,XYCharts不支持ValueMarkers(可能是应该在层次结构中的位置)(使用具有常量值的数据)是一种在某些情况下可能(或不可)接受/可能的黑客攻击。

更简洁的方法是支持此类标记的自定义图表。 一个自定义ScatterChart像:

public class ScatterXChart extends ScatterChart { // data defining horizontal markers, xValues are ignored private ObservableList> horizontalMarkers; public ScatterXChart(Axis xAxis, Axis yAxis) { super(xAxis, yAxis); // a list that notifies on change of the yValue property horizontalMarkers = FXCollections.observableArrayList(d -> new Observable[] {d.YValueProperty()}); // listen to list changes and re-plot horizontalMarkers.addListener((InvalidationListener)observable -> layoutPlotChildren()); } /** * Add horizontal value marker. The marker's Y value is used to plot a * horizontal line across the plot area, its X value is ignored. * * @param marker must not be null. */ public void addHorizontalValueMarker(Data marker) { Objects.requireNonNull(marker, "the marker must not be null"); if (horizontalMarkers.contains(marker)) return; Line line = new Line(); marker.setNode(line ); getPlotChildren().add(line); horizontalMarkers.add(marker); } /** * Remove horizontal value marker. * * @param horizontalMarker must not be null */ public void removeHorizontalValueMarker(Data marker) { Objects.requireNonNull(marker, "the marker must not be null"); if (marker.getNode() != null) { getPlotChildren().remove(marker.getNode()); marker.setNode(null); } horizontalMarkers.remove(marker); } /** * Overridden to layout the value markers. */ @Override protected void layoutPlotChildren() { super.layoutPlotChildren(); for (Data horizontalMarker : horizontalMarkers) { double lower = ((ValueAxis) getXAxis()).getLowerBound(); X lowerX = getXAxis().toRealValue(lower); double upper = ((ValueAxis) getXAxis()).getUpperBound(); X upperX = getXAxis().toRealValue(upper); Line line = (Line) horizontalMarker.getNode(); line.setStartX(getXAxis().getDisplayPosition(lowerX)); line.setEndX(getXAxis().getDisplayPosition(upperX)); line.setStartY(getYAxis().getDisplayPosition(horizontalMarker.getYValue())); line.setEndY(line.getStartY()); } } } 

测试图表的片段(在oracle的教程中插入到在线示例中):

 // instantiate chart NumberAxis xAxis = new NumberAxis(0, 10, 1); NumberAxis yAxis = new NumberAxis(-100, 500, 100); ScatterXChart sc = new ScatterXChart<>(xAxis,yAxis); // .. fill with some data ... // ui to add/change/remove a value marker Data horizontalMarker = new Data<>(0, 110); Button add = new Button("Add Marker"); add.setOnAction(e -> sc.addHorizontalValueMarker(horizontalMarker)); Slider move = new Slider(yAxis.getLowerBound(), yAxis.getUpperBound(), 0); move.setShowTickLabels(true); move.valueProperty().bindBidirectional(horizontalMarker.YValueProperty()); Button remove = new Button("Remove Marker"); remove.setOnAction(e -> sc.removeHorizontalValueMarker(horizontalMarker)); 

附录:

虽然我不建议相关问题中的方法 (将标记线添加到图表的父级并在外部管理其位置/长度),但可以在可resize的容器中使用它。 让它发挥作用的关键因素:

  • 听取图表的大小/位置变化并适当更新线条
  • 将标记的托管属性设置为false

在代码中(updateShift是原始中计算yShift / lineX的部分):

 Pane pane = new StackPane(chart); chart.widthProperty().addListener(o -> updateShift(chart)); chart.heightProperty().addListener(o -> updateShift(chart)); valueMarker.setManaged(false); pane.getChildren().add(valueMarker); 

为什么不在图表中添加该行? 我有图表,我显示100,99,95和50百分位数,我解决这个问题的方法是为每个百分位数的正确y值添加一行。

要做到这一点,只需添加一个有两个点的线,一个在y = 60 x = 70(最左边的x轴值),另一个在y = 60和x = 120(最右边的x轴)值)。

这样做的好处是你不必手动对齐水平线,缺点是这条水平线也将成为图例的一部分。 然而,看到你没有一个应该没问题的传奇。

如果您决定添加图例,请务必正确命名水平线,l