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

Dom*_* D. 6 java javafx javafx-2

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

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

的ChangeListener:

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

listView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<SpecificAlgorithmData>() {
    @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 <Integer> 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

的onClick:

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

listView.setOnMouseClicked(new EventHandler<MouseEvent>() {
    @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);
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

Jam*_*s_D 7

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

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

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

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<String> list = new ListView<>();
        MultipleSelectionModel<String> selectionModel = list.getSelectionModel();
        selectionModel.setSelectionMode(SelectionMode.MULTIPLE);
        for (int i=1; i<=20; i++) {
            list.getItems().addAll("Item "+i);
        }
        list.setCellFactory(lv -> {
            ListCell<String> 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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