当前位置: 首页 > 知识库问答 >
问题:

在javafx中刷新单个ListView项

伍皓
2023-03-14

你好,

我有一个问题,使ListView更新“良好”。这是一个包含一堆播放列表项的播放列表。基本上,当项的样式或内容发生变化时,我希望它在ListView中发生变化。当前,我刷新了整个列表,我猜这是可行的,但它似乎是一个很差(不清楚)的解决方案对我来说(它闪烁)。有没有一种方法可以刷新/重绘一个特定的物品?我还没找到。

    null
protected Playlist(List<PlaylistItem> list){
    ...

    // initialise the items
    backup = FXCollections.observableArrayList(list);
    setItems(backup);

    // Use a custom CellFactory
    setCellFactory(new Callback<ListView<PlaylistItem>, ListCell<PlaylistItem>>() {
        @Override
        public ListCell<PlaylistItem> call(ListView<PlaylistItem> list) {
            return new PlaylistCell();
        }
    });

    ...
}
private class PlaylistCell extends ListCell<PlaylistItem> {
    private PlaylistItem lastItem = null;
    private final BooleanProperty booleanProperty = new SimpleBooleanProperty(false);

    /** Add a listener to the boolean property upon construction */
    private PlaylistCell() {
        booleanProperty.addListener( new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                if (newValue) { updateItem(lastItem, lastItem == null); };
            }
        });
    }

    @Override
    public void updateItem(PlaylistItem item, boolean empty) {
        super.updateItem(item, empty);
        booleanProperty.set(false);

        if (lastItem != item){
            // remove the pointer if we change item
            if (lastItem != null && booleanProperty == lastItem.getBooleanProperty())
                lastItem.setBooleanProperty(null);
            // and attach it to the new item
            if (item != null)
                item.setBooleanProperty(booleanProperty);
        }

        // redraw the cell
        if (!empty && item != null) {
            lastItem = item;

            // current song in bold
            if (item.equals(current)) {
                setId("current-item");
            } else{
                setId(null);
            }

            // mark queued songs & update text
            if (queue.contains(item)) {
                int i = queue.indexOf(item);
                super.setText(item.toString() + "\t (" + (i + 1) + (i != queue.lastIndexOf(item) ? ", ...)": ')'));
            } else {
                super.setText(item.toString());
            }
        }

        // draw an empty cell
        else {
            lastItem = null;
            setText(null);
            setId(null);
        }

    }

}

共有1个答案

仇承志
2023-03-14

假设queue是要播放的队列中项目的observableList ,而current是表示当前播放的项目的objectproperty (或类似的东西),我认为您只需要类似的东西

private class PlaylistCell extends ListCell<PlaylistItem> {

    public PlaylistCell() {

        textProperty().bind(Bindings.createStringBinding(this::calculateText,
            itemProperty(), emptyProperty(), current, queue);
        idProperty().bind(Bindings
            .when(current.isEqualTo(itemProperty())
            .then("current-item")
            .otherwise(""));
    }

    private String calculateText() {
        if (isEmpty() || getItem() == null) return null ;

        PlaylistItem item = getItem();

        if (queue.contains(item)) {
            int index = queue.indexOf(item) ;
            boolean unique = index == queue.lastIndexOf(item);
            return String.format("%s (%d%s)", item ,index + 1, (unique ? "" : ", ..."));
        } else {
            return item.toString();
        }
    }
}

我建议使用CSSpseudoclass而不是操作ID:

private class PlaylistCell extends ListCell<PlaylistItem> {

    private final BooleanBinding isCurrent = current.isEqualTo(itemProperty());
    private final PseudoClass currentPC = PseudoClass.getPseudoClass("current");

    public PlaylistCell() {

        textProperty().bind(Bindings.createStringBinding(this::calculateText,
            itemProperty(), emptyProperty(), current, queue);
        isCurrent.addListener((obs, wasCurrent, isNowCurrent) -> 
            pseudoClassStateChanged(currentPC, isNowCurrent));
    }

    // ...
}

然后将CSS更改为使用选择器

.list-cell:current { /* ... */ }
#current-item { /* ... *. }
ObservableList<PlaylistItem> items = FXCollections.observableArrayList(
    item -> new Observable[] { current, queue /* , other properties the toString() depends on...*/ });

ListView<PlaylistItem> listView = new ListView<>();
listView.setItems(items);

后来呢

public class PlaylistCell extends ListCell<PlayListItem> {

    private final PseudoClass currentPC = PseudoClass.getPseudoClass("current");


    @Override
    protected void updateItem(PlaylistItem item, boolean empty) {

        pseudoClassStateChanged(currentPC, current.isEqualTo(item));

        if (empty) {
            setText(null);
        } else {
            if (queue.contains(item)) {
                int index = queue.indexOf(item) ;
                boolean unique = index == queue.lastIndexOf(item);
                return String.format("%s (%d%s)", item ,index + 1, (unique ? "" : ", ..."));
            } else {
                return item.toString();
            }
        }
    }
}
 类似资料:
  • 在JavaFX中,我怎么能让一个矩形闪烁到视图之外。 我正在制作一个单词搜索游戏,我有一个随机的2D数组。我正在将此数组打印到600x600画布上,如下所示: 我也有一个正方形绘制在同一画布上,就像这样: 这意味着我可以通过增加和来移动正方形。这给了:这个。 现在唯一的问题是,我需要一个矩形来闪烁,这样当选中时,下面的字母仍然可见。我该怎么做?我尝试将颜色设置为不透明,但这也会导致游戏板的其他部分

  • 我有Mainactive,它保存片段。我的一个片段(参与者)检查数据库中是否有任何内容。如果没有,则显示带有消息以添加数据的片段(空参与者列表)。如果是,它显示带有2个选项卡的TabHost片段,其中一个包含带有数据库条目的ListView片段(参与者列表)。有一个FAB按钮可以添加更多记录。添加另一条记录后如何刷新ListView?我不确定,因为TabHost不适用于我在应用程序中使用的Frag

  • 当我想更新JavaFX中的时,出现了一个问题。 调试很混乱,因为我找不到异常的原因。我在网上搜索了一下,但没有找到对我有用的东西。希望有人能帮我解决这个问题。

  • 问题内容: 我正在尝试创建一个程序来模拟使用Java和JavaFX解决Rubik’s Cube的问题。该场景具有一个文本框,该文本框将以正确的方式显示计算机所做的每一步。文本框旁边有一个展开的多维数据集,其中 应 显示该多维数据集的当前状态。 问题在于,GUI只会更新以显示移动列表,并且在所有进程的最后都显示多维数据集的状态。我已经浏览了文档,该站点上的其他问题,其他站点上的其他问题,但找不到任何

  • 我有课: 阅读了手册后,我明白了我们需要在FX线程中刷新UI。我已经使用了platform.runlater(),但是在流结束时UI变慢了。 为我糟糕的英语感到抱歉。