如何在8x8 GridLayout中获取JPanel的坐标?

时间:2017-12-19 02:43:45

标签: java grid-layout

我和一个伙伴正在从头开始使用Java为我们的AP计算机科学课进行国际象棋游戏,我们需要在鼠标释放后获得最终方格的坐标。 .getX().getY()为我们提供了精确的坐标,但我们需要网格坐标。像5,4或3,2(在国际象棋中,这将是e4或c2)。定义类都运行正常,我们只需要这部分:

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

完整的实施课程如下。提前谢谢!

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

2 个答案:

答案 0 :(得分:1)

如评论中所述,我将使用JLabel网格,添加和删除图标,并为我的JLabel提供一个客户端属性值,该值对应于相应的行和列(国际象棋术语中的文件和排名)。我会给我的ChessBoard类两个String常量,以便在将客户端属性放入时以及稍后提取它们时使用:

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

只需在JLabel上调用putClientProperty(...)即可添加属性:

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

其中rank和file是合适的字符串。

例如,请运行此演示程序以查看我的意思:

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

我正在开发一个更广泛的版本,一个可以移动图标的版本,但还没有完成它......

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

}

答案 1 :(得分:0)

Java坐标系从左上角开始,坐标随着向下和向右的增加而增加。因此,对于任何width x height棋盘,预期的行和列间隔将是这样的:

// 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)
...

我建议您使用Map。在这里,我没有将以下代码段集成到您的代码中。然而,它基本上需要两个Double输入和输出棋盘单元,适用于棋盘的任何给定宽度和高度:

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()getY()应该返回Double。所以我相信一旦你理解了上面的代码,你就可以轻松地将它集成到你的项目中。它并不完美。我没有处理掉外情况。但必不可少的部分有效。