Reputation: 632
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
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
Reputation: 367
Use this...
Platform.runLater(new Runnable() {
@Override
public void run() {
}
});
Upvotes: 3