I am trying to show the progress and the status of the each task in the JavaFX
TableView
. Each task represents by a row into a TableView
.
Each task executes in a separate Thread. Task may be like - downloading files from server, copy files from one account to another account etc. Threads may take long time to finish there task. My app also control the number of threads to perform operation in queue. With default setting, It can run maximum 5 threads at a time.
My Issue is - My TableView
does not show the updated status and progress. I have to click on column headers to refresh the TableView
. How to make TableView update aromatically? In background, if I run a thread that triggers automatically after specific time interval for refreshing the TableView
making my UI freeze.
The sample does not show what exactly I am doing in my app but I tried to demonstrate what issue I am facing. When you run the program you will see the TableView with two columns 1. Name and 2. Progress. On start-up Name will will be "Before" for each row whereas the you will see the progress bar running. I have added delay of 1 second in updating cell values and stop progress bar.
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.ProgressBarTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.StackPaneBuilder;
import javafx.stage.Stage;
public class UpdateTableView extends Application {
private TableView<Person> personTable = new TableView<>();
private TableColumn colName = new TableColumn<>("Name");
private TableColumn colProgressBar = new TableColumn("Progress Bar");
@Override
public void start(Stage primaryStage) {
showDialog(primaryStage);
colName.setCellValueFactory(new PropertyValueFactory("name"));
colProgressBar.setCellValueFactory(new PropertyValueFactory("progressBar")); // "name" here is for just to render the column
colProgressBar.setCellFactory(ProgressBarTableCell.forTableColumn());
personTable.getColumns().addAll(colName, colProgressBar);
for (int i = 0; i < 10; i++) {
Person person = new Person();
person.setProgressBar(-1.0);
person.setName("Before" + i);
personTable.getItems().add(person);
}
Thread threadAction1 = new Thread() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(UpdateTableView.class.getName()).log(Level.SEVERE, null, ex);
}
ObservableList<Person> items = personTable.getItems();
for (int i = 0; i < items.size(); i++) {
Person person = items.get(i);
person.setName("After" + i);
person.setProgressBar(0.0);
}
}
};
threadAction1.start();
}
public void showDialog(Stage primaryStage) {
try {
StackPane root = StackPaneBuilder.create().children(personTable).build();
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
} catch (Exception ex) {
System.out.println("Exception caught while showing dialog" + ex.getMessage());
}
}
public static class Person {
private StringProperty name;
public void setName(String name) {
this.name = new SimpleStringProperty(name);
}
private DoubleProperty progressBar;
private Person() {
}
public double getProgressBar() {
return progressBar.get();
}
public void setProgressBar(double surname) {
this.progressBar = new SimpleDoubleProperty(surname);
}
public Person(String name, double surname) {
this.name = new SimpleStringProperty(name);
this.progressBar = new SimpleDoubleProperty(surname);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public DoubleProperty progressBarProperty() {
return progressBar;
}
}
public static void main(String[] args) {
launch(args);
}
}
You should have to update your
Person
class as given below :in
setter
methods you are creating new object ofname
&progressbar
each-time, so thatTableView
is not getting update.