循环删除JButtons

时间:2016-03-12 00:39:54

标签: java arrays swing jbutton indexoutofboundsexception

我正在做一个TicTacToe程序,现在我正在使用菜单来改变电路板的大小(从3x3到9x9)我需要在添加新的按钮之前删除当前使用的按钮。在尝试删除它们时循环,我收到此错误:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3
    at TicTacToe$menuItem.actionPerformed(TicTacToe.java:84)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
    at java.awt.Component.processMouseEvent(Component.java:6535)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6300)
    at java.awt.Container.processEvent(Container.java:2236)
    at java.awt.Component.dispatchEventImpl(Component.java:4891)
    at java.awt.Container.dispatchEventImpl(Container.java:2294)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
    at java.awt.Container.dispatchEventImpl(Container.java:2280)
    at java.awt.Window.dispatchEventImpl(Window.java:2750)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.awt.EventQueue$4.run(EventQueue.java:729)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Process finished with exit code 0

这是代码(需要导入的所有东西,我只是没有将其粘贴)

public class TicTacToe extends JFrame{

public enum Space{EMPTY, X_SPACE, O_SPACE}
public enum Winner{PLAYER, COMPUTER, NEITHER}

int size;
Button button[][];
Space board[][];
int weight[][];
menuItem item[];

ImageIcon X = new ImageIcon(this.getClass().getResource("X.png"));
ImageIcon O = new ImageIcon(this.getClass().getResource("O.png"));
JPanel panel = new JPanel();


public TicTacToe(int s) {
    // Initialize window properties
    super("Tic Tac Toe");
    boardSize(s);
    item = new menuItem[7];
    clearBoard();
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(500, 500);
    setResizable(false);
    setLocationRelativeTo(null);
    panel.setLayout(new GridLayout(s, s));

    JMenuBar menubar = new JMenuBar();
    this.setJMenuBar(menubar);

    JMenu menu = new JMenu("Set Size");
    menubar.add(menu);

    for(int i=0; i<item.length; i++){
        item[i] = new menuItem(this, i+3, menu);
    }

    add(panel);
    setVisible(true);
    initWeight(); // Adds priority initialized in initWeight
}

public class Button extends JButton implements ActionListener {
    int row, col;
    TicTacToe ttt;
    public Button(TicTacToe t, int r, int c){
        ttt = t;
        row = r;
        col = c;
        this.addActionListener(this); // Adds the action listener to the buttons(this)
    }
    public void actionPerformed(ActionEvent e){
        // Displays move after event is found
        ttt.enterMove(row, col);
        displayWinner();
    }
}

public class menuItem extends JMenuItem implements ActionListener{
    int size;
    TicTacToe ttt;
    public menuItem(TicTacToe t,int s, JMenu menu){
        ttt = t;
        size = s;
        setText(s+"x"+s);
        menu.add(this);
        this.addActionListener(this);
    }
    public void actionPerformed(ActionEvent e){
        int s = size;
        for(int i=0; i < s; i++){
            for(int j=0; j < s; j++){
                ttt.panel.remove(button[i][j]);
            }
        }
        ttt.boardSize(size);
    }
}

public void addButtons(int s){
    s = size;
    for(int i = 0; i < s; i++)
    {
        for(int j = 0; j < s; j++)
        {
            board[i][j] = Space.EMPTY;
            button[i][j] = new Button(this, i, j);
            panel.add(button[i][j]);
        }
    }
}

public void displayWinner() {
    Space winner = getWinner();
    String msg;
    if(winner == Space.X_SPACE)
        msg = "Congratulations. You beat a bot smartass.\n Would you like to play again?";
    else if(winner == Space.O_SPACE)
        msg = "Wow... You just lost against a random number generator... You suck.\n Do you want redemption?";
    else
        return;

    int playAgain = JOptionPane.showConfirmDialog(this, msg, "Play Again", JOptionPane.YES_NO_OPTION); // Creates the window asking to play again

    if(playAgain == JOptionPane.YES_OPTION)
        clearBoard();
    else
        System.exit(0);
}

public void newGame(){
    for(int i = 0; i < size; i++){
        for(int j=0; j < size; j++) {
            board[i][j] = Space.EMPTY;
        }
    }
}

public boolean enterMove(int i, int j) {
    boolean goodMove = false;
    if(board[i][j] == Space.EMPTY){
        board[i][j] = Space.X_SPACE;
        goodMove = true;
    }else{
        JOptionPane.showMessageDialog(this, "Invalid Move", "Error", JOptionPane.ERROR_MESSAGE);
    }
    if(goodMove)
        updateBoard();

    if(getWinner() == Space.EMPTY && goodMove){
        computerMove();
        updateBoard();
    }
    return goodMove;
}

public void boardSize(int s) {
    size = s;
    button = new Button[size][size];
    board = new Space[size][size];
    weight = new int[size][size];
    addButtons(s);
    clearBoard();
    newGame();
}

public void initWeight(){
    //Corners
    weight[0][0] = 2;
    weight[0][size -1] = 2;
    weight[size-1][0] = 2;
    weight[size-1][size-1] = 2;

    //Edges
    for(int i = 1; i < size-1; i++) {
        weight[i][0] = 1;
        weight[0][i] = 1;
        weight[size - 1][i] = 1;
        weight[i][size - 1] = 1;
    }

    //Center(s)
    for(int i=1; i < size-1; i++){
        for(int j=1; j < size-1; j++){
            if(weight[i][j] == 0)
                weight[i][j] = 3;
            else if(weight[j][i] == 0)
                weight[j][i] = 3;
        }
    }

}

public boolean computerMove() {
    int mi = size, mj = size;
    int w = 0;

    for(int i=0; i < size; i++){
        for(int j=0; j <size; j++){
            if(board[i][j] == Space.EMPTY){
                if(weight[i][j] > w){
                    w = weight[i][j];
                    mi = i;
                    mj = j;
                }
            }
        }
    }
    if(mi < size && mj < size){
        board[mi][mj] = Space.O_SPACE;
        return true;
    }
    return false;
}

public void clearBoard(){
    for(int i=0; i < size; i++){
        for(int j=0; j < size; j++) {
            board[i][j] = Space.EMPTY;
            button[i][j].setIcon(null);
        }
    }
}

public Space getWinner(){
    Space w = Space.EMPTY;

    // Check for winner horizontally and vertically
    boolean dwii=true, dwij=true;
    for(int i=0; i < size; i++){
        boolean hw=true, vw=true;
        for(int j=1; j < size; j++){
            if(board[i][0] != board[i][j])
                hw = false;
            if(board[0][i] != board[j][i])
                vw = false;
        }
        if(hw && board[i][0] != Space.EMPTY)
            w = board[i][0];
        if(vw && board[0][i] != Space.EMPTY)
            w = board[0][i];

        if(board[0][0] != board[i][i])
            dwii = false;
        if(board[0][size-1] != board[i][size-i-1])
            dwij = false;
    }
    if(dwii && board[0][0] != Space.EMPTY)
        w = board[0][0];
    if(dwij && board[0][size-1] != Space.EMPTY)
        w = board[0][size-1];

    return w;
}

public void updateBoard() {
    for (int i = 0; i < size; i++) {
        for(int j=0; j < size; j++) {
            if (board[i][j] == Space.O_SPACE)
                button[i][j].setIcon(O);
            else if (board[i][j] == Space.X_SPACE)
                button[i][j].setIcon(X);
        }
    }
}

public static void main(String[] args) { // all this does is run the window
    new TicTacToe(3);
}
}

这是给我带来麻烦的部分。

        public void actionPerformed(ActionEvent e){
    int s = size;
    for(int i=0; i < s; i++){
        for(int j=0; j < s; j++){
            ttt.panel.remove(button[i][j]);
        }
    }
    ttt.boardSize(size);
}
}

2 个答案:

答案 0 :(得分:1)

  

我需要在添加新按钮之前删除当前使用的按钮。

您可以在Container类上使用removeAll()方法。

这当然假设您创建了一个仅包含网格按钮的面板,这就是我设计GUI的方式。将组件分解为逻辑面板始终是个好主意。

答案 1 :(得分:0)

您似乎意外地修改了全局属性&#39; size&#39;在你的menuItem构造函数中。在这种情况下,&#39; size&#39;是> 3初始化menuItems后。