JavaFX:在不破坏选择模型的情况下在 ListView 中显示图像 问题我的代码Stack Overflow 上的旧解决方案示例我对解决方案的尝试结果我正在努力解决的问题

问题描述

问题

我想显示一个包含文本和图像的列表。我能够做到这一点,但选择模型很时髦。当我用鼠标选择列表中的一个项目时,似乎整个列表视图元素都被选中了。当我使用箭头键时,选择模型工作正常。

我的代码

在我的控制器中,我有 ObservableList<Game> gameList。 Game 类如下所示:

public class Game {
    private String name;
    private Image image;
}

Stack Overflow 上的旧解决方案示例

搜索有关如何显示图像和名称解决方案时,我发现了许多使用 setCellFactory 方法的 Stack Overflow 解决方案,如下面的代码片段:

listView.setCellFactory(param -> new ListCell<>() {
            private final ImageView imageView = new ImageView();
            @Override
            public void updateItem(String item,boolean empty) {
                if (empty) {
                    setText(null);
                    setGraphic(null);
                } else {
                    imageView.setimage(/*Some image*/);
                    setText(game.getName());
                    setGraphic(imageView);
                }
            }
        });

我对解决方案的尝试

但是,我要显示的图像存储在我的 ObservableList 中的 Game 对象中。根据我的理解,上面的 String item 参数是 Game objects toString 方法,但我想在制作自定义 ListCell 时访问整个 Game 对象。我尝试更改该解决方案以访问整个 Game 对象。这是我的代码目前的样子:

public class MyController implements Initializable {
    @FXML
    public ListView<Game> listView;

    public ObservableList<Game> gameList;

    @Override
    public void initialize(URL url,ResourceBundle resourceBundle) {
        gameList = FXCollections.observableList(/*List of games*/);
        listView.setItems(gameList);
        listView.setCellFactory(param -> new ListCell<>() {
            private final ImageView imageView = new ImageView();
            @Override
            public void updateItem(Game game,boolean empty) {
                if (empty) {
                    setText(null);
                    setGraphic(null);
                } else {
                    imageView.setimage(game.getimage());
                    setText(game.getName());
                    setGraphic(imageView);
                }
            }
        });
    }
}

结果

使用上面的代码,我可以在我的 ListView 中显示每个游戏及其名称

enter image description here

我正在努力解决的问题

列表完全按照我想要的方式显示,但选择模型似乎被破坏了。 我使用 listView.getSelectionModel().getSelectedItem();获取选定的游戏。当我使用鼠标选择一个项目时,上述方法返回 null。这是我左键单击列表中的“其他游戏”项目时的样子:

enter image description here

但是,我可以使用箭头键选择我想要的列表中的任何项目。当我这样做时,从我的 ObservableList 中选择的游戏被返回。

有人知道我如何解决这个问题吗?

解决方法

默认的 ListCell.updateItem(...) 方法处理选择等。所以你需要确保调用它。

来自documentation

非常重要,Cell 的子类覆盖 updateItem 方法正确...注意此代码示例中的两个重要 积分:

  1. 我们调用 super.updateItem(T,boolean) 方法。如果不这样做,则项目和空属性设置不正确,您将 最终可能会出现图形问题。
  2. ...

所以你需要:

listView.setCellFactory(param -> new ListCell<>() {
    private final ImageView imageView = new ImageView();
    @Override
    public void updateItem(Game game,boolean empty) {

       // call default implementation:
       super.updateItem(item,empty);

       if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            imageView.setImage(game.getImage());
            setText(game.getName());
            setGraphic(imageView);
        }
    }
});