Asalas77
Asalas77

Reputation: 632

How to update TableView items outside JavaFX Thread

I have a table view that lists user's friends and I need to update it every 5 seconds with data that I retrieve from database.

This is the code I use:

Main.java
   private List<Friend> userFriends;

fx controller:

    ObservableList<FriendWrapper> friendList = FXCollections.observableList(
    new ArrayList<FriendWrapper>());

private void updateFriendList() {
    new Thread(new Runnable() {
        public void run() {
            while (Params.loggedUser != null) {
                Main.setUserFriends(Params.dao.listUserFriends(Params.loggedUser));
                friendList.clear();
                for (Friend friend : Main.getUserFriends()) {
                    friendList.add(new FriendWrapper(friend.getFriendName(), friend.getOnline(), friend.getFriendId(), friend.getWelcomeMessage()));
                }
                Params.dao.updateOnlineStatus(Params.loggedUser, 3);
                try {
                    Thread.sleep(1000 * 5); 
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }, "updateFriendList").start();
}

Friend is database model. FriendWrapper is object used for table rows.

however I get IllegalStateException: Not on FX application thread on line friendList.clear();

How can I change the items of TableView from a thread running in the background?

Upvotes: 3

Views: 3548

Answers (2)

eckig
eckig

Reputation: 11134

Instead of a quick Platform.runLater() hack, you should probably make use of the Task class:

protected class LoadFriendsTask extends Task<List<FriendWrapper>>
{

    @Override
    protected List<FriendWrapper> call() throws Exception {

        List<Friend> database = new ArrayList<>(); //TODO fetch from DB
        List<FriendWrapper> result = new ArrayList<>();
        //TODO fill from database in result
        return result;
    }

    @Override
    protected void succeeded() {
        getTableView().getItems().setAll(getValue());
    }

}

You can launch this one as a Thread, for example:

new Thread(new LoadFriendsTask()).start()

For further reference:

Upvotes: 10

Vikas Tiwari
Vikas Tiwari

Reputation: 367

Use this...

Platform.runLater(new Runnable() {
    @Override
    public void run() {

    }
});

Upvotes: 3

Related Questions