私は最小限の、再現性の例を生成するために自分のコードをリファクタリングしています。
問題 - 私はパネルからカードを削除することはできませんよ(私は問題が発生したコードにコメントしている、クラス「ClearCardEventListener」を参照してください)。
以下の完全なコード。
フォルダ=プログラムを実行する前に、あなたはダウンロードする必要があります単一の画像が必要になりますし、リソースに追加https://ibb.co/MNccGS0
- プログラムを実行します。
- 「カードを追加」ボタンをクリックします(これはパネル上の2心の画像アイコンが追加されます)
「クリアカード」ボタンをクリックします(これは私がパネルからカードを削除することができませんでしだ問題で、です)
package debug.debug; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; public class App extends JFrame { public static void main(String[] args) { App app = new App(); Insets insets = app.getInsets(); app.setSize(300 + insets.left + insets.right, 300 + insets.top + insets.bottom); } JPanel panel; JButton clearCardButton; JButton addCardButton; List<Card> playerCards = new ArrayList<Card> (); Deck deck = new Deck(); public App() { setTitle("BlackJack Game"); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); panel = new JPanel(); add(panel); panel.setLayout(null); addCardButton = new JButton("Add card"); clearCardButton = new JButton("Clear card"); panel.add(addCardButton); panel.add(clearCardButton); addCardButton.addActionListener(new AddCardEventListener(this, this.deck)); clearCardButton.addActionListener(new ClearCardEventListener(this, this.deck)); addCardButton.setBounds(150, 50, addCardButton.getPreferredSize().width, addCardButton.getPreferredSize().height); clearCardButton.setBounds(150, 100, clearCardButton.getPreferredSize().width, clearCardButton.getPreferredSize().height); } public JPanel getPanel() { return panel; } public void addPlayerCard(Card card) { playerCards.add(card); } public List<Card> getPlayerCards() { return playerCards; } public List<JLabel> getPlayerCardLabels() { List<JLabel> playerCardLabels = new ArrayList<JLabel> (); for (int i = 0; i<this.getPlayerCards().size(); i++) { playerCardLabels.add(this.getPlayerCards().get(i).getCardLabel()); } return playerCardLabels; } } class AddCardEventListener implements ActionListener { private App app; private Deck deck; AddCardEventListener(App app, Deck deck) { this.app = app; this.deck = deck; } public void actionPerformed(ActionEvent arg0) { // Player gets a card app.addPlayerCard(deck.getCard()); // Display that player's card app.getPanel() .add(app.getPlayerCards().get(0).getCardLabel()).setBounds(0, 0, 72, 96); } } class ClearCardEventListener implements ActionListener { private App app; private Deck deck; ClearCardEventListener(App app, Deck deck) { this.app = app; this.deck = deck; } public void actionPerformed(ActionEvent arg0) { System.out.println("DEBUG: " + app.getPlayerCards().get(0).getCardLabel()); /*** * * NOT ABLE TO REMOVE CARD, WHY ??? * */ app.getPlayerCards().get(0).getCardLabel().setIcon(null); app.getPlayerCards().get(0).getCardLabel().revalidate(); app.getPlayerCards().get(0).getCardLabel().repaint(); app.getPanel().remove(app.getPlayerCards().get(0).getCardLabel()); } } class Card { private String suit; private String rank; private int value; public void setSuit(String suit) { this.suit = suit; } public void setRank(String rank) { this.rank = rank; } public void setValue(int value) { this.value = value; } public String getSuit() { return suit; } public String getRank() { return rank; } public int getValue() { return value; } // Hardcoded for debugging, so every card image is a 2 of hearts public JLabel getCardLabel() { return new JLabel(new ImageIcon(getClass() .getResource("/cards/2h.png"))); } } class Deck { private final String RANKS[] = { "Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" }; private final String SUITS[] = { "Spades", "Hearts", "Diamonds", "Clubs" }; private Card[] deck; static private int cardPosition = 0; public Deck() { deck(); // Create the deck shuffle(); // shuffle the deck } public Card[] deck() { deck = new Card[52]; for (int x = 0; x<deck.length; x++) { String rankTemp = RANKS[x % 13]; String suitTemp = SUITS[x / 13]; deck[x] = new Card(); deck[x].setRank(rankTemp); deck[x].setSuit(suitTemp); deck[x].setValue((x % 13) + 1); if (deck[x].getValue() > 10) deck[x].setValue(10); else if (deck[x].getValue() == 1) deck[x].setValue(11); } return deck; } public void shuffle() { Collections.shuffle(Arrays.asList(deck())); } public Card[] getDeck() { return deck; } public Card getCard() { return deck[cardPosition++]; } }
問題#1
あなたが呼び出すたびにCard#getCardLabel
、新しい作成されたJLabel
インスタンスを...
class Card {
// Hardcoded for debugging, so every card image is a 2 of hearts
public JLabel getCardLabel() {
return new JLabel(new ImageIcon(getClass()
.getResource("/cards/2h.png")));
}
}
この手段あなたが行うときに...
app.getPanel().add(app.getPlayerCards().get(0).getCardLabel()).setBounds(0, 0, 72, 96);
そして...
System.out.println("DEBUG: " + app.getPlayerCards().get(0).getCardLabel());
そして...
app.getPlayerCards().get(0).getCardLabel().setIcon(null);
app.getPlayerCards().get(0).getCardLabel().revalidate();
app.getPlayerCards().get(0).getCardLabel().repaint();
app.getPanel().remove(app.getPlayerCards().get(0).getCardLabel());
各呼び出しは、実際の新しいインスタンスを作成しているJLabel
ので、画面上の1には、変更しようとしているものとは何の関係もありません。
だから、代わりに、あなたは、Card#getCardLabel
ONE作成する必要がありますJLabel
ONCEだけ、これはまた、「遅延ロード」として知られているが...
class Card {
private JLabel label;
//...
// Hardcoded for debugging, so every card image is a 2 of hearts
public JLabel getCardLabel() {
if (label == null) {
// Simple image for demonstration purposes
BufferedImage img = new BufferedImage(100, 150, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, 100, 150);
g2d.setColor(Color.RED);
g2d.drawLine(0, 0, 100, 150);
g2d.drawLine(100, 0, 0, 150);
g2d.dispose();
label = new JLabel(new ImageIcon(img));
}
return label;
}
}
問題#2
Swingは、それ自体の中に、コンポーネントを追加または削除することを、レイアウトや塗料のパスをトリガしない手段、(OK、それは「最適化」です)怠惰です。これは、UIへの大規模な変更を加えることができるように行われていない、それは非常に遅くなり、それぞれの変更を、更新しようとしています。
追加またはコンポーネントを削除すると、あなたも呼び出す必要があることを、この手段repaint
新しいペイントパストリガーする(私もお勧めしたいのrevalidate
が、あなたのために何かをするつもりはないので、あなたは、任意のレイアウトマネージャを使用していません)
app.getPanel().remove(app.getPlayerCards().get(0).getCardLabel());
app.getPanel().repaint();