java - ListView 单元格上的 setOnMouseEntered/Exited

标签 java listview javafx

我正在尝试制作一个ListView,其中每个单元格都由一个标签和一个按钮组成。我想让按钮在鼠标飞过单元格时出现,并在鼠标飞出时消失。为此,我在 ListCell 对象上使用了 setOnMouseEntered() 方法,但按钮仅出现在第一个单元格(添加到 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);
        }
    }
}

如何使其适用于每个单元格?

最佳答案

只有一个单元格可以有按钮,因为您已将 ImageView 设为静态。 ImageViewNode ,并且每个节点在场景图中只能出现一次。通过将 ImageView 设为静态,您可以尝试将相同的 ImageView 强制放入场景图中的多个位置。当您在按钮上调用 setGraphic(...) 时, ImageView 实际上会从前一个按钮中删除,以满足它只能在场景图中使用一次的规则。 (我怀疑所有按钮确实都在那里,但只有一个有图形:因为没有文本,也没有背景,所以其他按钮完全不可见,可能是零维度。)

修复方法是将 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);
        }
    }
}

关于java - ListView 单元格上的 setOnMouseEntered/Exited,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35407554/

相关文章:

java - 使用 throws 关键字并在 main 中处理它,而不是在它发生的方法中处理它

java - iCal 同步可以在 Java 中使用吗?如何使用java连接ical服务器?

JavaFX:使用 -splash 选项启动时 useSystemMenuBar 出现问题

java - 如何强制 JavaFX 应用程序中的所有按钮使用我的自定义皮肤?

java - 如何在场景生成器中更改场景大小?

java - 如何在 CXF 中的根类型上覆盖驼峰命名法 (wadl2java)

javascript - SmartGWT 与 React.js : a good widget library for the latter?

java - 如何获取带有子字符串文本的真实数据文本?

winforms - 如何以编程方式更改其集合中的 ListView 项键?

android - 如何使 ListWheelScrollView 水平