简体   繁体   中英

How do i add event handlers to checkboxes in a listview checkbox cell?

I am creating a list of cards that users can select from to start a game. Users select their cards by a checkbox next to the card name, and they are only allowed to select 10 cards. I want to be able to limit the number of checkboxes that can be selected by having an event handler get called when a checkbox is clicked and determine whether the checkbox is allowed to be clicked or not. How can i add an event handler to every checkbox to do this? If there is a better way, i am definitely open to suggestions. Here is my code where i setup the listview and the checkbox callback:

ListView<Card> cards;
Callback<Card, ObservableValue<Boolean>> checkBoxCallback = new Callback<Card, ObservableValue<Boolean>>() {
        @Override
        public BooleanProperty call(Card card) {
            return card.selectedProperty();
        }
    };

    StringConverter<Card> cardToStringConverter = new StringConverter<Card>() {
        @Override
        public Card fromString(String card) {
            try {
                return CardFactory.createCard(card);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        public String toString(Card card) {
            return card.toString();
        }

    };

    Callback<ListView<Card>, ListCell<Card>> listViewCallback = CheckBoxListCell.forListView(checkBoxCallback, cardToStringConverter);
    cards.setCellFactory(listViewCallback);
    cards.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Card>() {
        @Override
        public void changed(ObservableValue<? extends Card> obsValue,
                Card oldValue, Card newValue) {
            cardImageView.setImage(newValue.getCardImage());
        }
    });

The getSelectedProperty Callback parameter of CheckBoxListCell.forListView() is bound bidirectionally,

(meaning that the CheckBox in the cell will set/unset this property based on user interactions, and the CheckBox will reflect the state of the ObservableValue, if it changes externally).

Thereby adding a change listener to the Card.selectedProperty() may be more accurate, covering the external modification by both checkBoxes and other controls/setters.

final IntegerProperty count = new SimpleIntegerProperty(0);
Text text = new Text("-");
// Bind count to text, to show on scene.
text.textProperty().bind(count.asString());

ChangeListener listener = new ChangeListener<Boolean>() {
    @Override
    public void changed(final ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
        count.set(count.get() + (newValue ? 1 : -1));
        if (count.get() >= 10) {
            System.out.println("exceeded max limit");
            // Revert selection
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    ((BooleanProperty) observable).set(false);
                }
            });
        }
    }
};
for (final Card card : cards.getItems()) {
    card.selectedProperty().addListener(listener);
}

At the end of the user work, remove the listeners.

for (final Card card : cards.getItems()) {
    card.selectedProperty().removeListener(listener);
}

Alternatively, if you strictly want to add listeners to checkboxes only, you can create custom ListCell having checkboxes internally and set a ListView.cellFactory().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM