JPanelのからコンポーネントを削除することができません。

Zahidulイスラム教:

私は最小限の、再現性の例を生成するために自分のコードをリファクタリングしています。

問題 - 私はパネルからカードを削除することはできませんよ(私は問題が発生したコードにコメントしている、クラス「ClearCardEventListener」を参照してください)。

以下の完全なコード。

フォルダ=プログラムを実行する前に、あなたはダウンロードする必要があります単一の画像が必要になりますし、リソースに追加https://ibb.co/MNccGS0

  1. プログラムを実行します。
  2. 「カードを追加」ボタンをクリックします(これはパネル上の2心の画像アイコンが追加されます)
  3. 「クリアカード」ボタンをクリックします(これは私がパネルからカードを削除することができませんでしだ問題で、です)

    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#getCardLabelONE作成する必要がありますJLabelONCEだけ、これはまた、「遅延ロード」として知られているが...

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

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=339072&siteId=1