I have a JPanel that contains a 16X16 GridLayout inside of a JLayeredPane and i've initialized the grid's cells in order to make the grid look like a board game. Now what i need to do, is be able to move the red and yellow pawns (numbers 1,2) around the outer parts of the grid and start/home areas. I tried removing the old component at a selected cell in the grid and then adding the pawn JButton to that cell (as you can see in the placePawnAt()
method) but then the whole grid gets messed up (see 2nd image). I read some posts and i didn't find a solution yet other than people suggesting you use a GridBagLayout. Any ideas on how i can go about moving my JButton pawns around the grid?
I considered creating a JLabel[][]
that will hold the JLabels of each cell and then i could simply swap components through the array and the grid would use the new component. However, my pawns are JButtons so i couldn't do it that way. Is there a way to place the pawns on top of a certain cell of the grid since this is a JLayeredPane instead of adding them in the grid's cells? And if so, how would i know to which point in the screen the pawn should move at in order to be directly on top of a selected cell ?
Here's the BoardPanel that extends JLayeredPane and contains the JPanel with the grid:
public class BoardPanel extends JLayeredPane {
// Image resource declaration and initialization
ImageIcon blueSlideEnd = new ImageIcon(getClass().getClassLoader().getResource("res/slides/blueSlideEnd.png"));
ImageIcon blueSlideMid = new ImageIcon(getClass().getClassLoader().getResource("res/slides/blueSlideMedium.png"));
ImageIcon blueSlideStart = new ImageIcon(getClass().getClassLoader().getResource("res/slides/blueSlideStart.png"));
ImageIcon greenSlideEnd = new ImageIcon(getClass().getClassLoader().getResource("res/slides/greenSlideEnd.png"));
ImageIcon greenSlideMid = new ImageIcon(getClass().getClassLoader().getResource("res/slides/greenSlideMedium.png"));
ImageIcon greenSlideStart = new ImageIcon(getClass().getClassLoader().getResource("res/slides/greenSlideStart.png"));
ImageIcon redSlideEnd = new ImageIcon(getClass().getClassLoader().getResource("res/slides/redSlideEnd.png"));
ImageIcon redSlideMid = new ImageIcon(getClass().getClassLoader().getResource("res/slides/redSlideMedium.png"));
ImageIcon redSlideStart = new ImageIcon(getClass().getClassLoader().getResource("res/slides/redSlideStart.png"));
ImageIcon yellowSlideEnd = new ImageIcon(getClass().getClassLoader().getResource("res/slides/yellowSlideEnd.png"));
ImageIcon yellowSlideMid = new ImageIcon(getClass().getClassLoader().getResource("res/slides/yellowSlideMedium.png"));
ImageIcon yellowSlideStart = new ImageIcon(getClass().getClassLoader().getResource("res/slides/yellowSlideStart.png"));
ImageIcon redPawnOne = new ImageIcon(getClass().getClassLoader().getResource("res/pawns/redPawn1.png"));
ImageIcon redPawnTwo = new ImageIcon(getClass().getClassLoader().getResource("res/pawns/redPawn2.png"));
ImageIcon yellowPawnOne = new ImageIcon(getClass().getClassLoader().getResource("res/pawns/yellowPawn1.png"));
ImageIcon yellowPawnTwo = new ImageIcon(getClass().getClassLoader().getResource("res/pawns/yellowPawn2.png"));
private JPanel boardGrid;
private JButton redPawn1;
private JButton redPawn2;
private JButton yellowPawn1;
private JButton yellowPawn2;
// Constructor
public BoardPanel() {
setPreferredSize(new Dimension(650,690)); // set the size of the JLayeredPane
boardGrid = new JPanel(new GridLayout(16,16)); // Set the layout manager of the JPanel to a GridLayout
boardGrid.setSize(650,690); // set the size of the JPanel that contains the grid
initializeGridCells(boardGrid);
add(boardGrid,0); // add the JPanel that holds the grid to the JLayeredPane
// Create the necessary non-grid related components
JLabel logo = createLogo();
RedRectangularJLabel redHomeArea = new RedRectangularJLabel("Home",Color.red, Color.white,55,255);
RedRectangularJLabel redStartArea = new RedRectangularJLabel("Start",Color.red,Color.white,150,44);
YellowRectangularJLabel yellowHomeArea = new YellowRectangularJLabel("Home",Color.yellow,Color.white,495,360);
YellowRectangularJLabel yellowStartArea = new YellowRectangularJLabel("Start", Color.yellow,Color.white,400,572);
JButton redPawn1 = createPawnButton(redPawnOne,165,65);
JButton redPawn2 = createPawnButton(redPawnTwo,205,65);
JButton yellowPawn1 = createPawnButton(yellowPawnOne,415,600);
JButton yellowPawn2 = createPawnButton(yellowPawnTwo, 455, 600);
// Add the components to the layered pane
add(logo,1);
add(redHomeArea,1);
add(redStartArea,1);
add(yellowHomeArea,1);
add(yellowStartArea,1);
add(redPawn1,2);
add(redPawn2,2);
add(yellowPawn1,2);
add(yellowPawn2,2);
// Move the non-grid components to the front of the layered pane to make them visible
moveToFront(logo);
moveToFront(redHomeArea);
moveToFront(redStartArea);
moveToFront(yellowHomeArea);
moveToFront(yellowStartArea);
moveToFront(redPawn1);
moveToFront(redPawn2);
moveToFront(yellowPawn1);
moveToFront(yellowPawn2);
}
/**
* Creates a JButton with the desired ImageIcon
* at the desired position and some extra styling attributes.
* @param pawnImg The ImageIcon to be used
* @param x The x position
* @param y The y position
* @return The final stylized JButton
*/
private JButton createPawnButton(ImageIcon pawnImg, int x , int y) {
JButton pawn = new JButton();
pawn.setIcon(pawnImg);
pawn.setLocation(x,y);
pawn.setSize(30,30);
pawn.setOpaque(false);
pawn.setBorder(new LineBorder(Color.black));
return pawn;
}
/**
* Initializes the cells of the grid with the appropriate
* JComponents.
* @param boardGrid The JPanel containing the GridLayout whose cells will be filled
*/
private void initializeGridCells(JPanel boardGrid) {
// Add the labels to the respective cells of the grid
RotatableJLabel tile;
for(int i = 0; i < 256; i++) {
if((i < 16) || (i%16 == 0) || (i > 240) || (i%16 == 15)) { // initialize the outer tiles of the board
if(i == 31 || i == 159) { // start of green slides
tile = new RotatableJLabel(greenSlideStart,180);
} else if(i == 47 || i == 63 || i == 175 || i == 191 || i == 207) { // middle part(S) of green slides
tile = new RotatableJLabel(greenSlideMid,180);
} else if(i == 79 || i == 223) { // end of green slides
tile = new RotatableJLabel(greenSlideEnd,180);
} else if(i == 254 || i == 245) { // start of yellow slides
tile = new RotatableJLabel(yellowSlideStart,0);
} else if(i == 253 || i == 252 || i == 242 || i == 244 || i == 243) { // middle part(s) of the yellow slides
tile = new RotatableJLabel(yellowSlideMid,0);
} else if(i == 251 || i == 241) { // end of yellow slides
tile = new RotatableJLabel(yellowSlideEnd,0);
} else if(i == 32 || i == 160) { // end of blue slides
tile = new RotatableJLabel(blueSlideEnd,180);
} else if(i == 48 || i == 64 || i == 80 || i == 192 || i == 176) { // middle of blue slides
tile = new RotatableJLabel(blueSlideMid,180);
} else if(i == 96 || i == 208) { // start of blue slides
tile = new RotatableJLabel(blueSlideStart,180);
} else if(i == 1 || i == 10) { // start of red slides
tile = new RotatableJLabel(redSlideStart,0);
} else if(i == 2 || i == 3 || i == 11 || i == 12 || i == 13) { // middle of red slides
tile = new RotatableJLabel(redSlideMid,0);
} else if(i == 4 || i == 14) { // end of red slides
tile = new RotatableJLabel(redSlideEnd,0);
}else { // simple tile
tile = new RotatableJLabel();
tile.setBackground(Color.white);
tile.setLabelBorder();
}
} else if(i == 18 || i == 34 || i == 50 || i == 66 || i == 82) { // red home path tiles
tile = new RotatableJLabel();
tile.setBackground(Color.red);
tile.setLabelBorder();
} else if(i == 237 || i == 221 || i == 205 || i == 189 || i == 173) { // yellow home path tiles
tile = new RotatableJLabel();
tile.setBackground(Color.yellow);
tile.setLabelBorder();
} else { // all other tiles
tile = new RotatableJLabel();
tile.setBackground(Color.cyan);
}
boardGrid.add(tile, i); // add the label to the respective grid cell
}
}
/**
* Creates a JLabel with the logo
* as its icon.
* @return A JLabel with the logo icon
*/
private JLabel createLogo() {
JLabel logo = new JLabel();
ImageIcon logoIcon = new ImageIcon(getClass().getClassLoader().getResource("res/sorryImage.png"));
logo.setBounds(240,310,logoIcon.getIconWidth(),logoIcon.getIconHeight());
logo.setIcon(logoIcon);
return logo;
}
/**
* Places the selected pawn to the desired position
* on the grid.
* @param cellIndex The index of the cell in the grid
* @param frame The JFrame containing the grid
*/
public void placePawnAt(int cellIndex, JFrame frame) {
boardGrid.remove(cellIndex);
boardGrid.add(redPawn1, cellIndex);
frame.revalidate();
frame.repaint();
}
}
Here's my main class which creates the JFrame containing the BoardPanel :
public class Controller {
private static Square[] boardTiles = new Square[256];
private static BoardPanel boardPanel;
private static GameInfoPanel infoPanel;
private static JFrame window;
/**
* Creates the JFrame that will accommodate all
* of the other GUI components and makes it visible.
*/
private static void createAndShowGUI() {
window = new JFrame("Sorry! Game");
ImageIcon appIcon = new ImageIcon(Controller.class.getClassLoader().getResource("res/icon.png")); // create the icon for the app
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // when the 'X' button is clicked, the app stops
window.setSize(new Dimension(1000, 750)); // setting the size of the window
window.setResizable(false); // Window won't be resizable
window.setIconImage(appIcon.getImage()); // set the icon for the app
window.setLocationRelativeTo(null); // centers the window to the screen
window.setLayout(new BorderLayout()); // set the jframe's layout to a border layout
boardPanel = new BoardPanel(); // create a new BoardPanel Instance
infoPanel = new GameInfoPanel(); // create a new GameInfoPanel instance
window.add(infoPanel,BorderLayout.EAST); // add the info panel to the right side of the frame
window.add(createMenu(),BorderLayout.NORTH); // add the menu bar to the top of the frame
window.add(boardPanel,BorderLayout.WEST); // add the board (JLayeredPane) to the left of the frame
window.setVisible(true); // make the window visible
}
//TODO:sp move this in a separate view class
private static JMenuBar createMenu() {
JMenuBar menuBar = new JMenuBar();
menuBar.add(new JMenu("New Game"));
menuBar.add(new JMenu("Save Game"));
menuBar.add(new JMenu("Continue Saved Game"));
menuBar.add(new JMenu("Exit Game"));
return menuBar;
}
private static void initializeBoardTiles(Square[] tiles) {
for(int i = 0; i < 256; i++) {
if((i < 16) || (i%16 == 0) || (i > 240) || (i%16 == 15)) { // initialize the outer tiles of the board
if(i == 31 || i == 159) { // start of green slides
tiles[i] = new StartSlideSquare(Color.green,true);
} else if(i == 47 || i == 63 || i == 175 || i == 191 || i == 207) { // middle part(S) of green slides
tiles[i] = new InternalSlideSquare(Color.green,true);
} else if(i == 79 || i == 223) { // end of green slides
tiles[i] = new EndSlideSquare(Color.green,true);
} else if(i == 254 || i == 245) { // start of yellow slides
tiles[i] = new StartSlideSquare(Color.yellow,true);
} else if(i == 253 || i == 252 || i == 242 || i == 244 || i == 243) { // middle part(s) of the yellow slides
tiles[i] = new InternalSlideSquare(Color.yellow,true);
} else if(i == 251 || i == 241) { // end of yellow slides
tiles[i] = new EndSlideSquare(Color.yellow,true);
} else if(i == 32 || i == 160) { // end of blue slides
tiles[i] = new EndSlideSquare(Color.blue,true);
} else if(i == 48 || i == 64 || i == 80 || i == 192 || i == 176) { // middle of blue slides
tiles[i] = new InternalSlideSquare(Color.blue,true);
} else if(i == 96 || i == 208) { // start of blue slides
tiles[i] = new StartSlideSquare(Color.blue,true);
} else if(i == 1 || i == 10) { // start of red slides
tiles[i] = new StartSlideSquare(Color.red,true);
} else if(i == 2 || i == 3 || i == 11 || i == 12 || i == 13) { // middle of red slides
tiles[i] = new InternalSlideSquare(Color.red,true);
} else if(i == 4 || i == 14) { // end of red slides
tiles[i] = new EndSlideSquare(Color.red,true);
}else { // simple tile
tiles[i] = new SimpleSquare(Color.green,true);
}
} else if(i == 18 || i == 34 || i == 50 || i == 66 || i == 82) { // red home path tiles
tiles[i] = new HomeSquare(Color.red,true);
} else if(i == 237 || i == 221 || i == 205 || i == 189 || i == 173) { // yellow home path tiles
tiles[i] = new HomeSquare(Color.yellow,true);
} else { // all other tiles
tiles[i] = new NonTraversableSquare(Color.cyan);
}
}
}
public static void main(String[] args) {
initializeBoardTiles(boardTiles);
createAndShowGUI();
//boardPanel.placePawnAt(5,window);
}
}
Here's the layout so far without calling the placePawnAt method :
And here's what i get if i use my faulty placePawnAt method :