我正在使用JavaFx BarChart显示直方图,xAxis是CategoryAxis,我想显示两条与平均值和中位数相对应的垂直线,如this picture
谢谢
答案 0 :(得分:0)
您必须将图表放入Pane
内,并将Lines
添加为同一Pane
的更多子元素。然后,诀窍是如何找到在何处绘制Lines
:为此,您必须使用CSS查找(.lookup(".chart-plot-background");
)查找图表区域,并向图表轴询问特定值将在哪里绘制(Axis().getDisplayPosition()
)。
这是一个完整的示例:
package so_52998721;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.geometry.Bounds;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
/**
*
* @author ced04u
*/
public class SO_52998721 extends Application {
private XYChart<String, Number> barChart;
final private Line horizontalLine = new Line();
final private Line verticalLine = new Line();
@Override
public void start(Stage primaryStage) {
Pane root = new Pane();
barChart = new BarChart<>(
new CategoryAxis(),
new NumberAxis(0, 100, 5));
root.getChildren().addAll(barChart, horizontalLine, verticalLine);
barChart.setMaxWidth(Double.MAX_VALUE);
barChart.prefWidthProperty().bind(root.widthProperty());
barChart.prefHeightProperty().bind(root.heightProperty());
//populate barchart with some data
barChart.getData().add(new XYChart.Series(
FXCollections.observableArrayList(new XYChart.Data("pizza", 80.0),
new XYChart.Data("spaghetti", 50.0),
new XYChart.Data("mozzarella", 30.0)
)
));
//lines have to be updated every time the chart size changes
barChart.boundsInLocalProperty().addListener(new ChangeListener<Bounds>() {
@Override
public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
Platform.runLater(() -> {
updateLines();
});
}
});
updateLines();
Scene scene = new Scene(root, 1024, 768);
primaryStage.setScene(scene);
primaryStage.show();
}
private void updateLines() {
// find chart area Node
Node chartArea = barChart.lookup(".chart-plot-background");
// remember scene position of chart area
Bounds chartAreaBounds = chartArea.localToParent(chartArea.getBoundsInLocal());
//******** horizontal line ******************
horizontalLine.setStartX(chartAreaBounds.getMinX());
horizontalLine.setEndX(chartAreaBounds.getMaxX());
final double averageValue = (80 + 50 + 30) / 3;
double yShift = chartAreaBounds.getMinY();
// find pixel position of the specified value
final double medianPosition = barChart.getYAxis().getDisplayPosition(averageValue);
horizontalLine.setStartY(yShift + medianPosition);
horizontalLine.setEndY(yShift + medianPosition);
//******** vertical line ******************
verticalLine.setStartY(chartAreaBounds.getMinY());
verticalLine.setEndY(chartAreaBounds.getMaxY());
double xShift = chartAreaBounds.getMinX();
// find pixel position of the specified value
final double mozzarellaPosition = barChart.getXAxis().getDisplayPosition("mozzarella");
verticalLine.setStartX(xShift + mozzarellaPosition);
verticalLine.setEndX(xShift + mozzarellaPosition);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}