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

时间:2014-05-13 04:16:31

标签: 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;
        }
    }
}

的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);
        }
    }
});

1 个答案:

答案 0 :(得分: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);
    }
}

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