Search code examples
javagrid-layout

How do I get coordinates of a JPanel in an 8x8 GridLayout?


Me and a buddy are making a chess game from scratch using Java for our AP Computer Science class, and we need to get the coordinates for the final square after the mouse is released. .getX() and .getY() give us the exact coordinates, but we want the grid coordinate. Like 5,4 or 3,2 (in chess, this would be e4 or c2). The definition classes are all working fine, we just need this part:

System.out.print(e.getX()+"  "+e.getY());
      Component c =  chessBoard.findComponentAt(e.getX(), e.getY());
      if (c instanceof JLabel){
          Container parent = c.getParent();
          parent.remove(0);
          parent.add( chessPiece );
      }
      else {
          Container parent = (Container)c;
          parent.add( chessPiece );
      }
      chessPiece.setVisible(true);
  }

Full implementation class is below. Thanks in advance!

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

public class ChessGame extends JFrame implements MouseListener, MouseMotionListener {
    private static final long serialVersionUID = 1L;//Serial ID for unique chess games
    JLayeredPane layeredPane;
  JPanel chessBoard;
  JLabel chessPiece;
  int xAdjustment;
  int yAdjustment;

  public ChessGame(){

      Board newGame = new Board();//Instantiate Board object w/ spots
      newGame.boardSetUp();
      Dimension boardSize = new Dimension(600, 600);//Instantiate Visual representation of Board.

      //  Use a Layered Pane for this this application
      layeredPane = new JLayeredPane();
      getContentPane().add(layeredPane);
      layeredPane.setPreferredSize(boardSize);
      layeredPane.addMouseListener(this);
      layeredPane.addMouseMotionListener(this);

      //Add a chess board to the Layered Pane 

      chessBoard = new JPanel();
      layeredPane.add(chessBoard, JLayeredPane.DEFAULT_LAYER);
      chessBoard.setLayout( new GridLayout(8, 8) );
      chessBoard.setPreferredSize( boardSize );
      chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);
      JLabel Vpiece = new JLabel();

      for (int i = 0; i < 64; i++) {
      JPanel square = new JPanel( new BorderLayout() );
      chessBoard.add( square );

      int row = (i / 8);

      if (row%2 == 0)
      square.setBackground( i % 2 == 0 ? Color.darkGray : Color.white );//Adjusting for First square
      else
      square.setBackground( i % 2 == 0 ? Color.white : Color.darkGray );//Setting colored boxes for chess board

      if(newGame.spotValues[row][i-(row*8)].piece!=null)
      {
        switch(newGame.spotValues[row][i-(row*8)].piece.name){
          case "Bishop":
              if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
                  Vpiece = new JLabel( new ImageIcon("resource/BishopW.png") );
              else
                  Vpiece = new JLabel( new ImageIcon("resource/BishopB.png") );
          break;

          case "King":
              if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
                  Vpiece = new JLabel( new ImageIcon("resource/KingW.png" ));
              else
                  Vpiece = new JLabel( new ImageIcon("resource/KingB.png" ));
          break;

          case "Queen":
              if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
                  Vpiece = new JLabel( new ImageIcon("resource/QueenW.png") );
              else
                  Vpiece = new JLabel( new ImageIcon("resource/QueenB.png") );
          break;

          case "Pawn":
              if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
                  Vpiece = new JLabel( new ImageIcon("resource/PawnW.png") );
              else
                  Vpiece = new JLabel( new ImageIcon("resource/PawnB.png") );
          break;

          case "Rook":
              if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
                  Vpiece = new JLabel( new ImageIcon("resource/RookW.png") );
              else
                  Vpiece = new JLabel( new ImageIcon("resource/RookB.png") );
          break;

          case "Knight":
              if(newGame.spotValues[row][i-(row*8)].piece.color.equals("White"))
                  Vpiece = new JLabel( new ImageIcon("resource/KnightW.png") );
              else
                  Vpiece = new JLabel( new ImageIcon("resource/KnightB.png") );
          break;
        }
        JPanel panel = (JPanel)chessBoard.getComponent(i);
        panel.add(Vpiece);
      }
    }

  }

      public void mousePressed(MouseEvent e){
          chessPiece = null;
          Component c =  chessBoard.findComponentAt(e.getX(), e.getY());


          if (c instanceof JPanel) 
          return; //makes sure no errors are given when pressed on a blank square

          Point parentLocation = c.getParent().getLocation(); //parentLocation is mouse pointer
          xAdjustment = parentLocation.x - e.getX();
          yAdjustment = parentLocation.y - e.getY();
          chessPiece = (JLabel)c;
          chessPiece.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
          chessPiece.setSize(chessPiece.getWidth(), chessPiece.getHeight());
          layeredPane.add(chessPiece, JLayeredPane.DRAG_LAYER);
          }

      //Move the chess piece around
      public void mouseDragged(MouseEvent me) {
          if (chessPiece == null) { //checks if square is blank or not
              return;
          }
          chessPiece.setLocation(me.getX() + xAdjustment, me.getY() + yAdjustment);
      }

          //Drop the chess piece back onto the chess board
      public void mouseReleased(MouseEvent e) {
          if(chessPiece == null) { //checks if square is blank or not
              return;
          }
          chessPiece.setVisible(false);
          /*
           * what are we doing below??
           * 
           * 
           */
          System.out.print(e.getX()+"  "+e.getY());
          Component c =  chessBoard.findComponentAt(e.getX(), e.getY()); //checks to see if there's a new piece at the new location
          if (c instanceof JLabel){
              Container parent = c.getParent();
              parent.remove(0);
              parent.add( chessPiece );
          }
          else {
              Container parent = (Container)c;
              parent.add( chessPiece );
          }
          chessPiece.setVisible(true);
      }
            /*
             * 
             * what are we doing above??
             * 
             */


      public void mouseClicked(MouseEvent e) {

      }
      public void mouseMoved(MouseEvent e) {
      }
      public void mouseEntered(MouseEvent e){

      }
      public void mouseExited(MouseEvent e) {

      }

      public static void main(String[] args) {
      JFrame frame = new ChessGame();
      frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE );
      frame.pack();
      frame.setResizable(true);
      frame.setLocationRelativeTo( null );
      frame.setVisible(true);
     }
}

