The table cells are empty in my tableview. JavaFX + Scenebuilder


Question

I am trying to get the table cells to show the string when i create new rows. But all the rows are just empty. Do anyone know what i am doing wrong? Here is the main class: package application;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Cursor;
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("/fxml/BasketCase_GUI_0.3.fxml"));
            Scene scene = new Scene(root,1110,740);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());

            primaryStage.setResizable(false);
            primaryStage.setScene(scene);
            primaryStage.setTitle("Basket Case_Beta");
            primaryStage.show();
            scene.setCursor(Cursor.DEFAULT);


        }

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

    }
}

This is normal and working so i dont think you need to worry about that one.

Here is the controller class. Where I think the problem might be.

package application;

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

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

public class MainController implements Initializable {

    @FXML
    TableView<Table> TableID;
    @FXML
    TableColumn<Table, Integer> aPlayerID;
    @FXML
    TableColumn<Table, String> aLeague;
    @FXML
    TableColumn<Table, String> aName;
    private int aNumber = 1;
    SimpleStringProperty str = new SimpleStringProperty();
    public MainController() {
        str.set("Hello");
    }

    final ObservableList<Table> data = FXCollections.observableArrayList(
            new Table(aNumber++, "hehe", "hoho"),
            new Table(aNumber++, "hehe", "hoho"),
            new Table(aNumber++, "hehe", "hoho")
            );

    public void buttonClick(ActionEvent event) {
        data.add(new Table(aNumber++, "hehe", "hoho"));
        TableID.getColumns().addAll(aPlayerID, aLeague, aName);
    }

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {

        aPlayerID.setCellValueFactory( new PropertyValueFactory<Table, Integer>("bPlayerID"));
        aLeague.setCellValueFactory( new PropertyValueFactory<Table, String>("bLeague"));
        aName.setCellValueFactory( new PropertyValueFactory<Table, String>("bName"));

        TableID.setItems(data);

    }

}

And here is also the table class thats needed for the tableviewer

package application;

import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;

public class Table {

    private final SimpleIntegerProperty bPlayerID;
    private final SimpleStringProperty bLeague;
    private final SimpleStringProperty bName;

    public Table(int cPlayerID, String cLeague, String cName) {
        this.bPlayerID = new SimpleIntegerProperty(cPlayerID);
        this.bLeague = new SimpleStringProperty(cLeague);
        this.bName = new SimpleStringProperty(cName);
    }

    public int getbPlayerID() {
        return bPlayerID.get();
    }
    public void setbPlayerID(int v) {
        bPlayerID.set(v);
    }
    public String getbLeague() {
        return bLeague.get();
    }
    public void setbLeague(String v) {
        bLeague.set(v);
    }
    public String getbName() {
        return bName.get();
    }
    public void setbName(String v) {
        bName.set(v);
    }
}

Do you guys know what could be wrong or maybe suggest how I could add just the tableviewer with code that still works with the rest of the fxml file from the scenebuilder?

1
2
11/22/2014 5:42:26 PM

Accepted Answer

The names of your get methods are wrong. According to the PropertyValueFactory documentation, if you pass in a property name of "xyz", the property value factory will first look for a method xyzProperty() belonging to the object in the table row. If it doesn't find that, it will fall back on looking for a method called getXyz() (carefully look at the capitalization there), wrapping the result in a ReadOnlyObjectWrapper.

So the following would work:

package application;

import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;

public class Table {

    private final SimpleIntegerProperty bPlayerID;
    private final SimpleStringProperty bLeague;
    private final SimpleStringProperty bName;

    public Table(int cPlayerID, String cLeague, String cName) {
        this.bPlayerID = new SimpleIntegerProperty(cPlayerID);
        this.bLeague = new SimpleStringProperty(cLeague);
        this.bName = new SimpleStringProperty(cName);
    }

    public int getBPlayerID() {
        return bPlayerID.get();
    }
    public void setBPlayerID(int v) {
        bPlayerID.set(v);
    }
    public String getBLeague() {
        return bLeague.get();
    }
    public void setBLeague(String v) {
        bLeague.set(v);
    }
    public String getBName() {
        return bName.get();
    }
    public void setBName(String v) {
        bName.set(v);
    }
}

However, as stated in the PropertyValueFactory documentation, the properties in this case would not be "live": in other words if the values change, the table will not automatically update. Additionally, if you wanted to make the table editable, it wouldn't update the properties without some explicit wiring to call the set methods.

It's better to define your table model using the outline in the Properties and Bindings tutorial:

package application;

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

public class Table {

    private final IntegerProperty bPlayerID;
    private final StringProperty bLeague;
    private final StringProperty bName;

    public Table(int cPlayerID, String cLeague, String cName) {
        this.bPlayerID = new SimpleIntegerProperty(cPlayerID);
        this.bLeague = new SimpleStringProperty(cLeague);
        this.bName = new SimpleStringProperty(cName);
    }

    public int getBPlayerID() {
        return bPlayerID.get();
    }
    public void setBPlayerID(int v) {
        bPlayerID.set(v);
    }
    public IntegerProperty bPlayerIDProperty() {
        return bPlayerID ;
    }

    public String getBLeague() {
        return bLeague.get();
    }
    public void setBLeague(String v) {
        bLeague.set(v);
    }
    public StringProperty bLeagueProperty() {
        return bLeague ;
    }

    public String getBName() {
        return bName.get();
    }
    public void setBName(String v) {
        bName.set(v);
    }
    public StringProperty bNameProperty() {
        return bName ;
    }
}

If you do that, then (in Java 8) you can use the following cell value factories, instead of the PropertyValueFactory:

aPlayerID.setCellValueFactory(cellData -> cellData.getValue().bPlayerIDProperty());

which will allow the compiler to catch any errors, instead of it just failing silently at runtime.

3
11/22/2014 10:11:30 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon