This discussion is archived
2 Replies Latest reply: Dec 18, 2012 8:16 AM by 942981 RSS

add change listener to hoverProperty of ListCell (not working)

942981 Newbie
Currently Being Moderated
In fact, adding any mouseEvent listener to a ListView results in nothing happening.
None of the LOGGER statements in the code below get printed out.

MyCustomListView extends ListView<MyObject>
public MyCustomListView() {

        hoveredItemProperty = new ReadOnlyObjectWrapper<>( null );
        setCellFactory( new Callback<ListView<MyObject>, ListCell<MyObject>>() {

            @Override
            public ListCell<MyObject> call(
                ListView<MyObject> arg0 ) {

                final ListCell<MyObject> listCell = new ListCell<>();
                listCell.setOnMouseReleased( new EventHandler<MouseEvent>() {
                    @Override
                    public void handle( MouseEvent event ) {
                         LOGGER.debug( "mouse in to {}", listCell );
                        hoveredItemProperty.set( listCell );
                    }
                } );
                listCell.setOnMouseEntered( new EventHandler<MouseEvent>() {
                    @Override
                    public void handle( MouseEvent event ) {
                        LOGGER.debug( "mouse in to {}", listCell );
                        hoveredItemProperty.set( listCell );
                    }
                } );
                listCell.hoverProperty().addListener(
                    new ChangeListener<Boolean>() {
                        @Override
                        public void changed(
                            ObservableValue<? extends Boolean> observable,
                            Boolean oldValue, Boolean newValue ) {
                            LOGGER.debug( "hovered: {}", newValue );
                            if ( newValue ) {
                                hoveredItemProperty.set( listCell );
                            }
                        }
                    } );
                return listCell;
            }

        } );

    }
Is there a way to listen to the hovered item in a ListView similarly to how we can listen to the selectedItemProperty through the SelectionModel?

Edited by: 939978 on Dec 17, 2012 12:12 PM
  • 1. Re: add change listener to hoverProperty of ListCell (not working)
    James_D Guru
    Currently Being Moderated
    Remember the ListCell is instantiated once (probably) and reused for each entry in the list. You need to hook into the item property of the Cell to know how to set your hoveredProperty.

    This shows two different ways, either of which will work:
    import javafx.application.Application;
    import javafx.beans.property.SimpleStringProperty;
    import javafx.beans.property.StringProperty;
    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    import javafx.event.EventHandler;
    import javafx.scene.Scene;
    import javafx.scene.control.Label;
    import javafx.scene.control.ListCell;
    import javafx.scene.control.ListView;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.BorderPaneBuilder;
    import javafx.stage.Stage;
    import javafx.util.Callback;
    
    public class ListViewHoverTest extends Application {
    
      @Override
      public void start(Stage primaryStage) {
        final ListView<String> list = new ListView<String>();
        list.getItems().addAll("Apples", "Oranges", "Bananas", "Pomegranates",
            "Mangoes");
        final StringProperty hoveredItem = new SimpleStringProperty(null);
        list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
          @Override
          public ListCell<String> call(ListView<String> listView) {
            final ListCell<String> listCell = new ListCell<String>() {
              @Override
              public void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                if (empty) {
                  setText(null);
                } else {
                  setText(item);
                }
              }
            };
    
            // Either of the following works:
            // register mouse listeners:
            listCell.setOnMouseEntered(new EventHandler<MouseEvent>() {
              @Override
              public void handle(MouseEvent event) {
                hoveredItem.set(listCell.getItem());
              }
            });
            listCell.setOnMouseExited(new EventHandler<MouseEvent>() {
              @Override
              public void handle(MouseEvent event) {
                hoveredItem.set(null);
              }
            });
    
            // or register a change listener with the hover property
            listCell.hoverProperty().addListener(new ChangeListener<Boolean>() {
              @Override
              public void changed(ObservableValue<? extends Boolean> observable,
                  Boolean oldValue, Boolean newValue) {
                if (newValue) {
                  hoveredItem.set(listCell.getItem());
                } else {
                  hoveredItem.set(null);
                }
              }
            });
    
            return listCell;
          }
        });
        Label label = new Label();
        label.textProperty().bind(hoveredItem);
        Scene scene = new Scene(BorderPaneBuilder.create().center(list)
            .bottom(label).build());
        primaryStage.setScene(scene);
        primaryStage.show();
      }
    
      public static void main(String[] args) {
        launch(args);
      }
    }
  • 2. Re: add change listener to hoverProperty of ListCell (not working)
    942981 Newbie
    Currently Being Moderated
    Thanks for the input.

    The problem on my side was that I was calling setCellFactory again from elsewhere in the program and overriding the work set up in my original post. Getting rid of that, my code now gives me access to the hovered cell. And with the getItem change you mentioned I can access the hovered item.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points