Thursday, May 16, 2013

Update ObservableList for TableView, in UI thread and background thread.

In the code example "Detect mouse click on JavaFX TableView and get the details of the clicked item", the content were pre-inserted in start() method. This example show how to add records into ObservableList for TableView. Also show how to do it in FX Application Thread (or UI thread) and in background thread.

Update ObservableList for TableView, in UI thread and background thread.
Update ObservableList for TableView, in UI thread and background thread.


  • To keep track of the record id, introduce a class variable, trackId, in Record class.
  • Output Platform.isFxApplicationThread() in constructor of Record; such that we can know the thread of the operation.
  • Add TextFields for user to enter fields of new records.
  • Add buttons to add record in UI thread and in background thread.

package javafx_testtableview;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

/**
* @web http://java-buddy.blogspot.com/
*/
public class JavaFX_TestTableView extends Application {

public static class Record {

private static int trackId;
private final SimpleIntegerProperty id;
private final SimpleStringProperty name;
private final SimpleStringProperty lastName;
private final SimpleStringProperty email;

private Record(String name, String lastName, String email) {

System.out.println("Platform.isFxApplicationThread(): "
+ Platform.isFxApplicationThread());

this.id = new SimpleIntegerProperty(trackId);
this.name = new SimpleStringProperty(name);
this.lastName = new SimpleStringProperty(lastName);
this.email = new SimpleStringProperty(email);
trackId++;
}

public int getId() {
return this.id.get();
}

public void setId(int id) {
this.id.set(id);
}

public String getName() {
return this.name.get();
}

public void setName(String name) {
this.name.set(name);
}

public String getLastName() {
return this.lastName.get();
}

public void setLastName(String lastName) {
this.lastName.set(lastName);
}

public String getEmail() {
return this.email.get();
}

public void setEmail(String email) {
this.email.set(email);
}
}
private TableView<Record> tableView = new TableView<>();
private final ObservableList<Record> recordList = FXCollections.observableArrayList();

private void prepareRecordList() {
recordList.add(new Record("William", "Austin", "xxx@xxx.xxx"));
recordList.add(new Record("Chris", "redfield", "yyy@yyy.yyy"));
recordList.add(new Record("Java", "Buddy", "javabuddy@abc.yyy"));
}

@Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new Group());
primaryStage.setTitle("http://java-buddy.blogspot.com/");
primaryStage.setWidth(400);
primaryStage.setHeight(500);

prepareRecordList();

tableView.setEditable(false);

Callback<TableColumn, TableCell> integerCellFactory =
new Callback<TableColumn, TableCell>() {
@Override
public TableCell call(TableColumn p) {
MyIntegerTableCell cell = new MyIntegerTableCell();
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new MyEventHandler());
return cell;
}
};

Callback<TableColumn, TableCell> stringCellFactory =
new Callback<TableColumn, TableCell>() {
@Override
public TableCell call(TableColumn p) {
MyStringTableCell cell = new MyStringTableCell();
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new MyEventHandler());
return cell;
}
};

TableColumn colId = new TableColumn("ID");
colId.setCellValueFactory(
new PropertyValueFactory<Record, String>("id"));
colId.setCellFactory(integerCellFactory);

TableColumn colName = new TableColumn("Name");
colName.setCellValueFactory(
new PropertyValueFactory<Record, String>("name"));
colName.setCellFactory(stringCellFactory);

TableColumn colLastName = new TableColumn("Last Name");
colLastName.setCellValueFactory(
new PropertyValueFactory<Record, String>("lastName"));
colLastName.setCellFactory(stringCellFactory);

TableColumn colEmail = new TableColumn("Email");
colEmail.setCellValueFactory(
new PropertyValueFactory<Record, String>("email"));
colEmail.setCellFactory(stringCellFactory);

tableView.setItems(recordList);
tableView.getColumns().addAll(colId, colName, colLastName, colEmail);

final VBox vbox = new VBox();

Label label_name = new Label("Name");
final TextField textField_name = new TextField();
HBox hBox_name = new HBox();
hBox_name.setSpacing(10);
hBox_name.getChildren().addAll(label_name, textField_name);

Label label_lastname = new Label("Last Name");
final TextField textField_lastname = new TextField();
HBox hBox_lastname = new HBox();
hBox_lastname.setSpacing(10);
hBox_lastname.getChildren().addAll(label_lastname, textField_lastname);

Label label_email = new Label("email");
final TextField textField_email = new TextField();
HBox hBox_email = new HBox();
hBox_email.setSpacing(10);
hBox_email.getChildren().addAll(label_email, textField_email);

Button button_Add = new Button("Add record");
button_Add.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {

//update recordList in UI thread
recordList.add(new Record(
textField_name.getText(),
textField_lastname.getText(),
textField_email.getText()));

textField_name.clear();
textField_lastname.clear();
textField_email.clear();
}
});

Button button_AddBackGround = new Button("Add record in BACKGROUND");
button_AddBackGround.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {

final String bufferName = textField_name.getText();
final String bufferLastName = textField_lastname.getText();
final String bufferEmail = textField_email.getText();

new Thread() {
public void run() {

//update recordList in Background thread
recordList.add(new Record(
bufferName,
bufferLastName,
bufferEmail));
};
}.start();

textField_name.clear();
textField_lastname.clear();
textField_email.clear();
}
});

vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(hBox_name, hBox_lastname, hBox_email,
button_Add, button_AddBackGround, tableView);

((Group) scene.getRoot()).getChildren().addAll(vbox);

primaryStage.setScene(scene);
primaryStage.show();
}

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

class MyIntegerTableCell extends TableCell<Record, Integer> {

@Override
public void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : getString());
setGraphic(null);
}

private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}

class MyStringTableCell extends TableCell<Record, String> {

@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : getString());
setGraphic(null);
}

private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}

class MyEventHandler implements EventHandler<MouseEvent> {

@Override
public void handle(MouseEvent t) {
TableCell c = (TableCell) t.getSource();
int index = c.getIndex();

try {
Record item = recordList.get(index);
System.out.println("id = " + item.getId());
System.out.println("name = " + item.getName());
System.out.println("lastName = " + item.getLastName());
System.out.println("email = " + item.getEmail());
} catch (IndexOutOfBoundsException exception) {
//...
}

}
}
}


No comments:

Post a Comment