【发布时间】:2015-07-01 15:33:13
【问题描述】:
我尝试根据这篇帖子label on barchart 实现jewelsea 的方法,但标签不可见,我不明白为什么。 唯一的区别是我使用的是 fxml 文件,而我的图表数据由几个系列组成。
为了更好地说明问题,我做了一个MVCE:
public class PaneController implements Initializable{
@FXML
private LineChart<Number, Number> lineChart;
@Override
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
lineChart.setLegendVisible(false);
lineChart.setCreateSymbols(false);
lineChart.setData(createData());
/** for each serie add label on the peak if intensity > 0 */
for(int i=0;i<lineChart.getData().size();i++){
for(XYChart.Data<Number, Number> value:lineChart.getData().get(i).getData()){
if(value.getYValue().intValue()>0){
value.nodeProperty().addListener(new ChangeListener<Node>() {
@Override public void changed(ObservableValue<? extends Node> ov, Node oldNode, final Node node) {
System.out.println("value:"+node);
if (node != null) {
displayLabelForData(value);
}
}
});
}
}
}
}
/** create data for the line chart */
public ObservableList<Series<Number,Number>> createData(){
ObservableList<Series<Number,Number>> data = FXCollections.observableArrayList();
for(int i=1;i<=10;i++){
XYChart.Series<Number, Number> peakSelect = new XYChart.Series<>();
peakSelect.getData().add(new XYChart.Data<Number, Number>(i,0));
peakSelect.getData().add(new XYChart.Data<Number, Number>(i,i*2));
data.add(peakSelect);
}
return data;
}
/** places a x value label on each peak */
private void displayLabelForData(XYChart.Data<Number, Number> data){
final Node node = data.getNode();
final Text dataText = new Text(data.getXValue() + "");
node.parentProperty().addListener(new ChangeListener<Parent>() {
@Override public void changed(ObservableValue<? extends Parent> ov, Parent oldParent, Parent parent) {
Group parentGroup = (Group) parent;
parentGroup.getChildren().add(dataText);
}
});
node.boundsInParentProperty().addListener(new ChangeListener<Bounds>() {
@Override public void changed(ObservableValue<? extends Bounds> ov, Bounds oldBounds, Bounds bounds) {
dataText.setLayoutX( Math.round( bounds.getMinX() + bounds.getWidth() / 2 - dataText.prefWidth(-1) / 2 ) );
dataText.setLayoutY( Math.round( bounds.getMinY() - dataText.prefHeight(-1) * 0.5 ) );
}
});
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.chart.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.PaneController">
<children>
<LineChart fx:id="lineChart" prefHeight="400.0" prefWidth="500.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<xAxis>
<NumberAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</LineChart>
</children>
</AnchorPane>
主类:
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("Pane.fxml"));
AnchorPane rootPane = (AnchorPane) loader.load();
Scene scene = new Scene(rootPane);
primaryStage.setScene(scene);
primaryStage.setTitle("Test");
primaryStage.show();
PaneController controller = loader.getController();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
感谢您的帮助!
【问题讨论】:
-
问题在于
value.nodeProperty().addListener行的initialize方法。不知何故,ChangeListener从未被调用过。我看看能不能找出原因。