如何在JavaFX Thread之外更新TableView项

时间:2015-02-11 11:35:43

标签: java multithreading exception javafx

我有一个列出用户朋友的表视图,我需要每隔5秒使用从数据库中检索的数据更新它。

这是我使用的代码:

Main.java
   private List<Friend> userFriends;

fx控制器:

    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是数据库模型。 FriendWrapper是用于表行的对象。

然而我在IllegalStateException: Not on FX application thread

上获得了friendList.clear();

如何从后台运行的线程更改TableView的项目?

2 个答案:

答案 0 :(得分:10)

您可能应该使用Task类,而不是快速Platform.runLater()黑客:

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());
    }

}

您可以将此作为Thread启动,例如:

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

供进一步参考:

答案 1 :(得分:3)

使用此...

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

    }
});