Java FX 如何在 ListView 中更改项目的样式

Java FX How to style an item in a ListView if changed

我有一个 ListView 个用户,可以是 on/off

我找到了一种根据某些条件设置每个单元格样式的方法:

friends.setCellFactory(lv -> new ListCell<String>() {
                @Override
                protected void updateItem(String friendname, boolean empty) {
                    super.updateItem(friendname, empty);
                    if (empty) {
                        setText(null);
                        setStyle("");
                    } else {
                        setText(friendname);
                        if (usersService.isOnline(friendname)) {
                            do stuf....
                        }
                    }
                }
});

是否有一种方法可以让我在每次用户打开或关闭时调用此方法?除了使用线程,因为我看到它每次调用时都会创建一个新列表...

创造一些你可以观察的东西,然后观察它...

例如如果您的 usersService 有一个 ObservableList<String> onlineUsers,其中包含所有在线用户的用户名列表,您可以:

friends.setCellFactory(lv -> {

    ListCell<String> cell = new ListCell<String>() {

        @Override
        protected void updateItem(String friendname, boolean empty) {
            super.updateItem(friendname, empty);
            if (empty) {
                setText(null);
                setStyle("");
            } else {
                setText(friendname);
            }
        }

    };

    cell.styleProperty().bind(new StringBinding() {
        { bind(cell.itemProperty(), usersService.getOnlineUsers()); }
        @Override
        protected String computeValue() {
            if (cell.getItem() == null) {
                return "" ;
            }
            if (usersService.getOnlineUsers().contains(cell.getItem())) {
                return "/* online style here */";
            }
            return "/* offline style here*/" ;
        }
    });

    return cell ;

});

然后每当在线用户列表发生变化时,单元格将相应更新。

您可以使用外部 CSS 文件和自定义 PseudoClass:

来简化此操作
PseudoClass online = PseudoClass.getPseudoClass("online");

friends.setCellFactory(lv -> {

    ListCell<String> cell = new ListCell<String>() {

        @Override
        protected void updateItem(String friendname, boolean empty) {
            super.updateItem(friendname, empty);
            setText(friendname);
        }

    };

    InvalidationListener listener = obs -> 
        cell.pseudoClassStateChanged(online, 
            cell.getItem() != null
            && usersService.getOnlineUsers().contains(cell.getItem()));
    cell.itemProperty().addListener(listener);
    usersService.getOnlineUsers().addListener(listener);

    return cell ;

});

然后在您的 CSS 文件中执行

.list-cell {
    /* offline style rules here */
}
.list-cell:online {
    /* online style rules here */
}