javafx 为折线图实现 x 值标签

javafx implement x-value labels for a line chart

我尝试按照这个postlabel 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>

主要Class:

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);
 }
}

感谢您的帮助!

我不知道如何解决你的问题,但我可以为你指出另一种方法来获得类似的效果。如果您需要使用折线图,可以试试这个 。但是,从您的示例来看,您似乎可以使用条形图,并使用您链接的问题中 jewelsea 的回答。