Arigatex
Arigatex

Reputation: 43

JavaFX LineChart using SceneBuilder

I'm trying to make a simple LineChart with some random info, but when I try to do it with a fxml file though SceneBuilder the Chart shows but never gets filled. Whenever I create the vbox,linechart and scene manually everything works fine. I'm really confused where the chart code should go when using the fxml file.

public class Main extends Application {
    LineChart chart1;

    @Override
    public void start(Stage primaryStage) throws Exception {
        //Through FXML
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Chart Test");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();

        //Manually
//        LineChart chart1;
//        XYChart.Series series1 = new XYChart.Series();
//        NumberAxis xAxis = new NumberAxis();
//        NumberAxis yAxis = new NumberAxis();
//        xAxis.setLabel("X Axis");
//        yAxis.setLabel("Y Axis");
//        series1.setName("Series 1");
//        chart1 = new LineChart(xAxis, yAxis);
//        series1.getData().add(new XYChart.Data<>(1, 20));
//        series1.getData().add(new XYChart.Data<>(2, 100));
//        series1.getData().add(new XYChart.Data<>(3, 80));
//        series1.getData().add(new XYChart.Data<>(4, 180));
//        series1.getData().add(new XYChart.Data<>(5, 20));
//        series1.getData().add(new XYChart.Data<>(6, -10));
//        chart1.getData().add(series1);
//        VBox vbox=new VBox(chart1);
//        Scene scene=new Scene(vbox,600,400);
//        primaryStage.setScene(scene);
//        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
public class Controller implements Initializable {

    @FXML
    LineChart chart1;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        XYChart.Series series1 = new XYChart.Series();
        NumberAxis xAxis = new NumberAxis();
        NumberAxis yAxis = new NumberAxis();
        xAxis.setLabel("X Axis");
        yAxis.setLabel("Y Axis");
        series1.setName("Series 1");
        chart1 = new LineChart(xAxis, yAxis);
        series1.getData().add(new XYChart.Data<>(1, 20));
        series1.getData().add(new XYChart.Data<>(2, 100));
        series1.getData().add(new XYChart.Data<>(3, 80));
        series1.getData().add(new XYChart.Data<>(4, 180));
        series1.getData().add(new XYChart.Data<>(5, 20));
        series1.getData().add(new XYChart.Data<>(6, -10));
        chart1.getData().add(series1);
    }

}
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.LineChart?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>

<GridPane alignment="center" hgap="10" vgap="10" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <columnConstraints>
      <ColumnConstraints />
   </columnConstraints>
   <rowConstraints>
      <RowConstraints />
   </rowConstraints>
   <children>
      <BorderPane prefHeight="298.0" prefWidth="356.0">
         <center>
            <LineChart fx:id="chart1" title="Chart Test" BorderPane.alignment="CENTER">
              <xAxis>
                <CategoryAxis side="BOTTOM" />
              </xAxis>
              <yAxis>
                <NumberAxis side="LEFT" />
              </yAxis>
            </LineChart>
         </center>
      </BorderPane>
   </children>
</GridPane>

Upvotes: 4

Views: 8378

Answers (1)

James_D
James_D

Reputation: 209299

You have already created a LineChart and the axes in your FXML file with the code

<LineChart fx:id="chart1" title="Chart Test" BorderPane.alignment="CENTER">
  <xAxis>
    <CategoryAxis side="BOTTOM" />
  </xAxis>
  <yAxis>
    <NumberAxis side="LEFT" />
  </yAxis>
</LineChart>

This chart is added to a border pane, which in turn is added to the grid pane that is returned from the FXMLLoader.load() method and placed in the scene.

However, in your initialize() method you then create another line chart:

chart1 = new LineChart(xAxis, yAxis);

which you then proceed to populate with data. Since this new line chart is never displayed in the scene, you never see the data.

Also, note there is a discrepancy between the two charts: in the one created in the FXML you have a CategoryAxis, which is an Axis<String> as the x-axis, but in the chart created in the controller you use a NumberAxis as the x-axis. You probably want a NumberAxis, so change the FXML:

<LineChart fx:id="chart1" title="Chart Test" BorderPane.alignment="CENTER">
  <xAxis>
    <NumberAxis side="BOTTOM" />
  </xAxis>
  <yAxis>
    <NumberAxis side="LEFT" />
  </yAxis>
</LineChart>

and then simply remove the creation of the second line chart (and the second set of axes):

@FXML
LineChart<Number, Number> chart1;

@Override
public void initialize(URL location, ResourceBundle resources) {
    XYChart.Series<Number, Number> series1 = new XYChart.Series<>();
    series1.setName("Series 1");
    series1.getData().add(new XYChart.Data<>(1, 20));
    series1.getData().add(new XYChart.Data<>(2, 100));
    series1.getData().add(new XYChart.Data<>(3, 80));
    series1.getData().add(new XYChart.Data<>(4, 180));
    series1.getData().add(new XYChart.Data<>(5, 20));
    series1.getData().add(new XYChart.Data<>(6, -10));
    chart1.getData().add(series1);
}

Upvotes: 4

Related Questions