单击时取消选择javafx ListView上的项目

我在JavaFX应用程序中使用ListView控件。 它被设置为MULTIPLE选择模式。 我知道作为用户,我可以按住Ctrl键单击一个项目以取消选择它,但这对我的用户来说不够直观。 我想要一种方法来第二次点击取消选择它。 换句话说,点击一次 – 选择; 单击所选项目,它将被取消选中。

我尝试过使用ChangeListener和onMouseClicked事件。 两者都不是很好。 以下是每个代码段的代码片段。

的ChangeListener:

效果 – 列表中的第一项永远不会被选中。 我点击它并保持不被点击。 对项目2..n没有影响

listView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() { @Override public void changed(final ObservableValue observableValue, final SpecificAlgorithmData oldData, final SpecificAlgorithmData newData) { //if already selected then deselect it int selectedIndex = listView.getSelectionModel().getSelectedIndex(); System.out.println("selected " + selectedIndex); System.out.println("all selected" + listView.getSelectionModel().getSelectedIndices()); if (!selecting && !listView.getSelectionModel().getSelectedIndices().contains(selectedIndex)){ Iterator  iterator = listView.getSelectionModel().getSelectedIndices().iterator(); selecting = true; listView.getSelectionModel().select(-1);//deselect all while (iterator.hasNext()){ int index = iterator.next(); if (index!= selectedIndex){ listView.getSelectionModel().select(index); } } selecting = false; } } } 

的onClick:

没有效果,因为我不知道如何获得我刚刚点击的索引。 由于硬编码,这完全不允许选择第2项。

 listView.setOnMouseClicked(new EventHandler() { @Override public void handle(final MouseEvent mouseEvent) { int selectedItem = 2; //FIXME: How to I get the index of clicked item? if (listView.getSelectionModel().isSelected(selectedItem)){ listView.getSelectionModel().clearSelection(selectedItem); } } }); 

更改JavaFX中控件的行为非常困难 – API中当前实际上没有挂钩到行为类中。

通过向列表中的单元格注册事件filter,直接实现选择行为以及使用事件,以下似乎可行。

虽然感觉有点脆弱(例如,如果未来版本决定在鼠标点击时实现默认行为,而不是鼠标按下,或者更好,如果未来版本决定添加鼠标事件处理的其他function,该怎么办)。 因此,请使用此解决方案,并附上一些“买家提防”通知。

 import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.control.MultipleSelectionModel; import javafx.scene.control.SelectionMode; import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; public class DeselectableList extends Application { @Override public void start(Stage primaryStage) { ListView list = new ListView<>(); MultipleSelectionModel selectionModel = list.getSelectionModel(); selectionModel.setSelectionMode(SelectionMode.MULTIPLE); for (int i=1; i<=20; i++) { list.getItems().addAll("Item "+i); } list.setCellFactory(lv -> { ListCell cell = new ListCell<>(); cell.textProperty().bind(cell.itemProperty()); cell.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> { list.requestFocus(); if (! cell.isEmpty()) { int index = cell.getIndex(); if (selectionModel.getSelectedIndices().contains(index)) { selectionModel.clearSelection(index); } else { selectionModel.select(index); } event.consume(); } }); return cell ; }); BorderPane root = new BorderPane(list); Scene scene = new Scene(root, 150, 400); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } 

显然你比我知道你的用户更好,但我可能更喜欢在ListView上有一个很好的工具提示向他们解释如何使用它…