WooWings
WooWings

Reputation: 1

JavaFX - unable to add items to tableview

I'm fairly new to JavaFX. I've been hopelessly trying to get this to work for so long and have no idea why it's not working. The items are not showing up on the tableview. I created the UI using scene builder. I've looked at many similar questions and nothing seems to have helped.

Simplified for minimal code:

Main:

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

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


    public static void main(String[] args) {
        launch(args);
    }
}

Controller:

package sample;

import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;

import java.net.URL;
import java.util.ResourceBundle;


public class Controller implements Initializable {
    ObservableList<Person> people = FXCollections.observableArrayList();
    @FXML private TableView<Person> table;
    @FXML private TableColumn<Person, SimpleStringProperty> c1;
    @FXML private TableColumn<Person, SimpleStringProperty> c2;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        c1.setCellValueFactory(new PropertyValueFactory<>("age"));
        c2.setCellValueFactory(new PropertyValueFactory<>("name"));

        people.add(new Person("2", "Sam"));
        people.add(new Person("1", "Met"));
        table.setItems(people);
    }


}

Person class:

package sample;

import javafx.beans.property.SimpleStringProperty;

public class Person {
    private SimpleStringProperty age;
    private SimpleStringProperty name;


    public Person(String age, String name) {
        this.age = new SimpleStringProperty(age);
        this.name = new SimpleStringProperty(name);
    }
}

FXML:

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

<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>


<?import javafx.scene.control.cell.PropertyValueFactory?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
            minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1"
        xmlns:fx="http://javafx.com/fxml/1">
  <TableView fx:id="table" layoutX="51.0" layoutY="31.0" prefHeight="338.0" prefWidth="498.0">
        <columns>
          <TableColumn fx:id="c1" prefWidth="75.0" text="C1">
            <cellValueFactory>
                <PropertyValueFactory property="c1" />
            </cellValueFactory>
          </TableColumn>
            <TableColumn fx:id="c2" prefWidth="75.0" text="C1">
                <cellValueFactory>
                    <PropertyValueFactory property="c2" />
                </cellValueFactory>
            </TableColumn>
        </columns>
      </TableView>
</AnchorPane>

Thanks.

Upvotes: 0

Views: 765

Answers (1)

c0der
c0der

Reputation: 18812

To make it work you need to implement a few changes. Read the comments in the code :

Person class must have public getters:

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Person {

    private final SimpleStringProperty age;
    private final SimpleStringProperty name;

    public Person(String age, String name) {
        this.age = new SimpleStringProperty(age);
        this.name = new SimpleStringProperty(name);
    }

    //add getters to properties with the appropriate naming convention  
    public final StringProperty ageProperty() {
        return age;
    }

    public final StringProperty nameProperty() {
        return name;
    }
}  

In the fxml you must specify the controller. Also note the change in TableView :

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

<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>

<?import javafx.scene.control.cell.PropertyValueFactory?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
            minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1"
           xmlns:fx="http://javafx.com/fxml/1"  
           fx:controller="xml_tabel_1.Controller"> <!-- need to specify the controller of the fxml -->
  <TableView items="${controller.people}"> <!-- need to specify the name of the observable list -->
        <columns>
          <TableColumn prefWidth="75.0" text="age">

            <cellValueFactory>
                <PropertyValueFactory property="age" />
            </cellValueFactory>
          </TableColumn>
            <TableColumn prefWidth="75.0" text="name">
                <cellValueFactory>
                    <PropertyValueFactory property="name" />
                </cellValueFactory>
            </TableColumn>
        </columns>
      </TableView>
</AnchorPane>

All you need to do in the controller is to populate the observable list and have a public getter for it :

import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.Initializable;

public class Controller implements Initializable {

    private final ObservableList<Person> people = FXCollections.observableArrayList();
    //all this was already set in fxml 
    //@FXML private TableView<Person> table;
    //@FXML private TableColumn<Person, SimpleStringProperty> c1;
    //@FXML private TableColumn<Person, SimpleStringProperty> c2;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        people.add(new Person("2", "Sam"));
        people.add(new Person("1", "Met"));
    }

    //add a getter to people 
    public ObservableList<Person> getPeople() {
        return people ;
    }
}

Upvotes: 2

Related Questions