2 Replies Latest reply: Dec 18, 2012 10:16 AM by 942981 RSS

    add change listener to hoverProperty of ListCell (not working)

    942981
      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
          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
            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.