Joe*_*Hut 5 java java-8 javafx-2 javafx-8
我在JavaFX中的定义位置添加一行时遇到问题.该行必须是一个常量行,如下所示:如何在JavaFX图表中添加值标记?
我的问题是,我的布局定义有点复杂.看一看:
重要的部分是顶部的那个.我希望在y = 60线上有这条线.RadioBoxes的左侧部分是VBox.带有(Scatter-)图表的部分是StackPane(因为我希望它填充宽度的其余部分).StackPane内部是图表和组.该集团唯一的子女就是这条线.
我认为问题在于,StackPane将集团的中心放在图表上方.但是我无法得到布局的组合,其中1.拉伸图表2.将线条设置在图表3上方.不会使线条居中
我尝试了很多组合,但我不能按照我想要的方式得到它.有人有想法吗?!
遗憾的是,XYCharts不支持ValueMarkers(可能是应该在层次结构中的位置)(使用具有常量值的数据)是一种在某些情况下可能(或不可)接受/可能的黑客攻击.
更清洁的出路是支持此类标记的自定义图表.一个自定义ScatterChart像:
public class ScatterXChart<X, Y> extends ScatterChart<X, Y> {
// data defining horizontal markers, xValues are ignored
private ObservableList<Data<X, Y>> horizontalMarkers;
public ScatterXChart(Axis<X> xAxis, Axis<Y> 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<X, Y> 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<X, Y> 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<X, Y> 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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
测试图表的片段(在oracle的教程中插入到在线示例中):
// instantiate chart
NumberAxis xAxis = new NumberAxis(0, 10, 1);
NumberAxis yAxis = new NumberAxis(-100, 500, 100);
ScatterXChart<Number,Number> sc = new ScatterXChart<>(xAxis,yAxis);
// .. fill with some data
...
// ui to add/change/remove a value marker
Data<Number, Number> 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));
Run Code Online (Sandbox Code Playgroud)
附录:
虽然我不建议在相关的问题的方法(添加标记线,以图表的父和外部管理其位置/长度)它是可以在可调整大小的容器中使用它.使它成功的关键因素:
在代码中(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);
Run Code Online (Sandbox Code Playgroud)