【问题标题】:JavaFX: Display image in ListView without breaking selection modelJavaFX:在 ListView 中显示图像而不破坏选择模型
【发布时间】:2021-08-25 15:40:14
【问题描述】:

问题

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

我的代码

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

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

Stack Overflow 上的旧解决方案示例

在搜索如何显示图像和名称的解决方案时,我发现了许多使用setCellFactory 方法的 Stack Overflow 解决方案,例如下面的代码 sn-p:

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 对象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 中显示每个游戏及其名称。

我正在尝试解决的问题

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

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

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

【问题讨论】:

  • 您在原始列表单元格版本中忘记调用super.updateItem(...)

标签: java image listview javafx observablelist


【解决方案1】:

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

来自documentation:

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

  1. 我们调用 super.updateItem(T, boolean) 方法。如果不这样做,则 item 和 empty 属性设置不正确,您将 最终可能会出现图形问题。
  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);
        }
    }
});

【讨论】:

  • 谢谢!我想这里的重要教训是正确阅读文档。我查看了 ListView 的 documentation,但直接跳到了我正在使用的方法。阅读顶部的“自定义 ListView 视觉效果”部分会让我找到答案。
猜你喜欢
  • 2020-06-07
  • 2015-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-26
相关资源
最近更新 更多