Search code examples
listviewjavafxselectionchangelistener

ListView selection listener: error no suitable method found for addListener(<anonymous ChangeListener<String>>)


this is about implementing a selection Listener to a ListView.

listView.setItems(FXCollections.observableList(content.getListContent()));
listView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() {
         @Override
        public void changed(ObservableValue<? extends String> observableValue, String s, String s2) {
                  System.out.println("Selected item: " + s2);
        }
    });

I get this error message:

error: no suitable method found for addListener(<anonymous ChangeListener<String>>)
    listView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() {
method Observable.addListener(InvalidationListener) is not applicable
  (argument mismatch; <anonymous ChangeListener<String>> cannot be converted to InvalidationListener)
method ObservableValue.addListener(ChangeListener<? super Warning>) is not applicable
  (argument mismatch; <anonymous ChangeListener<String>> cannot be converted to ChangeListener<? super Warning>)

I don't know how to fix this. Anybody can help? Thanks in advance.


Solution

  • I'm guessing from the error message that you declared the list view as

    private ListView<Warning> listView ;
    

    and that the return type of content.getContentList() is List<Warning> (or something that is a subinterface or implementation of that).

    ListView<T>.getSelectionModel() returns a MultipleSelectionModel<T> (see docs), so listView.getSelectionModel() is giving you a MultipleSelectionModel<Warning>.

    MultipleSelectionModel<T>.selectedItemProperty() returns a ReadOnlyObjectProperty<T> (see docs), so listView.getSelectionModel().selectedItemProperty() evaluates to a ReadOnlyObjectProperty<Warning>.

    Finally, ReadOnlyObjectProperty<T> inherits a addListener(ChangeListener<? super T>) method from ObservableValue<T> (docs), so you need to pass in a ChangeListener<T> where T is Warning or some superclass of it.

    So you need

    listView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Warning>() {
        @Override
        public void changed(ObservableValue<? extends Warning> observableValue, Warning s, Warning s2) {
            System.out.println("Selected item: " + s2);
        }
    });
    

    Note that using Java8 lambdas and type inference will allow you to sidestep the whole issue:

    listView.getSelectionModel().addListener((obs, oldValue, newValue) -> {
        System.out.println("Selected item: "+newValue);
    });
    

    If you use this, a decent IDE will also be able to infer that newValue is a Warning here, and give you access to its methods, etc.