如何将 imageview 绑定到数组索引 mvvm javafx

how to bind imageview to array index mvvm javafx

我目前正尝试在 JavaFX 中编写 BlackJack 程序,我使用 ImageViews 来显示卡片。我有一个播放器模型,它有一个由我的 Card class.

中的字符串和卡片组成的 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) returns 存储在括号中数字索引处的字符串 (0)。

希望有人能帮忙?这是我第一次使用 MVVM 并使用 JavaFX 制作更复杂的程序。谢谢。

不确定我会有多大帮助,但我只用一张这样的图片做了类似的事情:

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

经理形象

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

所以在你的情况下,我想直接为每张卡片放置一个对象元素会更容易 然后选择

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

回答你的问题,你需要先让cards可观察:

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

然后您可以创建一个 Binding,它总是 returns 您地图中的第一个项目,如下所示:

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 class,但任何时候你需要一组固定的常量,你应该使用枚举:

花色 class:

enum Suit { 
    CLUB, DIAMOND, HEART, SPADE 
}

排名class:

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

卡片class:

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

现在,您可以用 Card 获得 Image 而无需使用 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