-1

I am trying to make a chess program where I have an 8x8 array of JPanels which all require an addMouseListener but in this addMouseListener I need to make use of the index of that array for it to work, like this:

panels[0][0].addMouseListener(new MouseAdapter() {

        public void mousePressed(MouseEvent e) {
            panels[0][0].setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
        }

        public void mouseReleased(MouseEvent e) {

        }
    });

Since I have 64 JPanels that means I need to copy this 63 times and possible changes need to be copied as well. Is there any better, more efficient way to achieve this?

borisjo
  • 158
  • 1
  • 16
  • 1
    1) *"Since I have 64 JPanels"* Use `JButton` components instead of the panels, use an `ActionListener` instead of the ``MouseListener`, and a factory method to add the listener to each button. .2) See also [Making a robust, resizable Swing Chess GUI](http://stackoverflow.com/q/21142686/418556). – Andrew Thompson May 06 '17 at 22:01

3 Answers3

3

Since I have 64 JPanels that means I need to copy this 63 times

You can write a generic listener

MouseListener ml = new MouseAdapter()
{
    @Override
    public void mousePressed(MouseEvent e)
    {
        JPanel panel = (JPanel)e.getSource();
        panel.setBorder(...);
    }
};

Then in your looping code you just do:

panels[?][?].addMouseListener( ml );

You should always attempt to write generic listeners so the code can be reused.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • This looks great but I think it still won't work since I directly need the indices in the code. I call a method within the mousePressed() method which takes in two integers, the row and the column which are the indices of that JPanel. Any idea how to fix this? – borisjo May 06 '17 at 21:38
  • I now perform a for loop within the mousePressed() method where I look for when an element of my panels array equals the (JPanel)e.getSource() and then pass on the row and col integers. It seems to be working but I was wondering whether you could stress if this is correct or not. – borisjo May 06 '17 at 21:51
  • 1
    @borisverwoerd, `This looks great` - well why don't you try it??? Why do you think you need the row/column? – camickr May 06 '17 at 22:57
  • `I call a method within the mousePressed() method` - Well that should be part of the original question. `I now perform a for loop` - I would say a simple loop is better than creating 64 MouseListeners. – camickr May 06 '17 at 23:07
2

You should use a loop for this:

for (int r = 0; r < panels.length; ++r) {
    for (int c = 0; c < panels[r].length; ++c) {
        // Do this to fix the "must be final" error:
        final int row = r;
        final int col = c;
        panels[row][col].addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                panels[row][col].setBorder(.....);
            }
            // ..... more
        });
    }
}

However, there are a few other additional ways to go about this. One is that you could write a class which saves the location of the panel:

class MyMouseListener extends MouseAdapter {
    int panelRow;
    int panelCol;

    MyMouseListener(int panelRow, int panelCol) {
        this.panelRow = panelRow;
        this.panelCol = panelCol;
    }
    //.....
}

That is basically what the example using an anonymous class does behind the scenes. You could also save a reference to the panel itself.

Or you can use the getSource() method on the MouseEvent:

@Override
public void mousePressed(MouseEvent e) {
    JPanel panelWhichWasClicked = (JPanel) e.getSource();
    // .....
}

In that case, you only need 1 mouse listener which you can add to every panel.

Radiodef
  • 37,180
  • 14
  • 90
  • 125
  • The first doesn't work and I know since I have tried it. The error I get is that the variables `row` and `col` need to be final. – borisjo May 06 '17 at 21:40
  • See my edit for how to fix that. That's just an oversight on my part. They changed how that works in Java 8 and for some reason I was thinking it wasn't necessary. – Radiodef May 06 '17 at 21:49
0

When you have an array you must take different approach.

First your class should implement MouseListener which has 5 abstract methods but you are probably interested in mouseClicked:

public class Example implements MouseListener{

@Override
public void mouseClicked(MouseEvent e) {
     JPanel panel = (JPanel) e.getSource(); // finding which panel is clicked on
}

@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
}  

Then somewhere inside your class you will do:

for(int i = 0; i < panels.length; i++){
     for(int j = 0; j < panels[0].length; j++){
         panels[0][0].addMouseListener(this);
     }
}
FilipRistic
  • 2,661
  • 4
  • 22
  • 31