Reputation: 1
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
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