单击时取消选择javafx ListView上的项目 [英] Deselect an item on an javafx ListView on click

查看:367
本文介绍了单击时取消选择javafx ListView上的项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using a ListView control in a JavaFX application. It is set for MULTIPLE selection mode. I know as a user, I can Ctrl-Click an item to deselect it, but this is not intuitive enough for my users. I want a way to click a second time to deselect it. In other words click once - select; click selected item and it becomes unselected.

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

I've tried using both a ChangeListener and an onMouseClicked event. Neither works very well. Below are code snippets of each.

ChangeListener:

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

effect - first item in the list is NEVER selected. I click on it and it stays unclicked. No effect on items 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项。

No effect, since I'm not sure how to get the index of the one I just clicked. Being hard coded, this simply disallows of ever selecting item 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);
        }
    }
});


推荐答案

更改JavaFX中控件的行为非常困难 - API中当前实际上没有钩子进入行为类。

Changing the behavior of controls in JavaFX is pretty difficult - there are really no hooks currently in the API into the behavior classes.

以下似乎可行,方法是在列表中注册一个事件过滤器,直接实现选择行为,并使用该事件。

The following seems to work, by registering an event filter with the cells in the list, implementing the selection behavior directly, and consuming the event.

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

It feels a bit fragile though (what if a future release decided to implement the default behavior on mouse clicked, instead of mouse pressed, for example; or perhaps better, what if a future release decided to add additional functionality handled by mouse events). So use this solution with a bit of a "buyer beware" notice attached.

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 上有一个很好的工具提示,向他们解释如何使用它......

Obviously you know your users better than I, but I might prefer just to have a nice tooltip on the ListView explaining to them how to use it...

这篇关于单击时取消选择javafx ListView上的项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