I am trying to show the progress and the status of the each task. Each task represents by a row into TableView
. Each task executs parallel in each Thread
. Please refer image of TableView
.
For "Progress" TableColumn
I have set Cell Factory to render `ProgressBar".
public static class ProgressBarTableCell<S, T> extends TableCell<S, T> {
private final ProgressBar progressBar;
private ObservableValue<T> ov;
public ProgressBarTableCell() {
this.progressBar = new ProgressBar();
progressBar.setPrefHeight(23);
setAlignment(Pos.CENTER);
}
@Override
public void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (item == null) {
setGraphic(null);
setText(null);
} else {
if (item.toString().equalsIgnoreCase("Processing")) {
Platform.runLater(new Runnable() {
@Override
public void run() {
if (getGraphic() == null) {
setGraphic(progressBar);
progressBar.setProgress(-1);
} else {
ProgressBar objpProgressBar = (ProgressBar) getGraphic();
objpProgressBar.setProgress(-1);
}
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
});
} else {
Platform.runLater(new Runnable() {
@Override
public void run() {
if (getGraphic() == null) {
setGraphic(progressBar);
progressBar.setProgress(0);
} else {
ProgressBar objpProgressBar = (ProgressBar) getGraphic();
objpProgressBar.setProgress(0);
}
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
});
}
}
}
}
The TableView
was not showing updated status and progress of tasks, so I am running a thread periodically in background, which modifies TableView
when I call startUpdatingTableProgress() and stops when I call stopUpdatingTableProgress().
public void stopUpdatingTableProgress() {
keepUpdating = false;
}
public void startUpdatingTableProgress() {
keepUpdating = true;
TableProgressBarUpdator tpu = new TableProgressBarUpdator(table);
tpu.start();
}
class TableProgressBarUpdator implements Runnable {
TableView table;
public TableProgressBarUpdator(TableView fxtable) {
table = fxtable;
}
public void start() {
new Thread(this).start();
}
public void run() {
while (keepUpdating) {
try {
updateProgressbar();
Thread.sleep(1000);
} catch (Exception e) {
LogHandler.doErrorLogging("Error while updating tables cell", e);
}
}
LogHandler.doDebugLogging("Table process repainting is completed.");
}
private void updateProgressbar() throws Exception {
Platform.runLater(new Runnable() {
@Override
public void run() {
((TableColumn) table.getColumns().get(0)).setVisible(false);
((TableColumn) table.getColumns().get(0)).setVisible(true);
}
});
}
}
But now My JavaFX
app's UI freezes after consecutive times. Is there any alternative way to call updateProgressbar() in background thread that triggers automatically after specific time interval and do not freeze my JavaFX
App's UI?
I do not know whether I am on the right way to update status of tasks where each task runs in a separate thread. If I would like to implement this with the help of javafx.concurrent package
then can anybody show me some guidance or flow? What will go into the Task and what will go into Service Class? How I can schedule it to update progress bar? FYI: At a time only 5 threads allowed to execute parallel.
Edited -
according to suggestion of Mr. Andy Till I have updated my code but still no luck -
TableColumn tableColumn_Progress = new TableColumn("Progress");
tableColumn_Progress.setCellValueFactory(new PropertyValueFactory<QueueData, Double>("progressBar"));
tableColumn_Progress.setPrefWidth(100);
Callback<TableColumn<QueueData, Double>, TableCell<QueueData, Double>> attachmentCellFactory = //
new Callback<TableColumn<QueueData, Double>, TableCell<QueueData, Double>>() {
@Override
public TableCell call(final TableColumn param) {
final ProgressBarTableCell cell = new ProgressBarTableCell() {
@Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
}
};
return cell;
}
};
tableColumn_Progress.setCellFactory(attachmentCellFactory);
In QueueData Class -
DoubleProperty progressBar = null;
public DoubleProperty progressBarProperty() {
return progressBar;
}
public Double getprogressBar() {
return progressBar.get();
}
public void setprogressBar(Double sType) {
this.progressBar = new SimpleDoubleProperty(sType);
}
And not calling any background thread to update UI but no luck.
Your 'QueueData' class should have methods to set double property of existing progress, it seems you are creating new SimpleDoubleProperty each and every time on setting progress status in setprogressBar(Double sType) method.
Update this as -
public void setprogressBar(Double sType) {
this.progressBar.set(sType);
}
Just create object of progressBar once at start then update existing one.
As I understand your code you are flipping the visibility to trigger the updateItem method on the table cell? This means that any number of threads could be trying to change the visibility every second and repaint endlessly.
I know you are already quite far with your implementation but the JavaFX service class already implements a progress feature which you can update which would be much simpler than how you are doing it now.
It would be much simpler and efficient to have a progress double property which you update from your thread and bind this to the ProgressBar.progressProperty() so everything would automatically update. This is how the Service class works but it is easy to implement yourself.
Also make sure you are disposing your threads, this is easy to check. Debug in eclipse and in the debug perspective it will show you the list of threads, make sure it doesn't grow endlessly.
For scheduling a Runnable checkout the ScheduledExecutor class, you can easily create it by using Executors.newScheduledThreadPool(numOfThreads).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With