Как связать просмотр изображений с индексом массива mvvm javafx - PullRequest
1 голос
/ 20 апреля 2020

В настоящее время я пытаюсь запрограммировать BlackJack на JavaFX и использую ImageViews для отображения карт. У меня есть модель игрока, в которой есть LinkedHashMap Строк и карт из моего класса карт.

LinkedHashMap<String, Card> cards = new LinkedHashMap<>();

Строка всегда выглядит как «ACE-CLUB» или «SIX-HEART», потому что мои импортированные изображения также с таким именем ("ACE-CLUB.png") .

Теперь я не знаю, как мне привязать ImageView playerCardOne к первой позиции LinkedHashMap. Я думал о создании массива, в котором хранятся только строки LinkedHashMap, но тогда я все еще не знаю, как связать ImageView. Я думал, что это может выглядеть примерно так, но это не работает:

playerCardOne.imageProperty().bind(new Image("/cards/" + vm.getPlayerCard(0) + ".png"));

Метод getPlayerCard (0) возвращает строку, которая хранится в индексе числа в скобках (0).

Надеюсь, кто-нибудь может помочь? Я впервые использую MVVM и создаю более сложную программу с использованием JavaFX. Спасибо.

Ответы [ 2 ]

0 голосов
/ 20 апреля 2020

Отвечая на ваш вопрос, вы должны сначала сделать cards наблюдаемым:

ObservableMap<String, Card> cards = FXCollections.observableMap(new LinkedHashMap<>());

Затем вы можете создать Binding, который всегда возвращает первый элемент на вашей карте, например:

ObjectBinding<Image> firstImageBinding = Bindings.createObjectBinding(() -> {
    Iterator<Map.Entry<String, Card>> iterator = cards.entrySet().iterator();
    if (iterator.hasNext()) {
        return new Image("/cards/" + iterator.next().getKey() + ".png");
    }
    return null;
}, cards);

Наконец, вы можете связать его со свойством Image:

playerCardOne.imageProperty().bind(firstImageBinding);

Хотя это может сработать, как вы ожидаете, я думаю, вы можете сделать его лучше.

Сначала Я не знаю, как вы реализовали Card класс, но всякий раз, когда вам нужен фиксированный набор констант, вы должны использовать перечисления:

Класс костюма:

enum Suit { 
    CLUB, DIAMOND, HEART, SPADE 
}

Класс ранга:

enum Rank { 
    ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING 
}

Класс карты:

public class Card {
    private final Suit suit;
    private final Rank rank;

    public Card(Suit suit, Rank rank) {
        this.suit = suit;
        this.rank = rank;
    }

    public Suit getSuit() {
        return suit;
    }

    public Rank getRank() {
        return rank;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Card card = (Card) o;
        return suit == card.suit &&
                rank == card.rank;
    }

    @Override
    public int hashCode() {
        return Objects.hash(suit, rank);
    }

    @Override
    public String toString() {
        return String.format("%s %s", suit, rank);
    }
}

Теперь вы можете получить Image для Card без необходимости использовать Map<String, Card>:

public Image getImageForCard(Card card) {
    String url = String.format("/cards/%s-%s.png", card.getRank(), card.getSuit());
    return new Image(url);
}

Если вам всегда интересно изображение первой карты в List<Card>, вы можете получить его так:

ObservableList<Card> cards = FXCollections.observableArrayList();

ImageView playerCardOne = new ImageView();
ObjectBinding<Image> firstImageBinding = Bindings.createObjectBinding(() -> 
        cards.isEmpty() ? null : getImageForCard(cards.get(0)), cards);
playerCardOne.imageProperty().bind(firstImageBinding);

cards.add(new Card(Suit.CLUB, Rank.ACE));
// playerCardOne's image is now /cards/ACE-CLUB.png

cards.add(0, new Card(Suit.HEART, Rank.SIX));
// playerCardOne's image is now /cards/SIX-HEART.png
0 голосов
/ 20 апреля 2020

Не уверен, что я очень помогу, но я сделал нечто похожее только с одним изображением, подобным этому:

Bindings.bindBidirectional(imageView.imageProperty(),manager.getCurrentImage());

с изображением менеджера

public final ObjectProperty<Image> currentImage = new SimpleObjectProperty<>();

, поэтому в вашем если бы я предположил, что было бы проще напрямую поместить для каждой карты элемент Object, тогда go с

playerCardOne.imageProperty().bind(vm.getPlayerCard(0).getImage())
...