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

Posted

技术标签:

【中文标题】如何扩展 JComponent 并使用它来编写自定义游戏板?【英文标题】:How to extend JComponent and use it to write a customized game board? 【发布时间】:2021-10-14 09:51:35 【问题描述】:

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



【问题讨论】:

通常,您创建一个棋盘的逻辑模型,然后在单个绘图 JPanel 上绘制该逻辑模型。 Oracle 教程Performing Custom Painting 将向您展示如何操作。 1) “教自己更多关于 Java 图形的知识。为此,我正在尝试构建一个国际象棋游戏” 请注意,simple chessboard 可以完全使用标准组件。除非这是为了增加其他功能(例如,为棋子的移动设置动画),否则“自定义彩绘游戏”会有更好的选择。 2) 如果需要自定义绘画,通常使用JPanel 比使用JComponent 更好。 3) 这里没有很好的例子来扩展JFrame。只需使用标准的“开箱即用”框架。 .. .. 4) 请参阅Detection/fix for the hanging close bracket of a code block 了解我无法再费心修复的问题。请edit问题在代码末尾关闭之前添加4个空格字符。 【参考方案1】:

我只在左上角得到一个黑色方块。

这主要是因为下面的调用:

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

getX() 返回被调用的Component 相对于包含ComponentContainer 的水平像素偏移/位置。 getY() 相应地返回被调用的Component 相对于包含ComponentContainer 的垂直像素偏移/位置。

getWidth()getHeight() 返回 Component 的大小。

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

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

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

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

【讨论】:

以上是关于如何扩展 JComponent 并使用它来编写自定义游戏板?的主要内容,如果未能解决你的问题,请参考以下文章

如何在VS代码的SonarQube扩展中自定义和关闭声纳规则

如何为 JFrame 上的 JComponent 添加滚动功能?

打字稿混淆:如何使用自定义和绝对类型库扩展 Express `Request`?

JPanel、JFrame、JComponent 和 JApplet 之间的区别

如何将视觉添加到 JComponent

如何检查 JScrollPane 中的 JComponent 是不是对用户可见?