I have a problem adding an icon to a spesific element(grid?) in gridlayout. My gridlayout contains 64 "bricks" which is intended to work as a chessboard.
My gridcode looks like this:
ChessBoard
public class SjakkBrett extends JFrame implements Config {
public ChessBoard() {
setSize(800,800);
setLayout(new GridLayout(BRICKS/ ROWS, 0) );
for (int id = 0; id < BRICKS; id++)
add(new Brick(id));
setVisible(true);
}
Config
public interface Config {
public int ROWS= 8;
public int BRICKS= 64;
}
My problem is that I can't seem to find a way to add icons to a specific brick in the board, such as setIcon(new ImageIcon("pawn.png"));
because I don't know how to use the brick ID's I'm making.
Anyone who could help me out here?
To answer your specific question:
List<Brick> bricks = new ArrayList<Brick>();
public ChessBoard() {
setSize(800,800);
setLayout(new GridLayout(BRICKS/ ROWS, 0) );
for (int id = 0; id < BRICKS; id++) {
Brick brick = new Brick(id);
add(brick);
bricks.add(brick);
}
setVisible(true);
}
public void setBrick(int id, int piece) {
bricks.get(id).setPiece(piece);
}
To answer your unasked questions, let's think about a game of chess for a bit.
A chess board already has a notation. A typical first move is e4. Since a piece is not specified, that means a pawn. The only pawn that can move to e4 is the pawn sitting on e2. So, e4 is a shorthand way of saying "move the pawn from e2 to e4".
So, we have bricks (squares) that are arranged to make a board. We have pieces with the ability to move from one brick to another, according to rules that are different for each piece. We also have capture rules and rules for determining who wins.
All of these elements have to be present in the game as either objects or methods.
So, let's talk about objects.
We have a brick (square).
We have a collection of bricks called a board.
We have pieces.
These objects are interrelated. What they all have in common is the idea of location.
A brick is located in a specific spot (e2).
A board needs to know how to translate a spot (e2) into something meaningful (row 1, column 4; assuming row 0, column 0 is the lower left corner).
A piece needs to know where it's located (e2), where it can legally go (e3, e4), and where it will go (e4).
This should be enough to get you started.
Adding labels with the icon would probably make it slightly easier to
make moveable pieces to the game later I guess, but still I don't know
how to add the labels to spesific ID's in the gridlayout. BRICKS is
just getting it's information from Config, where it's declared(?) the
value 64. Sorry if I use the wrong names and stuff here, but I'm way
to fresh with java to actually work with it.
have look at put/getClientProperty, then any action/event from Keyboard
or MouseXxxListener
returns proper coordinates from the array of JLabel
s or JButtons
you can to multiple numbers of put/getClientProperty
, there isn't any limits
I'd be to use JButton
(implemented setXxxIcon
in API) instead of JLabel
(there required call for repaint()
for MouseMotionListener
)
Ive had this code lying around which I used as foundation to my own chess game.
Basically consists of 6 classes:
Test
basically holds main
and creates the GUI as well as loading a single piece to the chessboard.
NotationPanel
which is used for row and coloumns to be shown on the side of the board.
Chessboard
which holds all the ChessboardBlock
s which make up the board also lays out the board with black and white labels in their appropriate locations.
ChessboardBlock
which has a set location(i.e A4 etc) and can hold a ChessPiece
instance.
ChessPiece
which holds data/image of the Piece
instance.
ChessPieceMouseAdapter
to handle dragging and dropping of Piece
s:
The output from a typical move:
From Location: A1 Piece Type: knight Piece Color: White
To Location: D3 Piece Type: knight Piece Color: White
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
ChessPieceMouseAdapter chessPieceMouseAdapter = new ChessPieceMouseAdapter() {
@Override
boolean chessPieceSelected(ChessPiece chessPiece, ChessboardBlock cb) {
System.out.println("From Location: " + chessPiece.getLocation()
+ " Piece Type: " + chessPiece.getType()
+ " Piece Color: " + chessPiece.getColor());
return true;
}
@Override
void chessPiecePlaced(ChessPiece chessPiece, ChessboardBlock cb) {
cb.setPiece(new ChessPiece(chessPiece.getImage(),
chessPiece.getType(),
cb.getBlockLocation(),
chessPiece.getColor()));
System.out.println("To Location: " + cb.getChessPiece().getLocation()
+ " Piece Type: " + cb.getChessPiece().getType()
+ " Piece Color: " + cb.getChessPiece().getColor());
}
};
Chessboard chessBoard = new Chessboard(chessPieceMouseAdapter);
chessPieceMouseAdapter.setChessboard(chessBoard);//or else NPE will be thrown when press/drag/release on chessboard occurs
BufferedImage knightImage = null;
try {
knightImage = ImageIO.read(new URL("http://i.stack.imgur.com/qdppY.png"));
} catch (Exception e) {
e.printStackTrace();
}
ChessPiece knightPiece = new ChessPiece(knightImage, "Knight", null, "White");//location parameter can be null or anything will be set if matching block is found
chessBoard.setChessPiece("A1", knightPiece);
NotationPanel rows = new NotationPanel(new String[]{"8", "7", "6", "5", "4", "3", "2", "1"}, NotationPanel.VERTICAL);
NotationPanel cols = new NotationPanel(new String[]{"A", "B", "C", "D", "E", "F", "G", "H"}, NotationPanel.HORIZONTAL);
frame.add(rows, BorderLayout.WEST);
frame.add(cols, BorderLayout.SOUTH);
frame.add(chessBoard);
frame.pack();
frame.setVisible(true);
}
});
}
}
class NotationPanel extends JPanel {
final static String HORIZONTAL = "horizontal";
final static String VERTICAL = "vertical";
public NotationPanel(String[] strings, String direction) {
if (direction.equals(VERTICAL)) {
setLayout(new GridLayout(8, 0));
} else {
setLayout(new GridLayout(0, 8));
}
for (String string : strings) {
this.add(new JLabel(string, JLabel.CENTER));
}
}
}
class Chessboard extends JPanel {
private final ArrayList<ChessboardBlock> chessBoardBlocks;
ChessPieceMouseAdapter chessPieceMouseAdapter;
public Chessboard(ChessPieceMouseAdapter chessPieceMouseAdapter) {
super(new GridLayout(8, 8));
chessBoardBlocks = new ArrayList<>(64);
layoutBoard();
this.chessPieceMouseAdapter = chessPieceMouseAdapter;
addMouseListener(this.chessPieceMouseAdapter);
addMouseMotionListener(this.chessPieceMouseAdapter);
}
private void layoutBoard() {
String[] cols = new String[]{"A", "B", "C", "D", "E", "F", "G", "H"};
int[] rows = new int[]{1, 2, 3, 4, 5, 6, 7, 8};
int NUMBER_OF_BLOCKS = 64;
String row, col;
int rowCount = 7, colCount = 0, trigger = 8;
for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
if (trigger == 0) {
colCount = 0;
trigger = 8;
rowCount--;
}
col = cols[colCount++];
row = String.valueOf(rows[rowCount]);
trigger--;
Color pieceHolderColor = ((rowCount + colCount) % 2 == 0 ? Color.WHITE : Color.BLACK);
String pieceHolderLocation = col + row;
ChessboardBlock pieceHolder = new ChessboardBlock(pieceHolderLocation, pieceHolderColor);
pieceHolder.setPiece(null);
add(pieceHolder);//add to the board
chessBoardBlocks.add(pieceHolder);//add to piece holder array
}
}
boolean setChessPiece(String location, ChessPiece piece) {
for (int i = 0; i < chessBoardBlocks.size(); i++) {
if (chessBoardBlocks.get(i).getBlockLocation().equalsIgnoreCase(location)) {
chessBoardBlocks.get(i).setPiece(new ChessPiece(piece.getImage(),
piece.getType(), chessBoardBlocks.get(i).getBlockLocation(),
piece.getColor()));
return true;
}
}
return false;
}
public ArrayList<ChessboardBlock> getChessBoardBlocks() {
return chessBoardBlocks;
}
@Override
protected void paintChildren(Graphics g) {
super.paintChildren(g);
if (chessPieceMouseAdapter.isDragging()) {
if (chessPieceMouseAdapter.getDraggedPiece() != null) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.drawImage(chessPieceMouseAdapter.getDraggedPiece().getImage(),
chessPieceMouseAdapter.getDraggedPieceLocation().x, chessPieceMouseAdapter.getDraggedPieceLocation().y, this);
}
}
}
}
class ChessboardBlock extends JLabel {
private final Dimension labelDimensions = new Dimension(50, 50);
private ChessPiece chessPiece;
private String location;
public ChessboardBlock(String location, Color backgroundColor) {
//super(location,JLabel.CENTER);//puts location as text on label
this.location = location;
setBackground(backgroundColor);
setOpaque(true);
}
@Override
public Dimension getPreferredSize() {
return labelDimensions;
}
void setPiece(ChessPiece p) {
this.chessPiece = p;
if (chessPiece == null) {
setIcon(null);
} else if (chessPiece.getImage() != null) {
setIcon(new ImageIcon(chessPiece.getImage()));
}
}
String getBlockLocation() {
return location;
}
public ChessPiece getChessPiece() {
return chessPiece;
}
}
class ChessPiece {
private BufferedImage image;
private String location;
private String type;
private final String color;
public ChessPiece(BufferedImage image, String type, String location, String color) {
this.image = image;
this.type = type;
this.location = location;
this.color = color;
}
public ChessPiece(ChessPiece p) {
this.image = p.getImage();
this.type = p.getType();
this.location = p.getLocation();
this.color = p.getColor();
}
public String getLocation() {
return location;
}
public String getColor() {
return color;
}
public void setLocation(String location) {
this.location = location;
}
public BufferedImage getImage() {
return image;
}
String getType() {
return type;
}
}
abstract class ChessPieceMouseAdapter extends MouseAdapter {
private Chessboard chessboard;
private ChessPiece draggedChessPiece;
private boolean dragging;
private Rectangle pieceRectangle;
private Point draggedPieceInitialLocation;
private Point pressedPoint;
public ChessPieceMouseAdapter() {
dragging = false;
draggedPieceInitialLocation = new Point();
pressedPoint = new Point();
}
public Point getDraggedPieceLocation() {
return new Point(pieceRectangle.x, pieceRectangle.y);
}
public ChessPiece getDraggedPiece() {
return draggedChessPiece;
}
@Override
public void mousePressed(MouseEvent me) {
pressedPoint = me.getPoint();
ArrayList<ChessboardBlock> chessBoardBlocks = chessboard.getChessBoardBlocks();
for (int i = 0; i < chessBoardBlocks.size(); i++) {
if (chessBoardBlocks.get(i).getChessPiece() != null) {
pieceRectangle = chessBoardBlocks.get(i).getBounds();
if (pieceRectangle.contains(pressedPoint)) {
ChessPiece chessPiece = chessBoardBlocks.get(i).getChessPiece();
if (chessPieceSelected(chessPiece, chessBoardBlocks.get(i))) {
draggedChessPiece = new ChessPiece(chessPiece);
chessBoardBlocks.get(i).setPiece(null);
draggedPieceInitialLocation.x = pieceRectangle.x;
draggedPieceInitialLocation.y = pieceRectangle.y;
dragging = true;
chessboard.repaint();
}
break;
}
}
}
}
@Override
public void mouseReleased(MouseEvent me) {
ArrayList<ChessboardBlock> chessBoardBlocks = chessboard.getChessBoardBlocks();
for (int i = 0; i < chessBoardBlocks.size(); i++) {
pieceRectangle = chessBoardBlocks.get(i).getBounds();
if (pieceRectangle.contains(me.getPoint())) {
if (draggedChessPiece != null) {
chessPiecePlaced(draggedChessPiece, chessBoardBlocks.get(i));
}
}
}
dragging = false;
draggedChessPiece = null;
chessboard.repaint();
}
@Override
public void mouseDragged(MouseEvent me) {
dragging = true;
pieceRectangle.x = me.getX() - (pressedPoint.x - draggedPieceInitialLocation.x);
pieceRectangle.y = me.getY() - (pressedPoint.y - draggedPieceInitialLocation.y);
chessboard.repaint();
}
boolean isDragging() {
return dragging;
}
abstract boolean chessPieceSelected(ChessPiece chessPiece, ChessboardBlock cb);
abstract void chessPiecePlaced(ChessPiece chessPiece, ChessboardBlock cb);
void setChessboard(Chessboard chessBoard) {
this.chessboard = chessBoard;
}
}
First of all you have new GridLayout(BRICKS/ ROWS, 0)
which shows you are setting layout to have 0 Columns. (The API specifies GridLayout(int rows, int cols)
)
As for the problem with finding the x, y coords
, you don't need to. If you have a placeholders (i.e. custom labels) you can set the background color to correspond to the board cell and hold the image in the cell. The images can be set on top of the background that way for the chess look and feel.
Have click events on the labels so that when the user clicks the label is does whatever you need it to do (move a piece to/from one cell to the other, player takes a piece, checks the board for mate/check mate, etc.)
You could implement the MouseListener
's mousePressed
and mouseReleased
methods on the labels to get the desired start and end labels and if you want drag and drop functionality maybe implement MouseMotionListener
's mouseDragged
method and a custom paint
method to the board (not labels).