You do not need to use Properties in your table data objects to display them, although it is desirable to use Properties in certain circumstances.
The following code will display a people table based on the Person class, which has only String fields.
import javafx.application.Application; import javafx.collections.*; import javafx.geometry.Insets; import javafx.scene.*; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.VBox; import javafx.scene.text.Font; import javafx.stage.Stage; public class ReadOnlyTableView extends Application { private TableView<Person> table = new TableView<Person>(); private final ObservableList<Person> data = FXCollections.observableArrayList( new Person("Jacob", "Smith", "jacob.smith@example.com"), new Person("Isabella", "Johnson", "isabella.johnson@example.com"), new Person("Ethan", "Williams", "ethan.williams@example.com"), new Person("Emma", "Jones", "emma.jones@example.com"), new Person("Michael", "Brown", "michael.brown@example.com") ); public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { stage.setTitle("Table View Sample"); stage.setWidth(450); stage.setHeight(500); final Label label = new Label("Address Book"); label.setFont(new Font("Arial", 20)); TableColumn firstNameCol = new TableColumn("First Name"); firstNameCol.setMinWidth(100); firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); TableColumn lastNameCol = new TableColumn("Last Name"); lastNameCol.setMinWidth(100); lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); TableColumn emailCol = new TableColumn("Email"); emailCol.setMinWidth(200); emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); table.setItems(data); table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); final VBox vbox = new VBox(); vbox.setSpacing(5); vbox.setPadding(new Insets(10, 0, 0, 10)); vbox.getChildren().addAll(label, table); stage.setScene(new Scene(new Group(vbox))); stage.show(); } public static class Person { private String firstName; private String lastName; private String email; private Person(String fName, String lName, String email) { this.firstName = fName; this.lastName = lName; this.email = email; } public String getFirstName() { return firstName; } public void setFirstName(String fName) { firstName = fName; } public String getLastName() { return lastName; } public void setLastName(String lName) { lastName = lName; } public String getEmail() { return email; } public void setEmail(String inMail) { email = inMail; } } }
Explanation
The purpose of using properties and observable lists is that they are elements that you can listen to. When properties are used, if the value of the property attribute in the datamodel changes, the view of the element in the TableView is automatically updated in accordance with the updated value of the date model. For example, if a personβs email property value is set to a new value, this update will be reflected in the TableView because it listens for the property change. If instead a plain String was used to represent the email, the TableView was not updated because it was not aware of changes in the email value.
The PropertyValueFactory documentation details this process:
An example of using this class:
TableColumn<Person,String> firstNameCol = new TableColumn<Person,String>("First Name"); firstNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName"));
In this example, the string "firstName" is used as a reference to the alleged firstNameProperty () method in the class type Person (which is the class type of the list of TableView items). In addition, this method should return an instance of Property. If the method meets these requirements, then the TableCell is populated with this ObservableValue. In addition, the TableView will automatically add an observer to the returned value, so that any changed changes will be the observed TableView, as a result of which the cell is immediately updated.
If no method matching this pattern exists, support for trying to call get () or is () (which is, getFirstName () or isFirstName () in the example above). If a matching method for this template exists, the value returned by this method is equally wrapped in ReadOnlyObjectWrapper and returned in TableCell. However, in this situation, this means that TableCell will not be able to observe the ObservableValue for changes (as is the case with the first approach above).
Update
Here is an example opposite to the first example, which demonstrates how a TableView can observe and automatically update based on changes in it. ObservableList elements and change attribute value of an element based on properties.
import javafx.application.Application; import javafx.beans.property.*; import javafx.collections.*; import javafx.event.*; import javafx.geometry.Insets; import javafx.scene.*; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.VBox; import javafx.scene.text.Font; import javafx.stage.Stage; public class PropertyBasedTableView extends Application { private TableView<Person> table = new TableView<Person>(); private final ObservableList<Person> data = FXCollections.observableArrayList(); private void initData() { data.setAll( new Person("Jacob", "Smith", "jacob.smith@example.com"), new Person("Isabella", "Johnson", "isabella.johnson@example.com"), new Person("Ethan", "Williams", "ethan.williams@example.com"), new Person("Emma", "Jones", "emma.jones@example.com"), new Person("Michael", "Brown", "michael.brown@example.com") ); } public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { initData(); stage.setTitle("Table View Sample"); stage.setWidth(450); stage.setHeight(500); final Label label = new Label("Address Book"); label.setFont(new Font("Arial", 20)); TableColumn firstNameCol = new TableColumn("First Name"); firstNameCol.setMinWidth(100); firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); TableColumn lastNameCol = new TableColumn("Last Name"); lastNameCol.setMinWidth(100); lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); TableColumn emailCol = new TableColumn("Email"); emailCol.setMinWidth(200); emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email")); table.setItems(data); table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); table.setPrefHeight(300); final Button setEmailButton = new Button("Set first email in table to wizard@frobozz.com"); setEmailButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { if (data.size() > 0) { data.get(0).setEmail("wizard@frobozz.com"); } } }); final Button removeRowButton = new Button("Remove first row from the table"); removeRowButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { if (data.size() > 0) { data.remove(0); } } }); final Button resetButton = new Button("Reset table data"); resetButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { initData(); } }); final VBox vbox = new VBox(10); vbox.setPadding(new Insets(10, 0, 0, 10)); vbox.getChildren().addAll(label, table, setEmailButton, removeRowButton, resetButton); stage.setScene(new Scene(new Group(vbox))); stage.show(); } public static class Person { private final StringProperty firstName; private final StringProperty lastName; private final StringProperty email; private Person(String fName, String lName, String email) { this.firstName = new SimpleStringProperty(fName); this.lastName = new SimpleStringProperty(lName); this.email = new SimpleStringProperty(email); } public String getFirstName() { return firstName.get(); } public void setFirstName(String fName) { firstName.set(fName); } public StringProperty firstNameProperty() { return firstName; } public String getLastName() { return lastName.get(); } public void setLastName(String lName) { lastName.set(lName); } public StringProperty lastNameProperty() { return lastName; } public String getEmail() { return email.get(); } public void setEmail(String inMail) { email.set(inMail); } public StringProperty emailProperty() { return email; }