Narek Ohanyan
Narek Ohanyan

Reputation: 13

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);
     }
}

Upvotes: 1

Views: 1392

Answers (2)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

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;
    }

}

Upvotes: 1

Java coordinate system starts from the top left corner and coordinates increase as you go down and right. So for any width x height chess board expected row and column intervals would be something like this:

// X coordinates
A: 0.0 - (width / 8)
B: (width / 8) - (2 * width / 8) 
C: (2 * width / 8) - (3 * width / 8)
...

// Y coordinates
8: 0.0 - (width / 8)
7: (width / 8) - (2 * width / 8) 
6: (2 * width / 8) - (3 * width / 8)
...

I would suggest you to use Map. Here, I did not integrate the following snippet into your code. However it basically takes two Double inputs and outputs a chess board cell, works with any given width and height for the chess board:

import java.util.HashMap;
import java.util.Map;

public class chessCell {

static final int CELL_COUNT = 8;
// Dimensions
static final double HEIGHT = 600;
static final double WIDTH = 600;

static Map<String, String> columnAsLetter = new HashMap<String, String>(){{
    put( "8", "a");
    put( "7", "b");
    put( "6", "c");
    put( "5", "d");
    put( "4", "e");
    put( "3", "f");
    put( "2", "g");
    put( "1", "h");
}};

static Map<String, String> rows = new HashMap<String, String>(){{
    for(int i = 0; i < CELL_COUNT; i++) {
        put(Integer.toString(i + 1), (Double.toString(HEIGHT - (i + 1) * HEIGHT / 8 ) + "-" + Double.toString(HEIGHT - i * HEIGHT / 8)));
    }
}};

static Map<String, String> columns = new HashMap<String, String>(){{
    for(int i = 0; i < CELL_COUNT; i++) {
        put(Integer.toString(i + 1), (Double.toString(WIDTH - (i + 1) * WIDTH / 8 ) + "-" + Double.toString(WIDTH - i * WIDTH / 8)));
    }
}};


public static String coord2cellName(double x, double y) {
    String column = "";
    String row = "";
    for(int i = rows.size(); i > 0; i--) {
        if(x > Double.parseDouble(rows.get(Integer.toString(i)).split("-")[0]) && 
                x <= Double.parseDouble(rows.get(Integer.toString(i)).split("-")[1])){
            row = Integer.toString(i);
        }

        if(y > Double.parseDouble(columns.get(Integer.toString(i)).split("-")[0]) && 
                y <= Double.parseDouble(columns.get(Integer.toString(i)).split("-")[1])){
            column = columnAsLetter.get(Integer.toString(i));
        }

    }
    System.out.println(column + row);
    return column + row;
}


public static void main(String[] args) {
    // TODO Auto-generated method stub
    coord2cellName(125.0, 155.0); // outputs c7
    coord2cellName(24.0, 34.0); // outputs a8
    coord2cellName(32.0, 88.0); // outputs b8
    }

}

getX() and getY() should be returning Double. So I believe once you understand the code above you can easily integrate it into your project. It is not perfect. I didn't handle out-of-board situation. But the essential part works.

Upvotes: 0

Related Questions