java - JavaFX:在 ListView 中显示图像而不破坏选择模型
问题描述
问题
我想显示一个包含文本和图像的列表。我能够做到这一点,但选择模型很时髦。当我用鼠标选择列表中的一个项目时,似乎选择了整个列表视图元素。当我使用箭头键时,选择模型工作正常。
我的代码
在我的控制器中,我有ObservableList<Game> gameList
. 游戏类如下所示:
public class Game {
private String name;
private Image image;
}
Stack Overflow 上旧解决方案的示例
在搜索有关如何显示图像和名称的解决方案时,我发现许多 Stack Overflow 解决方案都使用了setCellFactory
以下代码片段这样的方法:
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 中选择的游戏被返回。
有谁知道我该如何解决这个问题?
解决方案
ListCell.updateItem(...)
除其他外,默认方法处理选择。所以你需要确保调用它。
从文档中:
Cell 的子类正确覆盖 updateItem方法非常重要……请注意此代码示例中的两个重点:
- 我们调用 super.updateItem(T, boolean) 方法。如果不这样做,则 item 和 empty 属性设置不正确,您最终可能会遇到图形问题。
- ...
所以你需要:
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);
}
}
});
推荐阅读
- ruby-on-rails - ActiveMerchant Cybersource 授权错误原因 102
- python - 在连接两个以上的数组时,我没有得到连接的数组
- eclipse - 重新部署时 Eclipse 中的 Orika ClassCastException
- nearprotocol - 如何将状态更新存储在链下数据库中?
- javascript - 有没有办法计算 Typed.js 花费的全部时间?
- mongodb - 具有语言支持的 MongoDb 文本搜索
- python - 尝试在 python 3.9 中创建虚拟环境
- spring-boot - Spring Boot 连接到 Kafka Brokers
- python - 生成具有 n 个连续重复元素的排列
- c - 计算机中的十进制转二进制