2

ユーザーがゲームを開始するために選択できるカードのリストを作成しています。ユーザーはカード名の横にあるチェックボックスでカードを選択し、10 枚のカードしか選択できません。チェックボックスがクリックされたときにイベントハンドラーを呼び出して、チェックボックスのクリックを許可するかどうかを決定することで、選択できるチェックボックスの数を制限できるようにしたいと考えています。これを行うには、すべてのチェックボックスにイベント ハンドラーを追加するにはどうすればよいですか? より良い方法があれば、私は間違いなく提案を受け入れます。リストビューとチェックボックスのコールバックを設定するコードは次のとおりです。

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());
        }
    });
4

1 に答える 1

3

の getSelectedPropertyCallbackパラメータCheckBoxListCell.forListView()は双方向にバインドされています。

(つまり、セル内の CheckBox はユーザーの操作に基づいてこのプロパティを設定/設定解除し、CheckBox は ObservableValue の状態が外部で変更された場合にそれを反映します)。

これにより、変更リスナーを に追加するCard.selectedProperty()と、より正確になり、checkBox と他のコントロール/セッターの両方による外部変更をカバーできます。

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

ユーザー作業の最後に、リスナーを削除します。

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

または、厳密にチェックボックスのみにリスナーを追加する場合は、内部にチェックボックスを持つカスタム ListCell を作成し、ListView.cellFactory() を設定できます。

于 2013-11-09T23:11:18.467 に答える