Tomasz Mularczyk
Tomasz Mularczyk

Reputation: 36179

ListView, Selecting items by double click

I have a main window where user can select program features by clicking on ListView item. However even if he clicks totally outside the Items(white arrow) program still fires up "Number Generator" feature. I dont like that.

enter image description here

public class MainRootController2 extends Controller implements Initializable {

    @FXML
    StackPane stackPane;
    @FXML
    ListView<String> listView;
    private ObservableList<String> list;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        //making a list and setting a background
        list = FXCollections.observableArrayList("Number Generator", "Cards");
        listView.setBackground(new Background(new BackgroundImage(new Image("MainRootBackground.jpg"),
                BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT,
                BackgroundPosition.CENTER, BackgroundSize.DEFAULT)));
        listView.setItems(list);
        listView.getSelectionModel().clearSelection();
    }

    @Override
    public Pane getMainPane() {
        return stackPane;
    }

    /************************ EVENTS *************************/
    @FXML
    private void listViewMouseDoubleClicked(MouseEvent e){
        if(e.getClickCount() > 1){
            String s = listView.getSelectionModel().getSelectedItem();

            switch(s){
                case "Number Generator":
                    ChangeTheRoot change = new ChangeTheRoot();
                    if( change.initialize(Main.primaryStage, true, Main.NUMBER_GENERATOR_ROOT, "Number Generator", true, new NumberGeneratorController()) == false)
                        Dialogs.create().title("Error").masthead(null).message("Couldn't load the components!").showInformation();

                    change.doFadingTransition(stackPane, Main.fadeOutMillis, Main.fadeInMillis, true);
                    break;

                default:
                    break;
            }
        }
    }

}

EDIT.... fixed version:

public class MainRootController2 extends Controller implements Initializable {

    @FXML
    StackPane stackPane;
    @FXML
    ListView<String> listView;
    private ObservableList<String> list;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        //making a list and setting a background
        list = FXCollections.observableArrayList("Number Generator", "Cards");

        listView.setBackground(new Background(new BackgroundImage(new Image("MainRootBackground.jpg"),
                BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT,
                BackgroundPosition.CENTER, BackgroundSize.DEFAULT)));
        listView.setItems(list);
        listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
                                    @Override 
                                    public ListCell<String> call(ListView<String> list) {
                                        return new MouseClickListCell();
                                    }

        });
        listView.getSelectionModel().clearSelection();
    }

    @Override
    public Pane getMainPane() {
        return stackPane;
    }

    /************************ EVENTS *************************/
    private void fireUpTheFeature(String name){
        String s = listView.getSelectionModel().getSelectedItem();

        switch(s){
            case "Number Generator":
                ChangeTheRoot change = new ChangeTheRoot();
                if( change.initialize(Main.primaryStage, true, Main.NUMBER_GENERATOR_ROOT, "Number Generator", true, new NumberGeneratorController()) == false)
                    Dialogs.create().title("Error").masthead(null).message("Couldn't load the components!").showInformation();

                change.doFadingTransition(stackPane, Main.fadeOutMillis, Main.fadeInMillis, true);
                break;
            case "Cards":
                break;
            default:
                break;
        }

    }

    public class MouseClickListCell extends ListCell<String>
    {
        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);

            if(empty) {
                setText(null);
                setOnMouseClicked(null);
            }
            else {
                setText(item.toString());
                setOnMouseClicked(new EventHandler<MouseEvent>() {

                    @Override
                    public void handle(MouseEvent event) {
                        if(event.getClickCount() > 1){
                            fireUpTheFeature(getItem());
                        }
                    }
                });
            }
        }
    }
}

Upvotes: 2

Views: 3914

Answers (1)

eckig
eckig

Reputation: 11134

I do not see your FXML file, but from your naming I can guess that your controllers method private void listViewMouseDoubleClicked(MouseEvent e) is fired whenever your ListView gets clicked.

This event gets fired whenever a user clicks anywhere in the area of the ListView. What you want is to remove that onMouseClicked handler and move that code into your ListCell renderer.

If you attach the mouse listeners only to non-empty cells your code will only be triggered when a ListCell gets clicked.

For example:

public static class MouseClickListCell<T> extends ListCell<T>
{
    @Override
    protected void updateItem(T item, boolean empty) {
        super.updateItem(item, empty);

        if(empty) {
            setText(null);
            setOnMouseClicked(null);
        }
        else {
            setText(item.toString());
            setOnMouseClicked(ev -> doMagic());
        }
    }
}

Upvotes: 5

Related Questions