0

I am trying to write a Battleship program using Java Swing and currently I have a class that makes two grids. I am trying to find out the location of which button was clicked so I can use this later to place shots etc... Unfortunately I am having a fair bit of trouble with this.

I have got the object to print out every thing that is in it by using the actionPerformed method but I only want the grid[x][y]. How do I go about this?

Thanks in advance for any help.

package testapp;

/**
 *
 * @author Craig
 */
import javax.swing.JFrame;
import javax.swing.*;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.*;
import java.awt.event.*;
import javax.swing.border.Border;

public class menu extends JPanel implements ActionListener{
        JButton[][] grid;
        TextField text = new TextField(20);

    public menu(int width, int length) {


        Border playerBorder = BorderFactory.createTitledBorder("Player");
        Border comBorder = BorderFactory.createTitledBorder("Com");


        JPanel player = new JPanel();
        player.setBorder(playerBorder);// set border round player grid 
        player.setLayout(new GridLayout(4,4));

        grid=new JButton[width][length]; //allocate the size of grid
        for(int y=0; y<length; y++){
            for(int x=0; x<width; x++){
                grid[x][y]=new JButton(); //creates new button    
                player.add(grid[x][y]); //adds button to grid
                grid[x][y].setBackground(Color.BLUE);//sets grid background colour
                grid[x][y].setPreferredSize(new Dimension(40, 40));//sets each grid buttons dimensions
                add(text);
                grid[x][y].addActionListener(this);
            }
        }

        JPanel com = new JPanel();
        com.setBorder(comBorder);// set border round com grid        
        com.setLayout(new GridLayout(4,4));
        grid=new JButton[width][length]; //allocate the size of grid
        for(int y=0; y<length; y++){
            for(int x=0; x<width; x++){
                grid[x][y]=new JButton(); //creates new button
                com.add(grid[x][y]); //adds button to grid
                grid[x][y].setBackground(Color.BLUE);//sets grid background colour
                grid[x][y].setPreferredSize(new Dimension(40, 40));//sets each grid buttons dimensions
            }
        }        

        //this.setLayout(new FlowLayout());
        this.add(player);
        this.add(com);

}
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        if (source instanceof JButton) {
            JButton btn = (JButton)source;
            text.setText("IN THE BOX ");
        }

    }

}
  • Just loop through the grid just like you added them and check if the grid[x][y] button == `source` – Paul Samsotha Jan 29 '14 at 15:35
  • 1
    [This question](http://stackoverflow.com/q/21346281/877472) popped up a couple of days ago which I think is pretty similar to your situation (if not exact). There was some debate about whether that OP's solution was appropriate, but the answer from Trashgod has a lot of good information. Ultimately, the OP's solution in their question might be one way to solve the problem. – Paul Richter Jan 29 '14 at 15:39
  • Thanks will have a look – user3249467 Jan 29 '14 at 15:42
  • 2
    Also consider [MVC](http://stackoverflow.com/a/3072979/230513). – trashgod Jan 29 '14 at 17:17

1 Answers1

1

There are different options. Extending JButton should IMHO be the last resort, and hardly ever necessary. Looping through the grid[][] array and checking whether they are the source of the respective event may be OK. But another (IMHO simple and elegant) solution is to use anonymous listeners:

// Where the grid buttons are created:
....
grid[x][y].addActionListener(createActionListener(x, y));


private ActionListener createActionListener(final int x, final int y)
{
    return new ActionListener()
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            clickedButton(x, y);
        }
    };
}

private void clickedButton(int x, int y)
{
    System.out.println("Clicked "+x+" "+y);
}

EDIT: Again, in form of a http://sscce.org/ (you could have created one, then I could have integrated my answer in your example...)

/**
 *
 * @author Craig and me :D
 */
import javax.swing.JFrame;
import javax.swing.*;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.*;
import java.awt.event.*;
import javax.swing.border.Border;

public class menu extends JPanel {

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new menu(4,4));
        f.setLocationRelativeTo(null);
        f.pack();
        f.setVisible(true);
    }

    JButton[][] grid;
    TextField text = new TextField(20);

    public menu(int width, int length) {


        Border playerBorder = BorderFactory.createTitledBorder("Player");
        Border comBorder = BorderFactory.createTitledBorder("Com");


        JPanel player = new JPanel();
        player.setBorder(playerBorder);// set border round player grid 
        player.setLayout(new GridLayout(4,4));

        grid=new JButton[width][length]; //allocate the size of grid
        for(int y=0; y<length; y++){
            for(int x=0; x<width; x++){
                grid[x][y]=new JButton(); //creates new button    
                player.add(grid[x][y]); //adds button to grid
                grid[x][y].setBackground(Color.BLUE);//sets grid background colour
                grid[x][y].setPreferredSize(new Dimension(40, 40));//sets each grid buttons dimensions
                add(text);
                grid[x][y].addActionListener(
                    createActionListener(x, y, "Player"));
            }
        }

        JPanel com = new JPanel();
        com.setBorder(comBorder);// set border round com grid        
        com.setLayout(new GridLayout(4,4));
        grid=new JButton[width][length]; //allocate the size of grid
        for(int y=0; y<length; y++){
            for(int x=0; x<width; x++){
                grid[x][y]=new JButton(); //creates new button
                com.add(grid[x][y]); //adds button to grid
                grid[x][y].setBackground(Color.BLUE);//sets grid background colour
                grid[x][y].setPreferredSize(new Dimension(40, 40));//sets each grid buttons dimensions
                grid[x][y].addActionListener(
                    createActionListener(x, y, "Computer"));
            }
        }        

        //this.setLayout(new FlowLayout());
        this.add(player);
        this.add(com);

    }
    private ActionListener createActionListener(
        final int x, final int y, final String name)
    {
        return new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                clickedButton(x, y, name);
            }
        };
    }

    private void clickedButton(int x, int y, String name)
    {
        System.out.println("Clicked "+x+" "+y+" for "+name);
    }
}
Marco13
  • 53,703
  • 9
  • 80
  • 159
  • Hi, how would I go about implementing this as I get errors at the moment such as: at the class name I get [menu is not abstract and does not override abstract method] and where I create the method private ActionListener I get [Illegal start of expression]. Sorry if these are really simple questions, just stuck – user3249467 Jan 29 '14 at 19:38