Reputation: 36423
I'm having a problem while trying to make my own chess game using JLayeredPane
.
I got this far:
(Hopefully you can see block G6
has a green border on the label showing which block was selected)
But when I add my 2 SidePanel
s to my ChessBoard
panel and then have another layer on top with labels that should cover each of the boards blocks exactly but it doesn't:
as you can see the green Border surrounding block G2
is off.
I have narrowed it down to the obvious when I add the SidePanel
s to the ChessBoard
and add that to the bottom layer and set its size to say 600x600 then add the top layer which is labels that will fit the blocks of the ChessBoard
exactly, and the green border is drawn around the selected JLabel
(and also the lower ChessBoard
square [black or white]) it is drawn off center due to the SidePanel
s which have decreased the chessboards actual size of 600x600, now it would be 600-sp1.getWidth()
x600-sp2.getHeight()
. I tried setting the bounds and preferred size of the top layer to compensate for it but it seems no use. Any help is appreciated thank you:
ChessBoardTest.java:
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashMap;
import javax.swing.*;
import javax.swing.border.BevelBorder;
public class ChessBoardTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Dimension boardSize = new Dimension(600, 600);
JFrame frame = new JFrame("Chess JLayeredPane Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
Container contentPane = frame.getContentPane();
ChessBoard chessBoard = new ChessBoard();
SidePanel sp1 = new SidePanel(new String[]{"8", "7", "6", "5", "4", "3", "2", "1"}, SidePanel.VERTICAL);
SidePanel sp2 = new SidePanel(new String[]{"A", "B", "C", "D", "E", "F", "G", "H"}, SidePanel.HORIZONTAL);
//adding these 2 side panels messes up the layout
chessBoard.add(sp1, BorderLayout.WEST);
chessBoard.add(sp2, BorderLayout.SOUTH);
chessBoard.setPreferredSize(boardSize);
chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);
ChessPieceLayer chessPieceLayer = new ChessPieceLayer();
//chessPieceLayer.setPreferredSize(boardSize);
//chessPieceLayer.setBounds(0, 0, boardSize.width, boardSize.height);
//i've tried resizing to make up for the side panels but no result
chessPieceLayer.setPreferredSize(new Dimension(600-sp1.getWidth(),600-sp2.getHeight()));
chessPieceLayer.setBounds(0+sp1.getWidth(), 0+sp2.getHeight(), 600-sp1.getWidth(), 600-sp2.getHeight());
JLayeredPane jLayeredPane = new JLayeredPane();
jLayeredPane.setPreferredSize(boardSize);
jLayeredPane.add(chessBoard, JLayeredPane.FRAME_CONTENT_LAYER);
jLayeredPane.add(chessPieceLayer, JLayeredPane.MODAL_LAYER);
contentPane.add(jLayeredPane);
frame.pack();
frame.setVisible(true);
}
});
}
}
SidePanel.java:
class SidePanel extends JPanel {
final static String HORIZONTAL = "horizontal";
final static String VERTICAL = "vertical";
public SidePanel(String[] strings, String direction) {
if (direction.equals(VERTICAL)) {
setLayout(new GridLayout(8, 0));
} else {
setLayout(new GridLayout(0, 8));
}
setDoubleBuffered(true);
for (String string : strings) {
this.add(new JLabel(string, JLabel.CENTER));
}
}
}
ChessBoard.java:
class ChessBoard extends JPanel {
public ChessBoard() {
super(new BorderLayout(), true);
this.add(populateBoard(Color.white, Color.black), BorderLayout.CENTER);
}
private JPanel populateBoard(Color c1, Color c2) {
JPanel panel = new JPanel(new GridLayout(8, 8));
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 ? c1 : c2);
panel.add(square);
}
}
return panel;
}
}
ChessPieceLayer.java:
class ChessPieceLayer extends JComponent {
private HashMap<PiecePanel, String> panelsMap = new HashMap<>(64);
final ChessPieceMouseListener listener;
ChessPieceLayer() {
super();
listener = new ChessPieceMouseListener();
setLayout(new GridLayout(8, 8));
setDoubleBuffered(true);
fillPanelsMap();
}
private void fillPanelsMap() {
String[] cols = new String[]{"A", "B", "C", "D", "E", "F", "G", "H"};
int[] rows = new int[]{1, 2, 3, 4, 5, 6, 7, 8};
String row, col;
int rowCount = 7, colCount = 0, trigger = 8;
for (int i = 0; i < 64; i++) {
if (trigger == 0) {
colCount = 0;
trigger = 8;
rowCount--;
}
col = cols[colCount++];
row = rows[rowCount] + "";
trigger--;
String location = col + row;
PiecePanel square = createAndAddPiecesWithMouseListener(location);
panelsMap.put(square, location);
}
}
private PiecePanel createAndAddPiecesWithMouseListener(String location) {
PiecePanel square = new PiecePanel(location, JLabel.CENTER);
square.addMouseListener(listener);
square.setText(location);
this.add(square);
return square;
}
}
PiecePanel.java:
class PiecePanel extends JLabel {
private String location;
public PiecePanel(String text, int horizontalAlignment) {
super("", horizontalAlignment);
this.location = text;
}
PiecePanel(String location) {
this.location = location;
}
public String getPieceLocation() {
return location;
}
public void setPieceLocation(String location) {
this.location = location;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
}
ChessPieceMouseListener.java:
class ChessPieceMouseListener implements MouseListener {
int counter = 0;
PiecePanel this_pp, prev_pp;
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
PiecePanel pp = (PiecePanel) e.getComponent();
if (counter == 0) {
this_pp = pp;
this_pp.setBorder(new BevelBorder(0, Color.green, Color.green));
JOptionPane.showMessageDialog(null, "From " + pp.getPieceLocation());
counter = 1;
} else {
prev_pp = this_pp;
this_pp = pp;
prev_pp.setBorder(null);
JOptionPane.showMessageDialog(null, "To " + pp.getPieceLocation());
counter = 0;
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
at first I used:
chessPieceLayer.setPreferredSize(boardSize);
chessPieceLayer.setBounds(0, 0, boardSize.width, boardSize.height);
Then I tried:
chessPieceLayer.setPreferredSize(new Dimension(600-sp1.getWidth(),600-sp2.getHeight()));
chessPieceLayer.setBounds(0+sp1.getWidth(), 0+sp2.getHeight(), 600-sp1.getWidth(), 600-sp2.getHeight());
but the result doesnt differ
Upvotes: 4
Views: 2448
Reputation: 47608
Ok, I found the problem and there is an easy solution. Next time, try to put your code in a single class so that I don't have to do so many Copy/Paste (this kind of discourage people to try your code) ;-).
Anyway, the problem comes from your SidePanel which takes space on your ChessBoardPanel and therefore introduces an offset. The solution is quite easy, all you have to do is:
sp1
and sp2
to contentPane
chessBoard
and chessPieceLayer
simply set the size to boardSize.Explanation
setSize
. If you want them to be offset-ed, you need to also call setLocation
, or concatenate these 2 calls in a single call to setBounds
Upvotes: 8