I am making a checkerboard gui JFrame that has a menubar on the north side of the JFrame, the actual checkerboard in the middle of the JFrame, and a status JPanel on the bottom of the application. I am having trouble displaying my checkerboard on the JFrame, though. There is a checkerpiece class (represents one square), a checkerboard class (which puts all the checkerpieces together), and a checkergame class which puts the checkerboard on the gui. I just need help with displaying my checkerboard on the JFrame right now, and dont need help with functionality. My Checkergame class constructor:
frame.setSize(505, 585);
frame.setLayout(new BorderLayout());
JMenuBar menuBar= new JMenuBar();
JMenu menuTwo = new JMenu("Game");
JMenuItem newGame = new JMenuItem("New Game");
JMenuItem exit = new JMenuItem("Exit");
menuTwo.add(newGame);
menuTwo.add(exit);
menuBar.add(menuTwo);
JMenu helpTwo = new JMenu("Help");
JMenuItem rules = new JMenuItem("Checker Game Rules");
JMenuItem about = new JMenuItem("About Checker Game App");
helpTwo.add(rules);
helpTwo.add(about);
menuBar.add(helpTwo);
frame.add(menuBar , BorderLayout.NORTH);
JPanel game = new JPanel();
CheckerBoard c = null;
try {
frame.getContentPane().add(new CheckerBoard(boardStatus));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
frame.add(game, BorderLayout.CENTER);
JPanel status = new JPanel();
status.setLayout(new GridLayout());
JLabel statusTwo = new JLabel("12 Red : 12 Black");
status.add(statusTwo);
status.add(name);
frame.add(statusTwo, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
My checkerboard class:
public class CheckerBoard extends JPanel {
private char[][] boardStatus;
public CheckerBoard(char [][] boardStatus) throws Exception {
JPanel board = new JPanel();
board.setLayout(new GridLayout(8,8));
for (int row = 0; row < 8; row++) {
for (int column = 0; column < 8; column++) {
board.add(new CheckerPiece(row, column, boardStatus[row][column]));
}
}
board.setVisible(true);
}
My checkerpiece class:
public class CheckerPiece extends JComponent{
private int row;
private int column;
private char status;
final int y1 = 60;
final int x1 = 480;
public CheckerPiece(int row, int column, char status) throws Exception {
setRow(row);
setColumn(column);
setStatus(status);
}
public int getRow() {
return row;
}
public void setRow(int row) throws Exception {
if (row >= 0 && row <= 7) {
this.row = row;
} else throw new IllegalCheckerboardArgumentException("Row must be between 0 and 7");
}
public int getColumn() {
return column;
}
public void setColumn(int column) throws Exception {
if (column >= 0 && column <= 7) {
this.column = column;
} else throw new IllegalCheckerboardArgumentException("Column must be between 0 and 7");
}
public char getStatus() {
return status;
}
public void setStatus(char status) throws Exception {
if (status == 'b' || status == 'e' || status == 'r')
this.status = status;
else throw new IllegalCheckerboardArgumentException("Status must be 'b', 'e', or 'r'.");
}
public void paintComponents(Graphics g) {
int x = 0;
int y = 0;
int count = 0;
if (status == 'b' ) {
g.setColor(Color.GREEN);
g.fillRect(0 + x, 0 + y, 60, 60);
g.setColor(Color.BLACK);
g.fillOval(5+x, 5 + y, 40, 40);
x += 60;
count++;
}
if (status == 'e') {
g.setColor(Color.WHITE);
g.fillRect(0 + x,0 + y, 60, 60);
x+= 60;
count++;
}
if (status == 'r') {
g.setColor(Color.GREEN);
g.fillRect(0 + x,0 + y, 60, 60);
g.setColor(Color.RED);
g.fillOval(5 + x, 5 + y, 40, 40);
x += 60;
count++;
}
if (count % 8 == 0) {
y += 60;
}
}
}
You need a method in your CheckerBoard class to return the JPanel so that it can be added to the JFrame.
import java.awt.GridLayout;
import javax.swing.JPanel;
public class CheckerBoard extends JPanel {
private static final long serialVersionUID = 1L;
private JPanel board;
public CheckerBoard(char [][] boardStatus)
throws Exception {
int height = boardStatus.length;
int width = boardStatus[0].length;
board = new JPanel();
board.setLayout(new GridLayout(width, height));
for (int row = 0; row < width; row++) {
for (int column = 0; column < height; column++) {
board.add(new CheckerPiece(row, column,
boardStatus[row][column]));
}
}
}
public JPanel getPanel() {
return board;
}
}
Related
I'm doing a Coursework assignment for the Uni, the assignment is to create a RectanglesGUI with JPanel, but I have a problem with the buttons I have created.
The buttonSOUTH supposed to do the following:
When the user clicks on the JButton in the SOUTH region, the
rectangles filled with color1 should all change to a random Color,
while the rectangles filled with color2 should not change. A second
click on the JButton should make the rectangles filled with color2 all
change to a random Color, while the rectangles filled with a random
Color by the first click should stay the same Color. The user should be
able to continue clicking on the button indefinitely, and with each click
one set of rectangles will be filled with a random Color.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class RectanglesGUI {
JFrame frame;
RectangleDrawPanel drawPanel;
Color color1 = Color.orange;
Color color2 = Color.blue;
public static void main (String[] args) {
RectanglesGUI gui = new RectanglesGUI();
gui.go();
}
//this method sets up the JFrame
public void go() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawPanel = new RectangleDrawPanel();
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.getContentPane().setBackground(Color.black);
frame.setSize(600,600);
frame.setVisible(true);
CreateButton newButton = new CreateButton();
newButton.CreateButton();
frame.repaint();
}
// To Create a new Button
public class CreateButton {
JButton buttonSOUTH;
JButton buttonNORTH;
public void CreateButton () {
buttonSOUTH = new JButton("Change Colors");
buttonSOUTH.setPreferredSize(new Dimension(100, 50));
buttonSOUTH.setVisible(true);
frame.add(buttonSOUTH, BorderLayout.SOUTH);
buttonSOUTH.addActionListener(new RandomColorListener());
buttonNORTH = new JButton("Reset Colors");
buttonNORTH.setPreferredSize(new Dimension(100, 50));
buttonNORTH.setVisible(true);
frame.add(buttonNORTH, BorderLayout.NORTH);
buttonNORTH.addActionListener(new ResetListener());
}
// ActionListener for buttonSOUTH
private class ResetListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
color1 = Color.orange;
color2 = Color.blue;
frame.repaint();
}
}
// ActionListener for buttonNORTH
private class RandomColorListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
ChangeColor c = new ChangeColor();
for (int i = 0; i < 100; i++){
if (i % 2 == 0) {
color1 = c.getColor1();
frame.repaint();
} else {
color2 = c.getColor2();
frame.repaint();
}
}
}
}
// Change Color Class
private class ChangeColor {
private Color getColor1(){
Random fill1 = new Random();
color1 = new Color (fill1.nextInt(256), fill1.nextInt(256),
fill1.nextInt(256));
return color1;
}
private Color getColor2(){
Random fill2 = new Random();
color2 = new Color (fill2.nextInt(256), fill2.nextInt(256),
fill2.nextInt(256));
return color2;
}
}
}
class RectangleDrawPanel extends JPanel {
public void paintComponent (Graphics g){
super.paintComponent(g);
Graphics2D g2=(Graphics2D)g;
int width = getWidth();
int height = getHeight();
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
int x = (getWidth() / 5) * i;
int y = (getHeight() / 5) * j;
if ((i % 2) == (j % 2)) {
g2.setColor(color1);
} else
g2.setColor(color2);
g2.fill3DRect(x,y,width,height,true);
}
}
}
}
}
But I don't know how to set this to be infinite
for (int i = 0; i < 100; i++){
if (i % 2 == 0) {
color1 = c.getColor1();
frame.repaint();
}
else {
color2 = c.getColor2();
frame.repaint();
}
}
this part for (int i = 0; i < 100; i++)
is not useful for checking.
both part inside condition checking will always executed. that mean both color2 and color1 will change. since i%2 will return 0 and 1
add this property to RectangleGui class boolean status=false;
then change code inside method actionPerformed in class RandomColorListener to:
if (status) {
color1 = c.getColor1();
frame.repaint();
} else {
color2 = c.getColor2();
frame.repaint();
}
status=!status;
I am referencing this link, however this won't ultimately fix my problem (i.e I run my program from someone else's computer). How to deal with "java.lang.OutOfMemoryError: Java heap space" error (64MB heap size). Right now, I have a game board that has 10x10 squares, but I need to increase this to 100x100, but when I do, I get this error. What is the best way to increase my game board size while avoiding this error? Current output is below, Code should compile and run. Thanks!
GameBoard Class:
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.*;
public class GameBoard {
private final JPanel board = new JPanel(new BorderLayout(3, 3));
private JButton[][] c1squares = new JButton[10][10];
private JPanel c1Board, c2Board;
private final JLabel messagec1 = new JLabel("Player 1 Board");
JToolBar tool = new JToolBar();
Insets Margin = new Insets(0,0,0,0);
int squares = 10;
int space = 100;
ImageIcon icon = new ImageIcon(new BufferedImage(space, space, BufferedImage.TYPE_INT_ARGB));
GameBoard() {
initializeGui();
}
public final void initializeGui() {
board.setBorder(new EmptyBorder(5, 5, 5, 5));
tool.setFloatable(false);
board.add(tool, BorderLayout.PAGE_START);
tool.add(messagec1);
c1Board = new JPanel(new GridLayout(0, 10));
c1Board.setBorder(new LineBorder(Color.BLACK));
board.add(c1Board);
for (int i = 1; i < c1squares.length; i++) {
for (int j = 0; j < c1squares[i].length; j++) {
JButton b = new JButton();
b.setMargin(Margin);
b.setIcon(icon);
if ((j % 2 == 1 && i % 2 == 1) || (j % 2 == 0 && i % 2 == 0)) {
b.setBackground(Color.WHITE);
} else {
b.setBackground(Color.BLACK);
}
c1squares[j][i] = b;
}
}
for (int i = 1; i < squares; i++) {
for (int j = 0; j < squares; j++) {
c1Board.add(c1squares[j][i]);
}
}
public final JComponent getGui() {
return board;
}
public final JComponent getGui2() {
return board2;
}
}
BattleShipFinal Class:
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class BattleshipFinal {
public static void main(String[] args) {
GameBoard gb = new GameBoard();
JFrame frame = new JFrame("Battleship - Server");
frame.add(gb.getGui());
frame.setLocationByPlatform(true);
frame.setMinimumSize(frame.getSize());
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(900,900));
frame.setMinimumSize(new Dimension(900,900));
frame.setLocation(50,50);
frame.pack();
frame.setVisible(true);
}
}
In case you are curious, and to illustrate what people said in the comments, you could have a custom JPanel painting the squares.
If you ever need to respond to mouse events, add a MouseListener to your panel, which will take care of the selected square (haven't added that part, but the selected field inside the Square class is a hint).
I removed stuff from your code, just to demonstrate this painting part.
GameBoard :
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class GameBoard {
private JPanel board;
private final Square[][] c1squares = new Square[10][10];
GameBoard() {
initializeGui();
}
public final void initializeGui() {
for (int i = 0; i < c1squares.length; i++) {
for (int j = 0; j < c1squares[i].length; j++) {
Square square = new Square();
if ((j % 2 == 1 && i % 2 == 1) || (j % 2 == 0 && i % 2 == 0)) {
square.setBackground(Color.WHITE);
} else {
square.setBackground(Color.BLACK);
}
c1squares[i][j] = square;
}
}
board = new BoardPanel(c1squares);
board.setBorder(new EmptyBorder(5, 5, 5, 5));
}
public final JComponent getGui() {
return board;
}
private class BoardPanel extends JPanel {
Square[][] squares;
public BoardPanel(final Square[][] squares) {
this.squares = squares;
}
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
for (int i = 0; i < squares.length; i++) {
for (int j = 0; j < squares[i].length; j++) {
Square currentSquare = squares[i][j];
System.out.println("Managing square " + i + " " + j);
g.setColor(currentSquare.getBackground());
g.fillRect(i * width / squares.length, j * height / squares.length, width / squares.length,
height / squares.length);
}
}
}
}
private class Square {
boolean isSelected;
Color background;
public boolean isSelected() {
return isSelected;
}
public void setSelected(final boolean isSelected) {
this.isSelected = isSelected;
}
public Color getBackground() {
return background;
}
public void setBackground(final Color background) {
this.background = background;
}
}
}
BattleshipFinal :
import java.awt.Dimension;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class BattleshipFinal {
public static void main(final String[] args) {
GameBoard gb = new GameBoard();
JFrame frame = new JFrame("Battleship - Server");
JComponent board = gb.getGui();
frame.add(board);
frame.setLocationByPlatform(true);
//frame.setMinimumSize(frame.getSize());
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
//frame.setPreferredSize(new Dimension(100, 100));
board.setMinimumSize(new Dimension(100, 100));
board.setPreferredSize(new Dimension(100, 100));
frame.setMinimumSize(new Dimension(100, 100));
frame.setLocation(50, 50);
frame.pack();
frame.setVisible(true);
}
}
Okay, I figured out the solution for this. Here is the output:
The way I fixed this was by changing these lines of code:
private JButton[][] c1squares = new JButton[100][100];
int squares = 100;
int space = 1000;
c1Board = new JPanel(new GridLayout(0, 100));
Currently I'm working on an assignment about creating a version of "Game of Life". However my cells won't appear.
This is my Cell Class:
class Cell{
boolean alive; //true if cell is alive, false if cell is dead
int numNeighbors; //number of alive neightboring cells
//change alive/dead state of the cell
void setAlive(boolean state){
alive = state;
}
//return alive/dead state of the cell
boolean isAlive(){
return alive;
}
//set numNeightbors of the cell to n
void setNumNeighbors(int n){
numNeighbors = n;
}
//take the cell to the next generation
void update(){
if(numNeighbors <2 || numNeighbors >3){
alive = false;
} else if((numNeighbors == 2 || numNeighbors == 3) && alive == true){
alive = true;
} else if(numNeighbors == 3 && alive == false){
alive = true;
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor( Color.blue );
g.setOpaque(true);
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
if(grid[i][j].isAlive()){
g.setColor( Color.BLACK);
} else {
g.setColor ( Color.WHITE);
g.fillRect(50, 50, 50*i, 50*j);
}
}
}
}
And this is my GameOfLife Class
<pre>import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import java.io.*;
public class GameOfLife implements MouseListener{
Cell[][] grid; //contain grid of cells
String birthFilename = "birth.txt"; //text file where initial generation is stored
int row; //number of rows
int col; //number of columns
ActionListener actionListener = new ActionListener(){
javax.swing.Timer timer = new javax.swing.Timer(500, this); //new timer
#Override
public void actionPerformed(ActionEvent event){
}
};
public void buildIt() {
int width = 600;
int height = 600;
JFrame frame = new JFrame("Game of Life");
readInitial();
//adds button interface
JPanel buttonbar = new JPanel();
frame.add(buttonbar, BorderLayout.SOUTH);
JButton start = new JButton("Start");
JButton stop = new JButton("Stop");
JButton nextg = new JButton("Next Generation");
buttonbar.add(nextg);
buttonbar.add(start);
buttonbar.add(stop);
JPanel panel = new JPanel();
frame.add(panel);
panel.setPreferredSize(new Dimension(width, height));
panel.setLayout(new GridLayout(row, col, 4, 4));
frame.pack();
frame.setBackground(Color.WHITE);
frame.setVisible(true);
}
public void mousePressed( MouseEvent e) {
//add code to update x and y
}
public void mouseReleased( MouseEvent e) { }
public void mouseClicked( MouseEvent e) { }
public void mouseEntered( MouseEvent e) { }
public void mouseExited( MouseEvent e) { }
//calculate number of living neightbors of each cell and sets numNeighbors
//Does not update dead/live state of cells
void calculateNumNeighbors(){
int numNeighbors = 0;
for(int i = 1; i < row + 1; i++){
for(int j = 1; j < col + 1; j++){
for(int k = -1; k < 2; k++){
for(int m = -1; m < 2; m++){
if(grid[i+k][j+m].isAlive() && !(k == 0 && m == 0)){
numNeighbors++;
}
}
}
grid[i][j].setNumNeighbors(numNeighbors);
}
}
}
//create grid and read initial generation from file
void readInitial(){
try{
grid = new Cell[row + 2][col + 2]; //empty neighbors at corners, so + 2
File file = new File(birthFilename);
Scanner scanner = new Scanner( file );
row = scanner.nextInt();
col = scanner.nextInt();
for(int i = 0; i < row + 2; i++){
for (int j = 0; j < col + 2; j++){
grid[i][j] = new Cell();
}
}
for(int i = 1; i < row + 1; i++){
for (int j = 1; j < col + 1; j++){
if(scanner.next().equals(".")){
grid[i][j].setAlive(false);
} else if(scanner.next().equals("*")){
grid[i][j].setAlive(true);
}
}
}
for(int i = 0; i < row + 2; i++){
grid[0][i].setAlive(false);
grid[row+2][i].setAlive(false);
}
for(int j = 0; j < col + 2; j++){
grid[j][0].setAlive(false);
grid[j][col+2].setAlive(false);
}
} catch(FileNotFoundException e) {
grid = new Cell[12][12];
row = 10;
col = 10;
for(int i = 0; i < 12; i++){
for (int j = 0; j < 12; j++){
grid[i][j] = new Cell();
grid[i][j].setAlive(false);
}
}
}
}
//update grid to the next generation, using the values of numNeightbors in the cells
void nextGeneration(){
for(int i = 1; i < row + 1; i++){
for (int j = 1; j < col + 1; j++){
grid[i][j].update();
}
}
}
public static void main(String[] arg) {
(new GameOfLife()).buildIt();
}
I hope anyone can help me out to make this program work.
I don't see why anything should draw. You've got a Cell class that yes has a paintComponent method, but this method is meaningless since it's not part of a Swing component. Your JPanel, where you should do drawing -- does nothing. You've other problems with the Cell class too in that it appears to be trying to draw the whole grid and not just a single cell.
Get rid of Cell's paintComponent method
Instead give it a public void draw(Graphics g) method that allows it to draw itself.
Create a JPanel that holds a grid of cells
Have this JPanel do the drawing in its paintComponent override. It will call the draw(g) method of all the Cells that it holds within a for loop.
Always place an #Override annotation above any overridden method. If you had done this, above your paintComponent, the compiler would have warned you that something was wrong.
For example: here's a small program that does not do the Game of Life, but shows an example of a JPanel holding and displaying a grid of non-component cells. By "non-component" the SimpleCell class does not extend from a Swing component, does not have any Swing methods, but as suggested above, does have a draw(...) method and can use this to draw itself. It also has a public boolean contains(Point p) method that the main program can use in its MouseListener to decide if it's been clicked:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class SimpleCellGrid extends JPanel {
private static final int ROWS = 40;
private static final int COLS = 40;
private static final int CELL_WIDTH = 10;
private static final int PREF_W = CELL_WIDTH * COLS;
private static final int PREF_H = CELL_WIDTH * ROWS;
private SimpleCell[][] cellGrid = new SimpleCell[ROWS][COLS];
public SimpleCellGrid() {
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
for (int row = 0; row < cellGrid.length; row++) {
for (int col = 0; col < cellGrid[row].length; col++) {
int x = col * CELL_WIDTH;
int y = row * CELL_WIDTH;
cellGrid[row][col] = new SimpleCell(x, y, CELL_WIDTH);
}
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (SimpleCell[] cellRow : cellGrid) {
for (SimpleCell simpleCell : cellRow) {
simpleCell.draw(g2);
}
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyMouse extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
for (SimpleCell[] cellRow : cellGrid) {
for (SimpleCell simpleCell : cellRow) {
if (simpleCell.contains(e.getPoint())) {
simpleCell.setAlive(!simpleCell.isAlive());
}
}
}
repaint();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("SimpleCellGrid");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SimpleCellGrid());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
public class SimpleCell {
private static final Color CELL_COLOR = Color.RED;
private boolean alive = false;
private int x;
private int y;
private int width;
private Rectangle rectangle;
public SimpleCell(int x, int y, int width) {
this.x = x;
this.y = y;
this.width = width;
rectangle = new Rectangle(x, y, width, width);
}
public boolean isAlive() {
return alive;
}
public void setAlive(boolean alive) {
this.alive = alive;
}
public void draw(Graphics2D g2) {
if (alive) {
g2.setColor(CELL_COLOR);
g2.fill(rectangle);
}
}
public boolean contains(Point p) {
return rectangle.contains(p);
}
#Override
public String toString() {
return "SimpleCell [alive=" + alive + ", x=" + x + ", y=" + y + ", width=" + width + ", rectangle=" + rectangle
+ "]";
}
}
So I am in the process of creating a game similar to Plants vs Zombies, however I've run into a slight problem: before I can apply the finishing touches such as levels, I need to prevent more than one JLabel being added to a JPanel. The placing of the JLabel works fine, though I think that I may have gone a roundabout route. The problem as stated above is that another JLabel can currently be added below a pre-existing JLabel. How do I set a JPanel to accept no more than the original component (the initial JLabel)? Any assistance would be greatly appreciated.
private final JFrame FRAME;
private final JPanel squares[][] = new JPanel[8][11];
private final Color DGY = Color.DARK_GRAY;
private final Color GRN = Color.GREEN;
private final Color BLK = Color.BLACK;
private final Color LGY = Color.LIGHT_GRAY;
private final Color GRY = Color.GRAY;
private final Color BLU = Color.BLUE;
private final Font F1 = new Font("Tahoma", 1, 36);
private String icon = "";
private int lvl = 10;
private void squareGen(int i, int j, Color col, boolean border)
{
squares[i][j].setBackground(col);
if (border)
{
squares[i][j].setBorder(BorderFactory.createLineBorder(BLK, 1));
}
FRAME.add(squares[i][j]);
}
public GameGUI()
{
FRAME = new JFrame("ESKOM VS SA");
FRAME.setSize(1600, 900);
FRAME.setLayout(new GridLayout(8, 11));
for (int x = 0; x < 8; x++)
{
if (x > 1 && x < 7)
{
squares[x][0] = new JPanel();
squareGen(x, 0, GRN, true);
} else if (x == 1 || x == 7)
{
squares[x][0] = new JPanel();
squareGen(x, 0, DGY, true);
} else
{
squares[x][0] = new JPanel();
squareGen(x, 0, BLU, false);
}
for (int y = 1; y < 11; y++)
{
squares[x][y] = new JPanel();
if (x == 0)
{
squareGen(x, y, BLU, false);
} else if (y == 10 || x == 1 || x == 7)
{
squareGen(x, y, DGY, true);
} else
{
squareGen(x, y, LGY, true);
addDToPanel(x, y);
}
}
}
JButton btnPause = new JButton();
btnPause.setText("||");
btnPause.setFont(F1);
btnPause.addActionListener(new java.awt.event.ActionListener()
{
#Override
public void actionPerformed(java.awt.event.ActionEvent evt)
{
btnPauseActionPerformed(evt);
}
});
squares[7][10].add(btnPause);
addButtons(8);
FRAME.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
FRAME.setLocationRelativeTo(null);
}
public void restart()
{
FRAME.dispose();
GameGUI ggui = new GameGUI();
ggui.setVisible(true);
}
public void mainMenu()
{
FRAME.dispose();
new StartUpUI().setVisible(true);
}
private void btnPauseActionPerformed(java.awt.event.ActionEvent evt)
{
new PauseGUI(this).setVisible(true);
}
private void btnAddDefenseActionPerformed(java.awt.event.ActionEvent evt)
{
JButton btn = (JButton) evt.getSource();
icon = btn.getActionCommand();
}
private void addButtons(int x)
{
JButton[] btn = new JButton[x];
for (int j = 1; j <= x; j++)
{
btn[j - 1] = new JButton();
ImageIcon ii = new ImageIcon(this.getClass().getResource("" + j + ".png"));
btn[j - 1].setIcon(ii);
btn[j - 1].setActionCommand("" + j);
btn[j - 1].setText("");
btn[j - 1].setForeground(btn[j - 1].getBackground());
squares[0][j].add(btn[j - 1]);
btn[j - 1].addActionListener(new java.awt.event.ActionListener()
{
#Override
public void actionPerformed(java.awt.event.ActionEvent evt)
{
btnAddDefenseActionPerformed(evt);
}
});
}
}
private void addDToPanel(int x, int y)
{
squares[x][y].addMouseListener(new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent me)
{
JPanel panel = (JPanel) me.getSource();
int j = (int) (panel.getX() / 145.45454545) + 1;
int i = (int) (panel.getY() / 112.5) + 1;
addDefense(i, j, icon);
icon = "";
FRAME.revalidate();
FRAME.repaint();
}
});
}
private void addDefense(int i, int j, String imageName)
{
try
{
JLabel jlbl = new JLabel();
ImageIcon ii = new ImageIcon(this.getClass().getResource(imageName + ".png"));
jlbl.setIcon(ii);
squares[i][j].add(jlbl, java.awt.BorderLayout.CENTER);
} catch (Exception e)
{
}
}
public void setLvl(int lvl)
{
this.lvl = lvl;
}
public void setVisible(boolean b)
{
FRAME.setVisible(b);
}
This is not my main class, this class is instantiated in the main class and setVisible() = true;
Again thanks in advance!
How do I set a JPanel to accept no more than the original
You can use the Container.getComponentCount() method to check how many components have been added to the panel.
Only add your component when the count is 0.
I have a class called BoardSquare that is an inherited class of JButton. Each of the BoardSquare objects is stored in an array BoardSquare[][] boardsquares. I have used the following code
BoardSquare.boardSquares[j][i].add(new JLabel((j+1)+":"+(i+1)));
to add labels to each of the squares in the array according to their coordinates. I need them to have these labels(I think) so that I can identify them and addActionListeners, etc. How do I make the JLabels invisible so they don't show up in my JFrame?
Alternatively, how can I make the JLabel of each button an instance variable so that I can call JLabel.setVisible(false) but still use them when I add action listeners?
EDIT: If anyone's interested, it's for a Checkers Game.
Here are my classes:
GameWindow
BoardSquare
Checker
MyListener
Thank you for the edit. If this were my application, I'd probably do things very differently including,
Use a grid of JLabels not JButtons. I see no need to use JButtons, and a problem in that the button would not be as visually appealing as other possible solutions.
Either give the JLabel cells or the containing JPanel a MouseListener,
Have the JPanel cells have no Icon and thus be empty if no checker is on them,
Or have them hold an ImageIcon of an appropriately colored checker if they are not empty.
You could even animate the GUI by using the glass pane to hold a JPanel with an appropriate checker ImageIcon that the user can drag.
Note that if you absolutely have to use JButtons, then don't add JLabels to them. Instead simply set the JButton's Icon to null or to an appropriate Checker ImageIcon.
Edit
For example, a bad code example as a proof of concept. Try compiling and running this.
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.*;
#SuppressWarnings("serial")
public class Checkers extends JPanel {
public static final int SIDE_LENGTH = 60;
public static final int ROW_COUNT = 8;
private static final String ROW = "row";
private static final String COLUMN = "column";
private static final Color LIGHT_COLOR = new Color(210, 180, 140);
private static final Color DARK_COLOR = new Color(107, 68, 35);
private Map<Checker, Icon> checkerIconMap = new EnumMap<Checker, Icon>(
Checker.class);
private JLabel[][] labelGrid = new JLabel[ROW_COUNT][ROW_COUNT];
private Checker[][] checkerGrid = new Checker[ROW_COUNT][ROW_COUNT];
public Checkers() {
for (Checker checker : Checker.values()) {
checkerIconMap.put(checker, createCheckerIcon(checker));
}
setLayout(new GridLayout(ROW_COUNT, ROW_COUNT));
for (int row = 0; row < labelGrid.length; row++) {
for (int col = 0; col < labelGrid[row].length; col++) {
checkerGrid[row][col] = Checker.EMPTY;
JLabel gridCell = new JLabel(checkerIconMap.get(Checker.EMPTY));
gridCell.setOpaque(true);
gridCell.putClientProperty(ROW, row);
gridCell.putClientProperty(COLUMN, col);
Color c = row % 2 == col % 2 ? LIGHT_COLOR : DARK_COLOR;
gridCell.setBackground(c);
add(gridCell);
labelGrid[row][col] = gridCell;
}
}
for (int i = 0; i < labelGrid.length / 2 - 1; i++) {
for (int j = 0; j < labelGrid.length / 2; j++) {
int row = i;
int col = j * 2;
col += row % 2 == 0 ? 1 : 0;
labelGrid[row][col].setIcon(checkerIconMap.get(Checker.BLACK));
checkerGrid[row][col] = Checker.BLACK;
row = ROW_COUNT - row - 1;
col = ROW_COUNT - col - 1;
labelGrid[row][col].setIcon(checkerIconMap.get(Checker.RED));
checkerGrid[row][col] = Checker.RED;
}
}
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
private Icon createCheckerIcon(Checker checker) {
BufferedImage img = new BufferedImage(SIDE_LENGTH, SIDE_LENGTH,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setColor(checker.getColor());
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int x = 3;
int y = x;
int width = SIDE_LENGTH - 2 * x;
int height = width;
g2.fillOval(x, y, width, height);
g2.dispose();
return new ImageIcon(img);
}
private class MyMouseAdapter extends MouseAdapter {
private int selectedRow = -1;
private int selectedCol = -1;
private Checker selectedChecker = null;
private JPanel glassPane = null;
private Point p = null;
private JLabel movingLabel = new JLabel(checkerIconMap.get(Checker.EMPTY));
public MyMouseAdapter() {
movingLabel.setSize(movingLabel.getPreferredSize());
movingLabel.setVisible(false);
}
#Override
public void mousePressed(MouseEvent e) {
p = e.getPoint();
for (int row = 0; row < labelGrid.length; row++) {
for (int col = 0; col < labelGrid[row].length; col++) {
JLabel gridCell = labelGrid[row][col];
if (gridCell == getComponentAt(p)) {
if (checkerGrid[row][col] != Checker.EMPTY) {
selectedRow = row;
selectedCol = col;
selectedChecker = checkerGrid[row][col];
checkerGrid[row][col] = Checker.EMPTY;
labelGrid[row][col].setIcon(checkerIconMap.get(Checker.EMPTY));
JRootPane rootPane = SwingUtilities.getRootPane(Checkers.this);
glassPane = (JPanel) rootPane.getGlassPane();
glassPane.setVisible(true);
glassPane.setLayout(null);
movingLabel.setIcon(checkerIconMap.get(selectedChecker));
movingLabel.setVisible(true);
glassPane.add(movingLabel);
int x = p.x - SIDE_LENGTH / 2;
int y = p.y - SIDE_LENGTH / 2;
movingLabel.setLocation(x, y);
}
}
}
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (selectedChecker == null) {
return;
}
p = e.getPoint();
if (!Checkers.this.contains(p)) {
// if mouse releases and is totally off of the grid
returnCheckerToOriginalCell();
clearGlassPane();
return;
}
for (int row = 0; row < labelGrid.length; row++) {
for (int col = 0; col < labelGrid[row].length; col++) {
JLabel gridCell = labelGrid[row][col];
if (gridCell == getComponentAt(p)) {
if (isMoveLegal(row, col)) {
checkerGrid[row][col] = selectedChecker;
labelGrid[row][col].setIcon(checkerIconMap.get(selectedChecker));
// todo: check for jumped pieces...
} else {
// illegal move
returnCheckerToOriginalCell();
}
}
}
}
clearGlassPane();
}
// this code would go in the model class
private boolean isMoveLegal(int row, int col) {
if (checkerGrid[row][col] != Checker.EMPTY) {
// trying to put a checker on another checker
returnCheckerToOriginalCell();
} else if (row == selectedRow && col == selectedCol) {
// trying to put checker back in same position
returnCheckerToOriginalCell();
} else if (row % 2 == col % 2) {
// invalid square
returnCheckerToOriginalCell();
} else {
// TODO: more logic needs to go here to test for a legal move
// and to remove jumped pieces
return true;
}
return false;
}
#Override
public void mouseDragged(MouseEvent e) {
if (selectedChecker == null || p == null) {
return;
}
p = e.getPoint();
int x = p.x - SIDE_LENGTH / 2;
int y = p.y - SIDE_LENGTH / 2;
movingLabel.setLocation(x, y);
}
private void clearGlassPane() {
glassPane.setVisible(false);
movingLabel.setVisible(false);
selectedChecker = null;
p = null;
selectedCol = -1;
selectedRow = -1;
}
private void returnCheckerToOriginalCell() {
checkerGrid[selectedRow][selectedCol] = selectedChecker;
labelGrid[selectedRow][selectedCol].setIcon(checkerIconMap.get(selectedChecker));
}
}
private static void createAndShowGui() {
Checkers mainPanel = new Checkers();
JFrame frame = new JFrame("JLabelGrid");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class CheckerModel {
}
enum Checker {
EMPTY(new Color(0, 0, 0, 0)), RED(Color.red), BLACK(Color.black);
private Color color;
private Checker(Color color) {
this.color = color;
}
public Color getColor() {
return color;
}
}
Better Model-View example being worked on...
Instead of adding the new Jlabel() directly to the array , make an instance first then add that ... i guess this is done in a loop so for example :
JLabel lbl;
for(....) {
lbl = new JLabel(new JLabel((j+1)+":"+(i+1));
lbl.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt()){
// TODO here
}
});
BoardSquare.boardSquares[j][i].add(lbl);