如何扩展 JComponent 并使用它来编写自定义游戏板?

How to extend JComponent and use it to write a customized game board?

我想在 Java 中自学更多有关图形的知识。为此,我正在尝试构建一个国际象棋游戏。我在制作董事会时遇到了第一个障碍。我的想法是,我将有一个名为“Square”的 JComponent 扩展,它是我的容器,用于放置棋盘正方形的颜色和该正方形上的棋子(如果有)。首先,我还没有尝试包括这件作品的任何表现形式,只是方形颜色。稍后我希望有一个抽象的“Pieces”class,它由多个代表所有不同类型的 subclasses 扩展,并根据需要将它们添加到每个 Square。

当我执行以下命令时,我只在左上角看到一个黑色方块。

ChessBoardTest.java

public class ChessBoardTest {
public static void main(String[] args) {
    ChessBoard Board = new ChessBoard();
    Board.Display();
}

}

ChessBoard.java

public class ChessBoard extends JFrame {

public static final int FRAME_WIDTH  = 500;
public static final int FRAME_HEIGHT = 500;

// Declare instance variables
private Square[][] square = new Square[rows][cols];
private final static int rows = 8;
private final static int cols = 8;


public ChessBoard() {
    
}

public void Display() {
    JPanel Board_Layout = new JPanel();
    Board_Layout.setLayout(new GridLayout(8,8));
    for(int i=0;i<8;i++)
    {
         for(int j=0;j<8;j++)
         {
             if((i+j) % 2 == 0) {
                 square[i][j] = new Square(1);
                 Board_Layout.add(square[i][j]);
             } else {
                 square[i][j] = new Square(0);
                 Board_Layout.add(square[i][j]);
             }
             
         }
    }
    setTitle("Chess Mod");
    setSize(FRAME_WIDTH, FRAME_HEIGHT);
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    add(Board_Layout);
    setVisible(true);
}


public void messageBox(String pMessage) {
    JOptionPane.showMessageDialog(this, pMessage, "Message", JOptionPane.PLAIN_MESSAGE);
}

}

Square.java

public class Square extends JComponent {

private int color;

public Square(int c) {
    this.color=c;
}

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    
    if (this.color == 1) {
        g.setColor(new Color(0,0,0));
    } else {
        g.setColor(new Color(255,255,255));
    }
    
    g.fillRect(this.getX(), this.getY(), this.getWidth(), this.getHeight());
}

}

I only get one black square in the upper left hand corner.

主要是因为下面的调用:

g.fillRect(this.getX(), this.getY(), this.getWidth(), this.getHeight());

getX() returns 被调用的 Component 的水平像素 offset/location,相对于包含 [=13] 的 Container =]. getY() 因此 returns 相对于包含 ComponentContainer 调用的 Component 的垂直像素 offset/location。 =43=]

getWidth()getHeight() return Component.

的大小

所以假设 Component 位于索引 2 的行和索引 3 的列,其坐标大约在 x == 3 * w / 8y == 2 * h / 8,其中 wh 是父级 Container(即 Board_Layout 面板)的大小(分别为宽度和高度)。假设当您显示图形用户界面时 Board_Layout 的大小为 300x300...这意味着我提到的位置处的 Square 只会绘制从 x == 112 开始的区域和 y == 75 并扩展为 Board_Layout 宽度(和高度)的八分之一(因为网格中有 8 行和 8 列)。但是 Square 本身的大小也是 Board_Layout 宽度(和高度)的八分之一,即大约 37x37。因此,从位置 112,75 开始并扩展的绘制区域根本不会显示(因为它完全位于 Square 的大小之外)。

只有左上角 Square 会有一些绘画,因为它在父级中的边界恰好与绘制区域相交。

要解决此问题,Graphics 对象的位置应相对于每个 Square 而不是其父对象 Board_Layout。例如:

g.fillRect(0, 0, getWidth(), getHeight());