JButtons 中的图标没有被删除?

Icons in JButtons not being removed?

我正在为 Java 游戏构建基于挥杆的 GUI。该游戏本质上是一个由自定义 Cell 对象组成的 4x4 网格,本质上是一个自定义 JButton。下面的代码

package gamePack;
import java.awt.Graphics;
import java.util.ArrayList;

import javax.swing.JButton;

public class Cell extends JButton {

int co_x = 0;
int co_y = 0;

  ArrayList<Players> current = new ArrayList <Players>();
}

ArrayList 允许我存储不同 Players 的对象。所有 Players 都继承自同一个 class,因此我实际上是在重新绘制单元格并根据 ArrayList 中的对象类型添加图标。每个单元格都有一个 ArrayList,因为每个单元格可以有多个 Players

GUI initialization:
package gamePack;

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;

import java.awt.Color;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.border.Border;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class StarFight {

    public JFrame frame;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    StarFight window = new StarFight();
                    window.frame.setVisible(true);


                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    /**
     * Create the application.
     */
    public StarFight() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setVisible(true);
        frame.setBounds(100, 100, 487, 349);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);

        final JPanel gamePanel = new JPanel();
        gamePanel.setBounds(0, 0, 365, 310);
        frame.getContentPane().add(gamePanel);
        int i = 4;
        int j = 4;
        final Cell[][] panelHolder = new Cell[i][j]; 
        gamePanel.setLayout(new GridLayout(4, 4, 0, 0));
        //91.25 x 77.5 rectangles

        Border border = BorderFactory.createLineBorder(Color.white);
        for(int m = 0; m < i; m++) {
            for(int n = 0; n < j; n++) {
                panelHolder[m][n] = new Cell();
                panelHolder[m][n].co_x = m;
                panelHolder[m][n].co_y= n;
                panelHolder[m][n].setBackground(Color.black);
                panelHolder[m][n].setEnabled(false);
                panelHolder[m][n].setBorder(border);
                gamePanel.add(panelHolder[m][n]);

            }
        }


        JPanel controlPanel = new JPanel();
        controlPanel.setBounds(375, 0, 86, 310);
        frame.getContentPane().add(controlPanel);
        controlPanel.setLayout(null);

        final JButton Move = new JButton("Move");
        Move.setEnabled(false);
        Move.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                panelHolder[0][0].current.clear();
                BattleCruiser q = new BattleCruiser();
                panelHolder[3][2].current.add(q);

                Redraw.draw(gamePanel, panelHolder);
            }
        });
        Move.setBounds(1, 82, 84, 65);
        controlPanel.add(Move);

        final JButton Undo = new JButton("Undo");
        Undo.setEnabled(false);
        Undo.setBounds(1, 158, 84, 65);
        controlPanel.add(Undo);

        JButton Exit = new JButton("Exit");

        Exit.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent arg0) {
                System.exit(0);
            }
        });
        Exit.setBounds(1, 234, 84, 65);
        controlPanel.add(Exit);

        final JButton btnStart = new JButton("Start");
        btnStart.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent arg0) {
                Move.setEnabled(true);
                Undo.setEnabled(true);
                btnStart.setEnabled(false);

                PlayChar p = new PlayChar();
                BattleCruiser q = new BattleCruiser();
                BattleStar s = new BattleStar();
                BattleShooter sh = new BattleShooter();

                panelHolder[0][0].current.add(p);


                Redraw.draw(gamePanel, panelHolder);
            }
        });
        btnStart.setBounds(1, 6, 84, 65);
        controlPanel.add(btnStart); 
    }
    }

单击“移动”按钮时游戏会发生变化。在这里,我在单击开始时添加了玩家的精灵,并调用了重绘方法。重绘方法如下:

package gamePack;

import java.awt.Color;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;


public class Redraw {



    public static void draw(JPanel gamePanel, Cell[][] panelHolder ){


        gamePanel.setBounds(0, 0, 365, 310);

        int i = 4;
        int j = 4;

        gamePanel.setLayout(new GridLayout(4, 4, 0, 0));
        //91.25 x 77.5 rectangles



        Border border = BorderFactory.createLineBorder(Color.white);
        for(int m = 0; m < i; m++) {
            for(int n = 0; n < j; n++) {
                panelHolder[m][n].setBackground(Color.black);
                panelHolder[m][n].setEnabled(false);
                panelHolder[m][n].setBorder(border);
                panelHolder[m][n].setIcon(null);

                for(Players p: panelHolder[m][n].current){
                    if(p instanceof PlayChar){
                        String arg = "Player.png";
                        ImageIcon icon = new ImageIcon(arg); 
                        JLabel label = new JLabel(); 
                        label.setIcon(icon); 
                        panelHolder[m][n].add(label);

                    } else if (p instanceof BattleStar) {
                        String arg = "BattleStar.png";
                        ImageIcon icon = new ImageIcon(arg); 
                        JLabel label = new JLabel(); 
                        label.setIcon(icon); 
                        panelHolder[m][n].add(label);
                    }   else if (p instanceof BattleCruiser){
                        String arg = "BattleCruiser.png";
                        ImageIcon icon = new ImageIcon(arg); 
                        JLabel label = new JLabel(); 
                        label.setIcon(icon); 
                        panelHolder[m][n].add(label);
                    } else if (p instanceof BattleShooter){
                        String arg = "BattleShooter.png";
                        ImageIcon icon = new ImageIcon(arg); 
                        JLabel label = new JLabel(); 
                        label.setIcon(icon); 
                        panelHolder[m][n].add(label);
                    } 
                }
            }
        }
        gamePanel.revalidate();
        gamePanel.repaint();
    }
}

重绘方法检查每个单元格中的ArrayList,然后适当添加一个图标。目前,当我单击“移动”时,它应该删除所有 JButton,然后使用适当的精灵将它们添加回来。

问题是,当我这样做时,即使在添加另一个精灵之前使用 current.clear(),0,0 位置的精灵仍然被绘制。单步执行代码显示未调用 PlayChar 对象的 if 语句,因此我必须假设它与重绘方法有关。我做错了什么吗?

编辑:根据反馈,我现在对其进行了更改,因此重绘功能不会替换 JButton,但会更改它们的属性。我还添加了它,以便在设置任何图标之前将每个图标设置为空,以确保将其删除。但是还是出现同样的问题

发现问题!感谢@faljbour

is there a reason why you are using a JLabel and calling add to set the icon on a JButton instead of using .setIcon(icon) directly?

这就是问题所在。该图像被设置为 JLabel,然后被添加,因此删除图标没有任何效果。

代码应为:

String arg = "Player.png";
ImageIcon icon = new ImageIcon(arg);  
panelHolder[m][n].setIcon(icon);