Mimicking CTRL+Click Multiple Selection in ListView using Javafx
Asked Answered
A

1

7

I'm trying to find different ways of selecting multiple items in a ListView. The GUI will be running on a touch screen monitor, So I won't be able to CTRL+Click. From researching through various past posts, I have been able to implement Multiple Selection via keeping all the selected items in an Array and then looping through it to get the final selections. The only problem I have with my code is that compared to a CTRL +click , the selection is done smoothly, where as my code leads to a type flickering every time a new item is selected. So basically the listView clears all the selections and then selects the correct ones. Is there a way to make this transition go smoothly? Would it be easier to mimic a touch to have CTRL+click effect?

selectedList = new int[totalTypes];//total number of item properties

for(int x=0; x<selectedList.length;x++){//0 = not selected, 1 = selected
    selectedList[x]=0;
}
testView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

    testView.setOnMouseClicked(new EventHandler<Event>(){
        @Override
        public void handle(Event event){
                if(selectedList[testView.getSelectionModel().getSelectedIndex()]==0){
                    selectedList[testView.getSelectionModel().getSelectedIndex()]=1;
                }
                else{
                    selectedList[testView.getSelectionModel().getSelectedIndex()]=0;
                }

                for(int x=0; x<selectedList.length;x++){
                    if(selectedList[x]==1){
                        testView.getSelectionModel().select(x); 
                    }
                    else{
                        testView.getSelectionModel().clearSelection(x);;
                    }
                }


        }

    });
Ambrosia answered 1/12, 2016 at 0:8 Comment(2)
seem you want to run it on a touch-enabled devices, you should use setOnTouchPressed instead setOnMouseClickedHist
the flash should caused by clear and reset action, I don't think it's necessary for a correct design.Hist
E
9

You could handle changing the selection when a user clicks a ListCell yourself instead of using the standard event handling:

@Override
public void start(Stage primaryStage) {
    ListView<Integer> listView = new ListView<>();
    listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
    listView.getItems().setAll(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    listView.addEventFilter(MouseEvent.MOUSE_PRESSED, evt -> {
        Node node = evt.getPickResult().getIntersectedNode();

        // go up from the target node until a list cell is found or it's clear
        // it was not a cell that was clicked
        while (node != null && node != listView && !(node instanceof ListCell)) {
            node = node.getParent();
        }

        // if is part of a cell or the cell,
        // handle event instead of using standard handling
        if (node instanceof ListCell) {
            // prevent further handling
            evt.consume();

            ListCell cell = (ListCell) node;
            ListView lv = cell.getListView();

            // focus the listview
            lv.requestFocus();

            if (!cell.isEmpty()) {
                // handle selection for non-empty cells
                int index = cell.getIndex();
                if (cell.isSelected()) {
                    lv.getSelectionModel().clearSelection(index);
                } else {
                    lv.getSelectionModel().select(index);
                }
            }
        }
    });

    Scene scene = new Scene(listView);

    primaryStage.setScene(scene);
    primaryStage.show();
}
Euchromosome answered 1/12, 2016 at 9:35 Comment(3)
This works flawlessly. Thank you! Out of curiosity, how does a node work here? I notice your assigning it to the cell. So does it act as the selected item per say?By the way I plan on using a touch screen monitor, So in my head i'm think the finger touch would be input as a mouse click? Or should I just change the event to a touch pressed? which then I cant get a node from.Ambrosia
@Ammar: MouseEvent.isSynthesized seems to indicate that touch events will trigger mouse events. I didn't test this though. How the code in the answer works is by using the descendant Node of the ListView (which could e.g. be a Text node in a ListCell) to try to find a ListCell as parent. If this can be done, then further event handling is stopped and the information from that ListCell is used to modify the selection. Otherwise no cell was clicked and the event is handled as usual...Euchromosome
Oh I see, makes more sense now. I appreciate your help!Ambrosia

© 2022 - 2024 — McMap. All rights reserved.