用JPanel创建一个棋盘

我在JPanel有一个简单的Chess板, GridLayout(8,8)作为布局管理器。

我正在尝试为字段的列名和行号添加面板。

现在我用BorderLayout创建了另一个面板作为布局管理器,在这个面板中我在BorderLayout.CENTER添加了板。 在董事会本身旁边,我在BorderLayout.SOUTH添加了一个GridLayout(0,8)面板,在BorderLayout.SOUTH添加了一个GridLayout(8,0)面板。 行号完全放在电路板旁边,因为左侧JPanel中的行数与电路板中的行数相匹配,但列名称(A,B,C,D,E,F,G,H)在由于BorderLayout.WEST中的JPanel,因此未正确放置棋盘下的JPanel。

如何制作带侧板的合适棋盘以显示字段编号/名称?

我已经尝试将南面板的布局设置为GridLayout(0,9)并将第一个字段设置为空,但左面板的宽度不等于电路板中的每个字段,因此这不是一个好的解决方法。

注意

这里看到的GUI已得到改进,并转移到制作强大,可resize的Swing Chess GUI 。

我会在这里留下动画GIF(因为它很可爱)和原始的,剥离的代码(只有125个代码行,在另一个线程上看到的最终代码是218 LOC)。

国际象棋游戏布局

 import java.awt.*; import java.awt.image.BufferedImage; import javax.swing.*; import javax.swing.border.*; public class ChessBoardWithColumnsAndRows { private final JPanel gui = new JPanel(new BorderLayout(3, 3)); private JButton[][] chessBoardSquares = new JButton[8][8]; private JPanel chessBoard; private final JLabel message = new JLabel( "Chess Champ is ready to play!"); private static final String COLS = "ABCDEFGH"; ChessBoardWithColumnsAndRows() { initializeGui(); } public final void initializeGui() { // set up the main GUI gui.setBorder(new EmptyBorder(5, 5, 5, 5)); JToolBar tools = new JToolBar(); tools.setFloatable(false); gui.add(tools, BorderLayout.PAGE_START); tools.add(new JButton("New")); // TODO - add functionality! tools.add(new JButton("Save")); // TODO - add functionality! tools.add(new JButton("Restore")); // TODO - add functionality! tools.addSeparator(); tools.add(new JButton("Resign")); // TODO - add functionality! tools.addSeparator(); tools.add(message); gui.add(new JLabel("?"), BorderLayout.LINE_START); chessBoard = new JPanel(new GridLayout(0, 9)); chessBoard.setBorder(new LineBorder(Color.BLACK)); gui.add(chessBoard); // create the chess board squares Insets buttonMargin = new Insets(0,0,0,0); for (int ii = 0; ii < chessBoardSquares.length; ii++) { for (int jj = 0; jj < chessBoardSquares[ii].length; jj++) { JButton b = new JButton(); b.setMargin(buttonMargin); // our chess pieces are 64x64 px in size, so we'll // 'fill this in' using a transparent icon.. ImageIcon icon = new ImageIcon( new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB)); b.setIcon(icon); if ((jj % 2 == 1 && ii % 2 == 1) //) { || (jj % 2 == 0 && ii % 2 == 0)) { b.setBackground(Color.WHITE); } else { b.setBackground(Color.BLACK); } chessBoardSquares[jj][ii] = b; } } //fill the chess board chessBoard.add(new JLabel("")); // fill the top row for (int ii = 0; ii < 8; ii++) { chessBoard.add( new JLabel(COLS.substring(ii, ii + 1), SwingConstants.CENTER)); } // fill the black non-pawn piece row for (int ii = 0; ii < 8; ii++) { for (int jj = 0; jj < 8; jj++) { switch (jj) { case 0: chessBoard.add(new JLabel("" + (ii + 1), SwingConstants.CENTER)); default: chessBoard.add(chessBoardSquares[jj][ii]); } } } } public final JComponent getChessBoard() { return chessBoard; } public final JComponent getGui() { return gui; } public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { ChessBoardWithColumnsAndRows cb = new ChessBoardWithColumnsAndRows(); JFrame f = new JFrame("ChessChamp"); f.add(cb.getGui()); f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); f.setLocationByPlatform(true); // ensures the frame is the minimum size it needs to be // in order display the components within it f.pack(); // ensures the minimum size is enforced. f.setMinimumSize(f.getSize()); f.setVisible(true); } }; SwingUtilities.invokeLater(r); } } 

笔记

  • 国际象棋棋盘左侧有一列,其上方有一排由9x9 GridLayout 。 网格布局的第一个单元格是没有文本的标签。
  • 为了简化游戏逻辑,我们维护一个单独的8x8按钮arrays。
  • 为了允许键盘function,我们使用棋盘位置的按钮。 这也提供了内置焦点指示。 删除按钮的边距以允许它们缩小到图标的大小。 将ActionListener添加到按钮,它将响应键盘和鼠标事件。
  • ? 在GUI的左侧意味着该区域“保留供将来使用”。 我们可能会用它来显示被捕获的棋子的列表,在推广棋子时选择棋子的选择器,游戏统计数据......
  • 棋子图像是从示例图像中获得的, 用于代码和标记Q&A ,然后由标签中的“填充”Unicode字符开发。

    使用图像更简单,而填充Unicode字符更通用,而且“更轻”。 IE支持3种不同尺寸的3种不同棋子样式的4种不同颜色需要36个单独的精灵表!