I'm building a swing based GUI for a Java game. The game is essentially a 4x4 grid made up of custom Cell
objects, which is in essence, a custom JButton. Code for this below
package gamePack;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JButton;
public class Cell extends JButton {
int co_x = 0;
int co_y = 0;
ArrayList<Players> current = new ArrayList <Players>();
}
The ArrayList
allows me to store Objects of different Players
. All the Players
inherit from the same class, so I'm essentially redrawing the cell and adding Icons based on the type of object within the ArrayList. There is an ArrayList for each cell as each cell can have multiple Players
.
GUI initialization:
package gamePack;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.border.Border;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class StarFight {
public JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
StarFight window = new StarFight();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public StarFight() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setVisible(true);
frame.setBounds(100, 100, 487, 349);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
final JPanel gamePanel = new JPanel();
gamePanel.setBounds(0, 0, 365, 310);
frame.getContentPane().add(gamePanel);
int i = 4;
int j = 4;
final Cell[][] panelHolder = new Cell[i][j];
gamePanel.setLayout(new GridLayout(4, 4, 0, 0));
//91.25 x 77.5 rectangles
Border border = BorderFactory.createLineBorder(Color.white);
for(int m = 0; m < i; m++) {
for(int n = 0; n < j; n++) {
panelHolder[m][n] = new Cell();
panelHolder[m][n].co_x = m;
panelHolder[m][n].co_y= n;
panelHolder[m][n].setBackground(Color.black);
panelHolder[m][n].setEnabled(false);
panelHolder[m][n].setBorder(border);
gamePanel.add(panelHolder[m][n]);
}
}
JPanel controlPanel = new JPanel();
controlPanel.setBounds(375, 0, 86, 310);
frame.getContentPane().add(controlPanel);
controlPanel.setLayout(null);
final JButton Move = new JButton("Move");
Move.setEnabled(false);
Move.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
panelHolder[0][0].current.clear();
BattleCruiser q = new BattleCruiser();
panelHolder[3][2].current.add(q);
Redraw.draw(gamePanel, panelHolder);
}
});
Move.setBounds(1, 82, 84, 65);
controlPanel.add(Move);
final JButton Undo = new JButton("Undo");
Undo.setEnabled(false);
Undo.setBounds(1, 158, 84, 65);
controlPanel.add(Undo);
JButton Exit = new JButton("Exit");
Exit.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
System.exit(0);
}
});
Exit.setBounds(1, 234, 84, 65);
controlPanel.add(Exit);
final JButton btnStart = new JButton("Start");
btnStart.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
Move.setEnabled(true);
Undo.setEnabled(true);
btnStart.setEnabled(false);
PlayChar p = new PlayChar();
BattleCruiser q = new BattleCruiser();
BattleStar s = new BattleStar();
BattleShooter sh = new BattleShooter();
panelHolder[0][0].current.add(p);
Redraw.draw(gamePanel, panelHolder);
}
});
btnStart.setBounds(1, 6, 84, 65);
controlPanel.add(btnStart);
}
}
The game changes when the Move button is clicked. Here, I'm adding in the player's sprite when I click start, and the redraw method is called. The redraw method below:
package gamePack;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;
public class Redraw {
public static void draw(JPanel gamePanel, Cell[][] panelHolder ){
gamePanel.setBounds(0, 0, 365, 310);
int i = 4;
int j = 4;
gamePanel.setLayout(new GridLayout(4, 4, 0, 0));
//91.25 x 77.5 rectangles
Border border = BorderFactory.createLineBorder(Color.white);
for(int m = 0; m < i; m++) {
for(int n = 0; n < j; n++) {
panelHolder[m][n].setBackground(Color.black);
panelHolder[m][n].setEnabled(false);
panelHolder[m][n].setBorder(border);
panelHolder[m][n].setIcon(null);
for(Players p: panelHolder[m][n].current){
if(p instanceof PlayChar){
String arg = "Player.png";
ImageIcon icon = new ImageIcon(arg);
JLabel label = new JLabel();
label.setIcon(icon);
panelHolder[m][n].add(label);
} else if (p instanceof BattleStar) {
String arg = "BattleStar.png";
ImageIcon icon = new ImageIcon(arg);
JLabel label = new JLabel();
label.setIcon(icon);
panelHolder[m][n].add(label);
} else if (p instanceof BattleCruiser){
String arg = "BattleCruiser.png";
ImageIcon icon = new ImageIcon(arg);
JLabel label = new JLabel();
label.setIcon(icon);
panelHolder[m][n].add(label);
} else if (p instanceof BattleShooter){
String arg = "BattleShooter.png";
ImageIcon icon = new ImageIcon(arg);
JLabel label = new JLabel();
label.setIcon(icon);
panelHolder[m][n].add(label);
}
}
}
}
gamePanel.revalidate();
gamePanel.repaint();
}
}
The redraw method checks the ArrayList in each cell, and then adds an icon appropriately. At the moment, when I click Move, it should remove all the JButtons, then add them back with the appropriate sprites.
The problem is that when I do so, even with the current.clear()
before adding another sprite, the sprite in the 0,0 position is still drawn. Stepping through the code shows that the if statement for the PlayChar
object isn't being called, so I have to assume that it's something to do with the redraw method. Am I doing something obviously wrong?
EDIT: Based on feedback, I have now changed it so the redraw function doesn't replace the JButtons, but changes their properties. I've also added it so that the Icon is set to null for each one before any Icons are set, to ensure that it is removed. The same problem, however, is still occurring