我试图创建一个ListView,其中每个单元格由Label和Button组成。当我的鼠标飞过细胞时,我想让按钮出现,当它飞出时我想消失。为此,我在ListCell对象上使用方法setOnMouseEntered(),但Button仅出现在第一个单元格中(添加到ObservableList的最新项目)
我的自定义ListCell类:
public class SubscribedTopicListCell extends ListCell<String> {
private final Label lSubscribedTopic = new Label();
private final Button btnUnsubscribe = new Button();
private static final ImageView ivBtnGraphic = new ImageView(new Image("resources/images/cross.png"));
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setGraphic(null);
if (!empty && item != null) {
lSubscribedTopic.setText(item);
btnUnsubscribe.setVisible(false);
btnUnsubscribe.setGraphic(ivBtnGraphic);
btnUnsubscribe.setBackground(Background.EMPTY);
btnUnsubscribe.setOnAction(e ->
MqttConnection.getInstance().unsubscribe(item)
);
this.setOnMouseEntered(e ->
btnUnsubscribe.setVisible(true)
);
this.setOnMouseExited(e ->
btnUnsubscribe.setVisible(false)
);
GridPane listCellPane = new GridPane();
listCellPane.add(lSubscribedTopic, 0, 0);
listCellPane.add(btnUnsubscribe, 1, 0);
ColumnConstraints col0 = new ColumnConstraints();
col0.setHalignment(HPos.LEFT);
ColumnConstraints col1 = new ColumnConstraints();
col1.setHalignment(HPos.RIGHT);
col1.setHgrow(Priority.ALWAYS);
listCellPane.getColumnConstraints().addAll(col0, col1);
setGraphic(listCellPane);
}
}
}
如何让它适用于每个细胞?
答案 0 :(得分:1)
只有一个单元格可以有一个按钮,因为您已经ImageView
静态。 ImageView
是Node
,每个节点只能在场景图中出现一次。通过使ImageView
静态,您尝试在多个位置强制使用相同的ImageView
到场景图中。当您在按钮上调用setGraphic(...)
时,图像视图会有效地从上一个按钮中删除,以便满足只能在场景图中使用一次的规则。 (我怀疑所有按钮都在那里,但只有一个有图形:因为没有文字而没有背景,其他按钮完全不可见,可能零维度。)
修复方法是使ImageView
成为实例变量。请注意,Image
不一个节点,多个ImageView
可以共享相同的Image
,因此您可以避免在内存中存储多个图像数据副本使Image
静态。
最后,虽然它不会真正改变功能,但每次调用updateItem()
时重新注册监听器都没有意义;你可以在构造函数中只执行一次。同样的布局:
public class SubscribedTopicListCell extends ListCell<String> {
private final Label lSubscribedTopic = new Label();
private final Button btnUnsubscribe = new Button();
private static final Image image = new Image("resources/images/cross.png");
private final ImageView ivBtnGraphic = new ImageView(image);
private final GridPane listCellPane = new GridPane();
public SubscribedTopicListCell() {
btnUnsubscribe.setOnAction(e ->
MqttConnection.getInstance().unsubscribe(getItem())
);
this.setOnMouseEntered(e ->
btnUnsubscribe.setVisible(true)
);
this.setOnMouseExited(e ->
btnUnsubscribe.setVisible(false)
);
listCellPane.add(lSubscribedTopic, 0, 0);
listCellPane.add(btnUnsubscribe, 1, 0);
ColumnConstraints col0 = new ColumnConstraints();
col0.setHalignment(HPos.LEFT);
ColumnConstraints col1 = new ColumnConstraints();
col1.setHalignment(HPos.RIGHT);
col1.setHgrow(Priority.ALWAYS);
listCellPane.getColumnConstraints().addAll(col0, col1);
btnUnsubscribe.setVisible(false);
btnUnsubscribe.setGraphic(ivBtnGraphic);
btnUnsubscribe.setBackground(Background.EMPTY);
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setGraphic(null);
if (!empty && item != null) {
lSubscribedTopic.setText(item);
setGraphic(listCellPane);
}
}
}