Changing behavior of controls in JavaFX is generally difficult. The "proper" way to do this would be to create a new skin implementation, which involves a lot of work, and since the behavior classes are currently not public API would involve a lot of "reinventing the wheel". A reasonable hack is to intercept the mouse events before they are received by the default skin class, and to modify the selection accordingly. You can do this using an event filter, consuming the event to prevent the skin from receiving it:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
public class ListViewModifiedSelection extends Application {
@Override
public void start(Stage primaryStage) {
ListView<String> listView = new ListView<>();
listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
for (int i = 1 ; i <= 25 ; i++) {
listView.getItems().add("Item "+i);
}
listView.setCellFactory(lv -> {
ListCell<String> cell = new ListCell<String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : item);
}
};
cell.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
if (cell.isEmpty()) {
return ;
}
int index = cell.getIndex() ;
if (listView.getSelectionModel().getSelectedIndices().contains(index)) {
listView.getSelectionModel().clearSelection(index);
} else {
listView.getSelectionModel().select(index);
}
listView.requestFocus();
e.consume();
});
return cell ;
});
primaryStage.setScene(new Scene(listView, 250, 450));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Preventing the skin from receiving the mouse event is a something of a hack, and you do risk breaking existing functionality by doing that. An alternative and more robust solution might be to manage your own "selection" functionality using check boxes in the list cells, or something similar.