In the mousePressed method, what does he mean by:
The purpose of the class is to drag a label from one square to another. So there is code in the mouseDragged
and mouseReleased
events to 1) do the dragging of the label on the layered pane and 2) drop the label onto the appropriate square.
However, if the user didn't click on a square containing a label then the above code should not be executed, so the chessPiece is initially set to null and the code in the above two method is only executed when a chessPiece was clicked on.
Is chessBoard.findComponentAt(e.getX(), e.getY()) returns the JPanel square?
If it returns a JPanel, then that means there is NO chessPiece (JLabel) on the square where the user clicked. Since there is no chessPiece there is nothing to be dragged.
If it returns a JLabel, then that means there IS a chessPiece where the user clicked. In this case addition code is executed to add the chessPiece to the layered pane so it can be dragged.
when Component c gets its parent, who is the parent?
It's the JPanel containing the label. Since the label is added to the layered pane for dragging it needs to be positioned at the same location on the layered pane relative to the panel square on the chessboard.
Here is a slightly updated version that checks the bounds of the chess piece as it is dragged so it can't be moved off of the chess board. Also adds the mouse listeners to the chess board not the layered pane so the findComponentAt() method is more consistent.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class ChessBoard extends JLayeredPane implements MouseListener, MouseMotionListener
{
JLayeredPane layeredPane;
JPanel chessBoard;
JLabel chessPiece;
int xAdjustment;
int yAdjustment;
public ChessBoard()
{
Dimension boardSize = new Dimension(600, 600);
setPreferredSize( boardSize );
// Add a chess board to the Layered Pane
chessBoard = new JPanel();
chessBoard.setLayout( new GridLayout(8, 8) );
chessBoard.setPreferredSize( boardSize );
chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);
chessBoard.addMouseListener( this );
chessBoard.addMouseMotionListener( this );
add(chessBoard, JLayeredPane.DEFAULT_LAYER);
// Build the Chess Board squares
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
JPanel square = new JPanel( new BorderLayout() );
square.setBackground( (i + j) % 2 == 0 ? Color.red : Color.white );
chessBoard.add( square );
}
}
// Add a few pieces to the board
ImageIcon duke = new ImageIcon("dukewavered.gif"); // add an image here
JLabel piece = new JLabel( duke );
JPanel panel = (JPanel)chessBoard.getComponent( 0 );
panel.add( piece );
piece = new JLabel( duke );
panel = (JPanel)chessBoard.getComponent( 15 );
panel.add( piece );
}
/*
** Add the selected chess piece to the dragging layer so it can be moved
*/
public void mousePressed(MouseEvent e)
{
chessPiece = null;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
if (c instanceof JPanel) return;
Point parentLocation = c.getParent().getLocation();
xAdjustment = parentLocation.x - e.getX();
yAdjustment = parentLocation.y - e.getY();
chessPiece = (JLabel)c;
chessPiece.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
add(chessPiece, JLayeredPane.DRAG_LAYER);
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
}
/*
** Move the chess piece around
*/
public void mouseDragged(MouseEvent me)
{
if (chessPiece == null) return;
// The drag location should be within the bounds of the chess board
int x = me.getX() + xAdjustment;
int xMax = chessBoard.getWidth() - chessPiece.getWidth();
x = Math.min(x, xMax);
x = Math.max(x, 0);
int y = me.getY() + yAdjustment;
int yMax = chessBoard.getHeight() - chessPiece.getHeight();
y = Math.min(y, yMax);
y = Math.max(y, 0);
chessPiece.setLocation(x, y);
}
/*
** Drop the chess piece back onto the chess board
*/
public void mouseReleased(MouseEvent e)
{
setCursor(null);
if (chessPiece == null) return;
// Make sure the chess piece is no longer painted on the layered pane
chessPiece.setVisible(false);
remove(chessPiece);
chessPiece.setVisible(true);
// The drop location should be within the bounds of the chess board
int xMax = chessBoard.getWidth() - chessPiece.getWidth();
int x = Math.min(e.getX(), xMax);
x = Math.max(x, 0);
int yMax = chessBoard.getHeight() - chessPiece.getHeight();
int y = Math.min(e.getY(), yMax);
y = Math.max(y, 0);
Component c = chessBoard.findComponentAt(x, y);
if (c instanceof JLabel)
{
Container parent = c.getParent();
parent.remove(0);
parent.add( chessPiece );
parent.revalidate();
}
else
{
Container parent = (Container)c;
parent.add( chessPiece );
parent.revalidate();
}
}
public void mouseClicked(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
private static void createAndShowUI()
{
JFrame frame = new JFrame("Chess Board");
frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
frame.add( new ChessBoard() );
frame.setResizable( false );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}