-2

There is a TableView with records, each of which corresponds to its own countdown. it is required to dynamically change the displayed time in the cell. In my case it should happen every second. There is a minimal reproducible example of my solution, but in my project with a database and several records - between iterations of "while", all records disappear for a split second and I see the blinking of the contents of the table. In addition, maybe, clearing the list and loading items into it is probably too resource-intensive for a simple real-time update of a single column. And maybe I shouldn't have used threads. What else can be done?

Table Controller

public class TableController {
    
    @FXML
    private TableColumn<taskEntry, String> nameColumn;

    @FXML
    private TableColumn<taskEntry, String> elapsedTimeColumn;

    @FXML
    private TableView<taskEntry> table;
    
    ObservableList<taskEntry> taskEntries = FXCollections.observableArrayList();

    @FXML
    private void initialize() {

        Thread thread = new UpdateThread();
        thread.start();
        
        nameColumn.setCellValueFactory(new PropertyValueFactory<taskEntry, String>("taskName"));
        elapsedTimeColumn.setCellValueFactory(new PropertyValueFactory<taskEntry, String>("elapsedTime"));
        table.setItems(taskEntries);
    }

    public class UpdateThread extends Thread {
        int i = 0;
        TaskEntry someEntry = new TaskEntry("Solve the problem");
        @Override
        public void run() {
            while (i < 60) {
                someEntry.setSecondsRemain(60 - i);
                taskEntries.clear();
                taskEntries.add(someEntry);
                i++;
                try {
                    UpdateThread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
}

Model


public class taskEntry {
    private String taskName;
    private int elapsedTime;

    public taskEntry(String taskName, int elapsedTime) {
        this.taskName = taskName;
        this.elapsedTime = elapsedTime;
    }

    public String getTaskName() {
        return taskName;
    }

    public void setTaskName(String taskName) {
        this.taskName = taskName;
    }

    public int getElapsedTime() {
        return elapsedTime;
    }

    public void setElapsedTime(int elapsedTime) {
        this.elapsedTime = elapsedTime;
    }
    
}
filippkos
  • 7
  • 4
  • repeating: [mcve] required.. and stick to java naming conventions NOW! that said: you __must not__ update any node in an active scenegraph from a background thead. Do some research on how to use concurrency in javafx, there are tons of tuturials and examples to work through – kleopatra Jun 04 '22 at 10:15
  • Use JavaFX properties for your `TaskEntry` class, so the table updates automatically (as well as using the animation API instead of background threads). – James_D Jun 04 '22 at 14:44
  • Also: [don't use `PropertyValueFactory`](https://stackoverflow.com/questions/72437983/why-should-i-avoid-using-propertyvaluefactory-in-javafx-and-what-should-i-use-i) – James_D Jun 04 '22 at 14:46

0 Answers0