JavaFX Table Columns, SceneBuilder Not Populating

2020-04-19 05:12发布

问题:

I've been looking at tutorials, and I can't seem to get a table to populate. I'm using net beans and scenebuilder too. Any help would be greatly appreciated! been struggling for 5 hours.

Here is my code for the Controller class:

public class FXMLDocumentController implements Initializable {

    @FXML
    private TableView<Table> table;
    @FXML
    private TableColumn<Table, String> countriesTab;

    /**
     * Initializes the controller class.
     */

    ObservableList<Table> data = FXCollections.observableArrayList(
            new Table("Canada"),
            new Table("U.S.A"),
            new Table("Mexico")
    );

    @Override
    public void initialize(URL url, ResourceBundle rb) {

        countriesTab.setCellValueFactory(new PropertyValueFactory<Table, String>("rCountry"));
        table.setItems(data);
    }
}

Here is my code for the Table

class Table {
    public final SimpleStringProperty rCountry;


    Table(String country){
        this.rCountry = new SimpleStringProperty(country);
    }

    private SimpleStringProperty getRCountry(){
        return this.rCountry;

    }
}

Here is my main:

public class Assignment1 extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

回答1:

For PropertyValueFactory to find the property the item class (i.e. Table in this case) needs public as access modifier, not package private. The method returning the property needs to be public as well.

Furthermore the correct name for the method returning the property itself is <nameOfProperty>Property according to the conventions required for PropertyValueFactory to work.

Also since the actual type of the property is an implementation detail, it would be better design to use StringProperty as return type instead of SimpleStringProperty

public class Table {

    private final SimpleStringProperty rCountry;

    public Table(String country){
        this.rCountry = new SimpleStringProperty(country);
    }

    public StringProperty rCountryProperty() {
        return this.rCountry;
    }
}

In case you used these modifiers to prevent write access to the property, you can still achieve this effect by using a ReadOnlyStringWrapper and return a ReadOnlyStringProperty:

public class Table {

    private final ReadOnlyStringWrapper rCountry;

    public Table(String country){
        this.rCountry = new ReadOnlyStringWrapper (country);
    }

    public ReadOnlyStringProperty rCountryProperty() {
        return this.rCountry.getReadOnlyProperty();
    }
}

In case there is no write access to the property at all, simply using a getter for the property is enough. You do not need to use a StringProperty at all in this case:

public class Table {

    private final String rCountry;

    public Table(String country){
        this.rCountry = country;
    }

    public String getRCountry() {
        return this.rCountry;
    }
}