Solution

  • As noted in comments, I would use a grid of JLabel, and add and remove icons, and would give my JLabel a client property value that corresponds to the appropriate row and column (file and rank in chess terminology). I would give my ChessBoard class two String constants to use when putting client properties in and when later extracting them:

    public static final String RANK = "rank";
    public static final String FILE = "file";
    

    You add the properties by simply calling putClientProperty(...) on the JLabel:

    label.putClientProperty(RANK, rank);
    label.putClientProperty(FILE, file);
    

    where rank and file are appropriate Strings.

    For example, please run this demo program to see what I mean:

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class SimpleChess extends JPanel {
        private ChessBoard chessBoard = new ChessBoard();
        private JTextField rankField = new JTextField(3);
        private JTextField fileField = new JTextField(3);
    
        public SimpleChess() {
            MyMouse myMouse = new MyMouse();
            chessBoard.addMouseListener(myMouse);
    
            rankField.setHorizontalAlignment(SwingConstants.CENTER);
            rankField.setFocusable(false);
            fileField.setHorizontalAlignment(SwingConstants.CENTER);
            fileField.setFocusable(false);
            JPanel topPanel = new JPanel();
            topPanel.add(new JLabel("Rank:"));
            topPanel.add(rankField);
            topPanel.add(Box.createHorizontalStrut(40));
            topPanel.add(new JLabel("File:"));
            topPanel.add(fileField);
    
            setLayout(new BorderLayout());
            add(topPanel, BorderLayout.PAGE_START);
            add(chessBoard, BorderLayout.CENTER);
        }
    
        class MyMouse extends MouseAdapter {
            @Override
            public void mousePressed(MouseEvent e) {
                if (e.getButton() != MouseEvent.BUTTON1) {
                    return;
                }
                Component c = chessBoard.getComponentAt(e.getPoint());
                if (!(c instanceof JLabel)) {
                    return;
                }
                JLabel cell = (JLabel) c;
                String rank = (String) cell.getClientProperty(ChessBoard.RANK);
                String file = (String) cell.getClientProperty(ChessBoard.FILE);
                // icon = cell.getIcon();
                rankField.setText(rank);
                fileField.setText(file);
            }
        }
    
        private static void createAndShowGui() {
            JFrame frame = new JFrame("Chess");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(new SimpleChess());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }
    
    @SuppressWarnings("serial")
    class ChessBoard extends JPanel {
        public static final String RANK = "rank";
        public static final String FILE = "file";
        private static final int ROWS = 8;
        private static final int COLS = 8;
        private static final Color COLOR_LIGHT = new Color(240, 201, 175);
        private static final Color COLOR_DARK = new Color(205, 133, 63);
        private static final Dimension CELL_SIZE = new Dimension(60, 60);
        private JLabel[][] chessTable = new JLabel[ROWS][COLS];
    
        public ChessBoard() {
            // create chess table
            setLayout(new GridLayout(ROWS, COLS));
            for (int i = 0; i < chessTable.length; i++) {
                for (int j = 0; j < chessTable[i].length; j++) {
                    String rank = String.valueOf((char) ('8' - i));
                    String file = String.valueOf((char) ('a' + j));
                    JLabel label = new JLabel();
                    label.setPreferredSize(CELL_SIZE);
                    label.setOpaque(true);
                    Color c = i % 2 == j % 2 ? COLOR_LIGHT : COLOR_DARK;
                    label.setBackground(c);
                    label.putClientProperty(RANK, rank);
                    label.putClientProperty(FILE, file);
                    chessTable[i][j] = label;
                    add(label);
                }
            }
        }
    }
    

    I was working on a more extensive version, one that moved Icons around, but haven't finished it yet....

    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Map;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class ChessLocation extends JPanel {
        public static final String RANK = "rank";
        public static final String FILE = "file";
        public static final String MOUSE_PRESS = "mouse press";
        public static final String PIECE_IMG_PATH = "https://upload.wikimedia.org"
             + "/wikipedia/commons/thumb/b/b2/Chess_Pieces_Sprite.svg" 
             + "/320px-Chess_Pieces_Sprite.svg.png";  // for smaller pieces
        //   + "/640px-Chess_Pieces_Sprite.svg.png"; // for larger pieces
        private static final int IMG_ROWS = 2;
        private static final int IMG_COLS = 6;
        private static final int ROWS = 8;
        private static final int COLS = 8;
        private static final Color COLOR_LIGHT = new Color(240, 201, 175);
        private static final Color COLOR_DARK = new Color(205, 133, 63);
        private Map<ChessPiece, Icon> pieceIconMap = new HashMap<>();
        private JLabel[][] chessTable = new JLabel[ROWS][COLS];
    
        public ChessLocation(BufferedImage img) {
            // get chess images and put into pieceIconMap
            int w = img.getWidth() / IMG_COLS;
            int h = img.getHeight() / IMG_ROWS;
            for (int row = 0; row < IMG_ROWS; row++) {
                int y = (row * img.getHeight()) / IMG_ROWS;
                for (int col = 0; col < IMG_COLS; col++) {
                    int x = (col * img.getWidth()) / IMG_COLS;
                    BufferedImage subImg = img.getSubimage(x, y, w, h);
                    Icon icon = new ImageIcon(subImg);
    
                    PieceColor color = PieceColor.values()[row];
                    PieceType type = PieceType.values()[col];
                    ChessPiece chessPiece = new ChessPiece(type, color);
                    pieceIconMap.put(chessPiece, icon);
                }
            }
    
            // create chess table
            setLayout(new GridLayout(ROWS, COLS));
            Dimension pieceSize = new Dimension(w, h);
            for (int i = 0; i < chessTable.length; i++) {
                for (int j = 0; j < chessTable[i].length; j++) {
                    String rank = String.valueOf((char) ('8' - i));
                    String file = String.valueOf((char) ('a' + j));
                    JLabel label = new JLabel();
                    label.setPreferredSize(pieceSize);
                    label.setOpaque(true);
                    Color c = i % 2 == j % 2 ? COLOR_LIGHT : COLOR_DARK;
                    label.setBackground(c);
                    label.putClientProperty(RANK, rank);
                    label.putClientProperty(FILE, file);
                    chessTable[i][j] = label;
                    add(label);
                }
            }
            resetBoard();
    
            MyMouse myMouse = new MyMouse();
            addMouseListener(myMouse);
            addMouseMotionListener(myMouse);
        }
    
        public void resetBoard() {
            for (JLabel[] row : chessTable) {
                for (JLabel cell : row) {
                    cell.setIcon(null);
                }
            }
            chessTable[0][0].setIcon(pieceIconMap.get(new ChessPiece(PieceType.ROOK, PieceColor.BLACK)));
            chessTable[0][7].setIcon(pieceIconMap.get(new ChessPiece(PieceType.ROOK, PieceColor.BLACK)));
            chessTable[7][0].setIcon(pieceIconMap.get(new ChessPiece(PieceType.ROOK, PieceColor.WHITE)));
            chessTable[7][7].setIcon(pieceIconMap.get(new ChessPiece(PieceType.ROOK, PieceColor.WHITE)));
    
            chessTable[0][1].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KNIGHT, PieceColor.BLACK)));
            chessTable[0][6].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KNIGHT, PieceColor.BLACK)));
            chessTable[7][1].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KNIGHT, PieceColor.WHITE)));
            chessTable[7][6].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KNIGHT, PieceColor.WHITE)));
    
            chessTable[0][2].setIcon(pieceIconMap.get(new ChessPiece(PieceType.BISHOP, PieceColor.BLACK)));
            chessTable[0][5].setIcon(pieceIconMap.get(new ChessPiece(PieceType.BISHOP, PieceColor.BLACK)));
            chessTable[7][2].setIcon(pieceIconMap.get(new ChessPiece(PieceType.BISHOP, PieceColor.WHITE)));
            chessTable[7][5].setIcon(pieceIconMap.get(new ChessPiece(PieceType.BISHOP, PieceColor.WHITE)));
    
            chessTable[0][3].setIcon(pieceIconMap.get(new ChessPiece(PieceType.QUEEN, PieceColor.BLACK)));
            chessTable[0][4].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KING, PieceColor.BLACK)));
            chessTable[7][3].setIcon(pieceIconMap.get(new ChessPiece(PieceType.QUEEN, PieceColor.WHITE)));
            chessTable[7][4].setIcon(pieceIconMap.get(new ChessPiece(PieceType.KING, PieceColor.WHITE)));
    
            // put in pawns
            for (int i = 0; i < PieceColor.values().length; i++) {
                PieceColor color = PieceColor.values()[i];
                ChessPiece piece = new ChessPiece(PieceType.PAWN, color);
                for (int j = 0; j < COLS; j++) {
                    int row = 6 - 5 * i;
                    chessTable[row][j].setIcon(pieceIconMap.get(piece));
                }
            }
        }
    
        private class MyMouse extends MouseAdapter {
            String rank = "";
            String file = "";
            Icon icon = null;
    
            @Override
            public void mousePressed(MouseEvent e) {
                if (e.getButton() != MouseEvent.BUTTON1) {
                    return;
                }
                rank = "";
                file = "";
                icon = null;
                Component c = getComponentAt(e.getPoint());
                if (!(c instanceof JLabel)) {
                    return;
                }
                JLabel cell = (JLabel) c;
                if (cell.getIcon() == null) {
                    return;
                }
                rank = (String) cell.getClientProperty(RANK);
                file = (String) cell.getClientProperty(FILE);
                icon = cell.getIcon();
                // cell.setIcon(null);
            }
        }
    
        private static void createAndShowGui() {
            BufferedImage img = null;
            try {
                URL imgUrl = new URL(PIECE_IMG_PATH);
                img = ImageIO.read(imgUrl);
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(-1);
            }
            ChessLocation chessLocation = new ChessLocation(img);
            JFrame frame = new JFrame("Chess");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(chessLocation);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }
    

    enum PieceColor {
        WHITE, BLACK
    }
    

    enum PieceType {
        KING(100), QUEEN(9), BISHOP(3), KNIGHT(3), ROOK(5), PAWN(1);
        private int value;
    
        private PieceType(int value) {
            this.value = value;
        }
    
        public int getValue() {
            return value;
        }
    }
    

    class ChessPiece {
        private PieceType type;
        private PieceColor color;
    
        public ChessPiece(PieceType type, PieceColor color) {
            this.type = type;
            this.color = color;
        }
    
        @Override
        public String toString() {
            return "ChessPiece [type=" + type + ", color=" + color + "]";
        }
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((color == null) ? 0 : color.hashCode());
            result = prime * result + ((type == null) ? 0 : type.hashCode());
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            ChessPiece other = (ChessPiece) obj;
            if (color != other.color)
                return false;
            if (type != other.type)
                return false;
            return true;
        }
    
    }