【问题标题】:How to update TableView items outside JavaFX Thread如何在 JavaFX 线程之外更新 TableView 项目
【发布时间】:2015-04-11 18:21:02
【问题描述】:

我有一个列出用户朋友的表格视图,我需要每 5 秒使用从数据库中检索到的数据对其进行更新。

这是我使用的代码:

Main.java
   private List<Friend> userFriends;

特效控制器:

    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 是用于表行的对象。

但是我在friendList.clear(); 在线得到IllegalStateException: Not on FX application thread

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

【问题讨论】:

    标签: java multithreading exception javafx


    【解决方案1】:

    使用这个...

    Platform.runLater(new Runnable() {
        @Override
        public void run() {
    
        }
    });
    
    【解决方案2】:

    您应该使用Task 类,而不是快速的Platform.runLater() hack:

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

    进一步参考:

    【讨论】:

    • call 方法的覆盖中,定义一个比Exception 更好的异常可能会更好。快速回忆一下,RuntimeException 扩展了 Exception,因此捕获 Exception 意味着您也捕获了所有未检查的异常。
    • @fge 是Tasks call()方法的默认签名。
    • 这并不意味着您不能指定更好的例外,实际上您应该。例如,Closeable 扩展了AutoCloseable,它指定抛出的异常是IOException,而不是Exception。或者您可以完全不指定任何例外。
    • @fge 你是对的。但是捕获所有内容也支持Tasks onFailed 钩子.. 取决于用例;)
    • @eckig 如何以固定的时间间隔循环启动它?
    猜你喜欢
    • 2017-07-22
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 2016-05-13
    • 2015-08-03
    相关资源
    最近更新 更多