-1

I'm making a Chess Game in java and I have initialized the board with an array of black and white squares with the help of Swing and AWT. In a subclass (i.e. SetSquaresToClickable), I wanted the program to go through the squares array(which is a JPanel 2d array), and check if the square contains a piece(which is an ImageIcon in a JLabel). If the square does contain a piece, that square should have a MouseListener. But I can't seem to find the correct if statement to check and implement all of this.

package mainBoard;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SetSquaresToClickable {
    InitializeBoard initializeBoard=new InitializeBoard();      //different class accessed in this class to access components(i.e squares)
    JPanel[][] squares=initializeBoard.getSquares();

    SetSquaresToClickable() {
        for(int i=0;i<8;i++) {
            for(int j=0;j<8;j++) {
                if(squares[i][j].contains(new JLabel)) {     //checks if square contains a piece(does not work)
                    squares[i][j].addMouseListener(new MouseAdapter() {
                        @Override
                        public void mouseClicked(MouseEvent e) {
                            squares[i][j].setBackground(Color.BLUE);     //sets square color to blue on being clicked if square contains piece.
                        }
                    });
                }
            }
        }
    }

    public static void main(String[] args) {
        new SetSquaresToClickable();
    }
}

If someone could help me, that would be great. Thanks in advance.

Abra
  • 19,142
  • 7
  • 29
  • 41
  • 1
    1) Instead of labels & mouse listeners, use buttons & an action listeners. A button can be made to look exactly like a label, but has the advantage in that using an action listener, it can respond to both mouse and keyboard. See [Making a robust, resizable Swing Chess GUI](http://stackoverflow.com/q/21142686/418556) for an example of using buttons. 2) Create a model for the chess game & have a method that can reference the model and adjust the icons in the buttons to reflect the state of the model. (Instead of checking round the label (or button) components for which image icon they display. – Andrew Thompson May 11 '21 at 06:45
  • *If the square does contain a piece, that square should have a MouseListener* - there is no need to add a listener to each individual square. You can just add a MouseListener to your chess board. In the mousePressed event you search for the chess piece that was clicked. Check out: https://stackoverflow.com/questions/6811247/drawing-in-jlayeredpane-over-exising-jpanels/6811800#6811800 for a working example fo this approach. – camickr May 11 '21 at 14:34

3 Answers3

1

Call getComponents() on the JPanel and iterate over the result checking for instanceof JLabel.

Check whether a JPanel contains a JButton

Here's a convenient contains method that checks whether a container contains a certain class and returns either the component or null.

Component contains(Container container, Class klass) {
    for (Component component : container.getComponents()) {
        if (klass.isInstance(component)) {
            return component;
        }
    }
    return null;
}

Check if squares[i][j] contains a JLabel with:

if (contains(squares[i][j], JLabel.class) != null) {
Nathan Mills
  • 2,243
  • 2
  • 9
  • 15
  • 1
    If the other SO question (that you linked to) answers this question, doesn't that make this question a duplicate? – Abra May 11 '21 at 04:16
  • Should it be like this? if(squares[i][j].getComponents() instanceof JLabel) If so, the program shows an error saying these are inconvertible types; cannot cast java.awt.Component[] to javax.swing.JLabel . – Kayhan Kolhatkar May 13 '21 at 04:01
1

You haven't posted all your code so I'll assume that somewhere in your code, before you call method SetSquaresToClickable you add the JLabel (with the icon of the chess piece) to one of the JPanels in the array squares.

Class JPanel is a subclass of class java.awt.Container and class Container has method getComponents which returns an array of all the components in the JPanel. You can iterate through the elements in the array returned by method getComponents and search for a JLabel.

In the below code, I add a JLabel to a JPanel and then I call getComponents on the JPanel and I iterate through the returned array looking for a Component which is a JLabel (since all Swing components, like JLabel, are subclasses of Component).

JPanel panel = new JPanel();
JLabel label = new JLabel();
panel.add(label);
Component[] components = panel.getComponents();
boolean found = false;
for (Component component : components) {
    if (component instanceof JLabel) {
        found = true;
        break;
    }
}
if (found) {
    System.out.println("Label found.");
}
else {
    System.out.println("Label not found.");
}

Alternatively, you can use the stream API to search for a JLabel in the array of components.

java.util.Optional<Component> optionalLabel = java.util.Arrays.stream(panel.getComponents())
                                                              .filter(component -> component instanceof JLabel)
                                                              .findAny();
Abra
  • 19,142
  • 7
  • 29
  • 41
0

What you're looking for here is the "instanceof" keyword. It will tell you if any object is of the same type of a class! In other words, your if statement:

if(squares[i][j].contains(new JLabel))

Should be:

if(squares[i][j] instanceof JLabel)
  • In the code in the question, `squares` is an array of `JPanel`. I don't think your `if` condition will ever be true. – Abra May 11 '21 at 03:59