Java 使用 JPanel 创建棋盘
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21077322/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create a Chess board with JPanel
提问by Jamgreen
I have a simple Chess board in a JPanel
with GridLayout(8,8)
as layout manager.
我有一个简单的棋盘JPanel
与GridLayout(8,8)
作为布局管理器。
I am trying to add panels for the fields' column name and row number.
我正在尝试为字段的列名和行号添加面板。
Right now I've created another panel with BorderLayout
as layout manager, and in this panel I add the board in BorderLayout.CENTER
. Next to the board itself I've added a panels with GridLayout(0,8)
in BorderLayout.SOUTH
and a panel with GridLayout(8,0)
in BorderLayout.WEST
. The rows numbers is perfectly placed next to the board because the number of rows in the left JPanel matches the number of rows in the board, but the column names (A, B, C, D, E, F, G, H) in the JPanel under the board is not placed correctly because of the JPanel in BorderLayout.WEST
.
现在我已经创建了另一个面板BorderLayout
作为布局管理器,在这个面板中我添加了BorderLayout.CENTER
. 在板本身旁边,我添加了一个带有GridLayout(0,8)
inBorderLayout.SOUTH
的面板和一个带有GridLayout(8,0)
in的面板BorderLayout.WEST
。行号完美地放置在板旁边,因为左侧 JPanel 中的行数与板中的行数匹配,但列名(A、B、C、D、E、F、G、H)在板下的 JPanel 没有正确放置,因为BorderLayout.WEST
.
What can I do to make a proper Chess board with side panels to show the field numbers/names?
我该怎么做才能制作一个带有侧面板的合适的国际象棋棋盘来显示字段编号/名称?
I've tried setting the layout for the south panel to GridLayout(0,9)
and have the first field empty, but the width of the left panel is not equal to each field in the board, so it's not a good workaround.
我尝试将南面板的布局设置为GridLayout(0,9)
第一个字段为空,但左侧面板的宽度不等于板上的每个字段,因此这不是一个好的解决方法。
采纳答案by Andrew Thompson
Note
笔记
The GUI seen here has been improved and moved to Making a robust, resizable Swing Chess GUI.
此处看到的 GUI 已得到改进并移至制作一个健壮的、可调整大小的 Swing Chess GUI。
I will leave the animated GIF here (because it's cute) and the original, stripped down code (of just 125 code lines, the final code seen on the other thread is 218 LOC).
我将把动画 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);
}
}
Notes
笔记
- The chess board complete with columns on the left and a row above it is provided by a 9x9
GridLayout
. The first cell of the grid layout is a label with no text. - To simplify the game logic though, we maintain a separate 8x8 array of buttons.
- To allow keyboard functionality we use buttons for the chess board places. This also provides inbuilt focus indication. Remove the margin of the button to allow them to shrink to the size of the icon. Add an
ActionListener
to the button and it will respond to both keyboard and mouse events. - The small
?
in the left hand side of the GUI is meant to imply that area is 'reserved for future use'. We might use it to show lists of captured pieces, a selector for choice of piece when promoting pawns, game statistics, ... - The chess piece images were obtained from Example images for code and mark-up Q&As, which was in turn developed out of 'Fill' Unicode characters in labels.
Using images is simpler, whereas filling Unicode characters is more versatile as well as being 'lighter'. I.E. to support 4 different colors in 3 separate sizes of 3 different chess piece styles would require 36 separate sprite sheets!
- 国际象棋棋盘的左侧有列,上面有一行,由 9x9 提供
GridLayout
。网格布局的第一个单元格是一个没有文本的标签。 - 不过,为了简化游戏逻辑,我们维护了一个单独的 8x8 按钮阵列。
- 为了允许键盘功能,我们在棋盘位置使用按钮。这也提供了内置的焦点指示。删除按钮的边距以允许它们缩小到图标的大小。
ActionListener
向按钮添加一个,它将响应键盘和鼠标事件。 ?
GUI 左侧的小号表示该区域“保留供将来使用”。我们可能会用它来显示捕获的棋子列表、在提升棋子时选择棋子的选择器、游戏统计数据……- 棋子图像是从代码和标记问答的示例图像中获得的,而这些图像又是从标签中的“填充”Unicode 字符中开发出来的。
使用图像更简单,而填充 Unicode 字符更通用,而且“更轻”。IE 支持 3 种不同尺寸的 3 种不同棋子样式中的 4 种不同颜色需要 36 个单独的精灵表!