Swing Java and anonymous classes accessing class attributes from outer classes - java

EDIT: I've found that the following code works. It appears there was a slip-up with the earlier code. However, I still have the burning question, of whether this code is good practice? Is this an acceptable method to share the model data underlying the Swing objects between the main application thread and the Swing event dispatch thread?
package com.guitest;
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class Test {
public static void main(String[] args) {
new Test().run();
}
public void run() {
Board board = new Board();
board.createBoard();
board.setTileValue(2, 2, 3);
board.revalidate();
board.repaint();
}
#SuppressWarnings("serial")
public class Board extends JFrame {
final int tileSize = 100;
final int numberOfRows = 2;
final int numberOfCols = 3;
private final Map<Integer, Integer> _tiles;
public Board() {
_tiles = Collections.synchronizedMap(new HashMap<Integer, Integer>(numberOfRows*numberOfCols));
for (int row = 0; row < numberOfRows; row++) {
for (int col = 1; col <= numberOfCols; col++) {
_tiles.put(row*numberOfCols+col, 1);
}
}
}
public void setTileValue(int row, int col, int value) {
_tiles.put(row*(numberOfCols-1)+col, value);
}
public void createBoard() {
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
setLayout(new GridLayout(numberOfRows, numberOfCols, 0, 0));
for (int row = 0; row < numberOfRows; row++) {
for (int col = 1; col <= numberOfCols; col++) {
add(createPanelFor(row, col));
}
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(numberOfCols*tileSize, numberOfRows*tileSize);
setVisible(true);
}
});
}
public JPanel createPanelFor(final int row, final int col) {
return new JPanel() {
#Override protected void paintComponent(Graphics g) {
g.setColor((col % 2 == 0) == (row % 2 == 0) ? Color.BLACK : Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
String string = String.valueOf(_tiles.get(row*numberOfCols+col));
g.setColor(Color.RED);
g.drawString(string, getHeight() / 2, getWidth() / 2);
}
};
}
}
}

Related

How do I change the color of a square once pressed on?

Right now I have code to be able to randomize colored squares over a 25x25 board. What I'm trying to do is be able to make those colored squares turn white once pressed on and once it turns white, you can't reverse it. I was thinking about using Listeners but I'm not sure how to start.
Here is what I have to create the randomized squares.
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
public class ColoredBoxes {
//Selected Colors
private Color[] availableColors = new Color[] {Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN};
public static void main(String[] args) {
new ColoredBoxes();
}
public ColoredBoxes() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Collapse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
//Size of the board
protected static final int ROWS = 25;
protected static final int COLS = 25;
protected static final int BOX_SIZE = 25;
private List<Color> colors;
//RandomColors across the given board size.
public TestPane() {
int length = ROWS * COLS;
colors = new ArrayList<Color>();
for (int index = 0; index < length; index++) {
int randomColor = (int) (Math.random() * availableColors.length);
colors.add(availableColors[randomColor]);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(COLS * BOX_SIZE, ROWS * BOX_SIZE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
System.out.println("...");
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int index = (row * COLS) + col;
g2d.setColor(colors.get(index));
g2d.fillRect(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
g2d.dispose();
}
}
}
Any help is much appreciated.
To change color on click, you just need a MouseListener, in the mouseClicked() method you must convert the click coordinates to row and column of the color grid, change that color and then ask the component to repaint.
Here the implementation, I just replaced your 1-dimensional color list with a 2-dimension color array, since it simplify the representation and the conversion from x,y to row,col.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ColoredBoxes {
//Selected Colors
private Color[] availableColors = new Color[] {Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN};
//This is the color that will be set when a cell is clicked
private static final Color CLICKED_COLOR = Color.white;
public static void main(String[] args) {
new ColoredBoxes();
}
public ColoredBoxes() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Collapse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
//Size of the board
protected static final int ROWS = 25;
protected static final int COLS = 25;
protected static final int BOX_SIZE = 25;
//Since you have a ROWSxCOLS color grid better use a 2-dimension array
private Color[][] cells;
//RandomColors across the given board size.
public TestPane() {
cells=new Color[ROWS][COLS];
for (int i=0;i<cells.length;i++) {
for (int j=0;j<cells[i].length;j++) {
int randomColor = (int) (Math.random() * availableColors.length);
cells[i][j]=availableColors[randomColor];
}
}
//Here the mouse listener, we only need to manage click events
//so I use a MouseAdapter to not implement the complete MouseListener interface
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
onClick(e);
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(COLS * BOX_SIZE, ROWS * BOX_SIZE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
System.out.println("...");
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
g2d.setColor(cells[row][col]);
g2d.fillRect(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
g2d.dispose();
}
//Finally the click handler
protected void onClick(MouseEvent e) {
//Convert mouse x,y (that are relative to the panel) to row and col
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
int row=(e.getY()-yOffset)/BOX_SIZE;
int col=(e.getX()-xOffset)/BOX_SIZE;
//Check that we are in the grid
if (row>=0&&row<ROWS&&col>=0&&col<COLS) {
//Set new color
cells[row][col]=Color.white;
//Repaint, only the changed region
repaint(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
}
}
You could use GridPane layout with a custom class for representing the squares
I have a working example here if you want to check
All squares handle their own painting
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
public class ColoredBoxes {
//Selected Colors
private Color[] availableColors = new Color[]{Color.YELLOW, Color.RED, Color.BLUE, Color.GREEN};
public ColoredBoxes() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Collapse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
new ColoredBoxes();
}
public class TestPane extends JPanel {
//Size of the board
protected static final int ROWS = 25;
protected static final int COLS = 25;
protected static final int BOX_SIZE = 25;
private List<Square> colors; // List of the representation of the Squares
//RandomColors across the given board size.
public TestPane() {
int length = ROWS * COLS;
GridLayout gridLayout = new GridLayout(ROWS, HEIGHT, 0, 0);
this.setLayout(gridLayout);
colors = new ArrayList<>();
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int randomColor = (int) (Math.random() * availableColors.length);
Square temp = new Square(availableColors[randomColor], row, col);
colors.add(temp);
this.add(temp);
}
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(COLS * BOX_SIZE, ROWS * BOX_SIZE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int xOffset = (getWidth() - (COLS * BOX_SIZE)) / 2;
int yOffset = (getHeight() - (ROWS * BOX_SIZE)) / 2;
System.out.println("...");
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
int index = (row * COLS) + col;
g2d.setColor(colors.get(index).getColor());
g2d.fillRect(xOffset + (col * BOX_SIZE), yOffset + (row * BOX_SIZE), BOX_SIZE, BOX_SIZE);
}
}
g2d.dispose();
}
}
public class Square extends JPanel {
private Color color;
private boolean clicked = false;
private int row;
private int col;
public Square(Color color, int row, int col) {
this.row = row;
this.col = col;
this.color = color;
this.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
if (!clicked) {
//do stuff
Square source = (Square) e.getSource();
source.setColor(Color.white);
repaint();//Dont forget the repaint method
clicked = true;
}
}
#Override
public void mousePressed(MouseEvent e) {
if (!clicked) {
//do stuff
Square source = (Square) e.getSource();
source.setColor(Color.white);
repaint();//Dont forget the repaint method
clicked = true;
}
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillRect(0, 0, getWidth(), getHeight());
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
}

Can't drag circles like example in book(Applet)

So my university uses the book Java programming from problem analysis to program design by DS Malik(ISBN: 978-1-111-53053-2) and in one of the examples I copied the code word for word. It runs but doesn't work the way its supposed too. What you're supposed to do is be able to click and drag circles that populate the screen in an applet. If anyone is interested in the programming example its 12-10. I have provided the code from eclipse. Any and all help is appreciated.
import javax.swing.*;
import java.awt.event.*;
import java.applet.*;
import java.awt.*;
public class FreeDrawApplet extends JApplet implements MouseMotionListener
{
//instance variables
ColorCircle[] myGraph;
final int NUM_CIRCLES = 7;
final int WIDTH = 400;
final int HEIGHT = 400;
public class ColorCircle
{
private int x;
private int y;
public void setx(int iNewX)
{
x = iNewX;
}
public void sety(int iNewY)
{
x = iNewY;
}
public void paint (Graphics g)
{
g.fillOval(x-10, y-10, 20, 20);
}
public boolean selected(int iXcoord, int iYcoord)
{
if ((iXcoord >= x-10) && (iXcoord <= x+10) && (iYcoord >= y-10) && (iYcoord <= y+10))
return true;
else
return false;
}
}//end of public class circle
public void init ()
{
addMouseMotionListener(this);
myGraph = new ColorCircle[NUM_CIRCLES];
for(int i = 0; i < NUM_CIRCLES; i++)
{
ColorCircle myVertex = new ColorCircle();
myVertex.setx((int)(Math.random() * (WIDTH-50)));
myVertex.sety((int)(Math.random() * (HEIGHT-100)));
myGraph[i] = myVertex;
}
JOptionPane.showMessageDialog(null, "Try to drag any one of the colored circles ", "Information", JOptionPane.PLAIN_MESSAGE);
}//end of method
public void paint(Graphics g)
{
Color[] myColor = {Color.black, Color.red, Color.blue, Color.green, Color.cyan, Color.orange, Color.yellow};
if(NUM_CIRCLES > 0)
for(int i =0; i < NUM_CIRCLES; i++)
{
g.setColor(myColor[i]);
myGraph[i].paint(g);
}
}//end of paint method
public void mouseDragged(MouseEvent event)
{
int iX = event.getX();
int iY = event.getY();
for(int i = 0; i < NUM_CIRCLES; i++)
{
if(myGraph[i].selected(iX, iY))
{
myGraph[i].setx(iX);
myGraph[i].sety(iY);
break;
}
}
repaint();
}
public void mouseMoved(MouseEvent p1)
{
}
}

Java - Add shape to frame

I create a JFrame, followed by a JPanel and the set the parameters. I have a JPanel called boardSquares where each square would be coloured later on.
Once I attempt to add the checker to the board, the board colours are re-arranged.
I have had numerous attempts to fix this but have not succeeded. I am also sure that there is a better way to do this. Below is some code. All help is appreciated!
public void paintComponent(Graphics g)
{
g.setColor(Color.BLUE);
g.fillOval(0, 0, 30, 30);
}
public static void checkerBoard()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
boardSquares[i][j] = new JPanel();
if ((i + j) % 2 == 0)
{
boardSquares[i][j].setBackground(Color.BLACK);
}
else
{
boardSquares[i][j].setBackground(Color.WHITE);
}
frameOne.add(boardSquares[i][j]);
}
}
}
Look at this example https://www.javaworld.com/article/3014190/learn-java/checkers-anyone.html
And I've little bit upgrade your example
Sorry, I don't have much time for it
import java.awt.*;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.Color;
import java.awt.Graphics;
public class Circle extends JPanel
{
public static JFrame frameOne = new JFrame("Frame 1");
public static Circle boardSquares[][] = new Circle[8][8];
public static void main(String[] args)
{
checkerBoard();
frameOne.setSize(new Dimension(400,400));
frameOne.getContentPane().setLayout(new GridLayout(8,8,0,0));
frameOne.setBackground(Color.BLACK);
frameOne.setVisible(true);
frameOne.setResizable(false);
frameOne.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
boardSquares[1][1].setChecker(true);
}
private Color c;
private boolean checker;
public Circle(int i, int j) {
super();
//setBorder(new Border());
//set
if ((i + j) % 2 == 0)
{
c = Color.DARK_GRAY;
}
else
{
c = Color.WHITE;
}
}
void setChecker(boolean ch) {
checker = ch;
}
public static void checkerBoard()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
boardSquares[i][j] = new Circle(i, j);
frameOne.add(boardSquares[i][j]);
}
}
}
public void paintComponent(Graphics g)
{
g.setColor(c);
g.fillRect(0, 0, 40, 40);
if (checker) {
g.setColor(Color.BLUE);
g.fillOval(4, 4, 32, 32);
}
}
}
I would create a separate board class and override the paintComponent method to draw the actual grid.
Then I would give the board a grid layout and add panels to hold the checkers.
There is an issue with the margin of the checker, but that may be due to the size of the panels. You can mess around with this. I fixed this by applying a border layout to the panel.
Finally, avoid using "magic numbers". Try to declare some instance variables inside your classes and pass their value in via the constructor or some setter/mutator methods.
Application.java
package game.checkers;
import java.awt.*;
import java.lang.reflect.InvocationTargetException;
import javax.swing.SwingUtilities;
public class Application implements Runnable {
public static final String APP_NAME = "Checkers Game";
private GameFrame gameFrame;
private GameBoard checkerBoard;
#Override
public void run() {
initialize();
Checker redChecker = new Checker(50, Color.RED);
Checker greenChecker = new Checker(50, Color.GREEN);
Checker blueChecker = new Checker(50, Color.BLUE);
checkerBoard.placeChecker(redChecker, 1, 5);
checkerBoard.placeChecker(greenChecker, 2, 4);
checkerBoard.placeChecker(blueChecker, 3, 3);
redChecker.addMouseListener(new CheckerMouseListener(redChecker));
greenChecker.addMouseListener(new CheckerMouseListener(greenChecker));
blueChecker.addMouseListener(new CheckerMouseListener(blueChecker));
}
protected void initialize() {
gameFrame = new GameFrame(APP_NAME);
checkerBoard = new GameBoard(8, 8);
checkerBoard.setPreferredSize(new Dimension(400, 400));
gameFrame.setContentPane(checkerBoard);
gameFrame.pack();
gameFrame.setVisible(true);
}
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Application());
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
}
GameFrame.java
package game.checkers;
import javax.swing.JFrame;
public class GameFrame extends JFrame {
private static final long serialVersionUID = 6797487872982059625L;
public GameFrame(String title) {
super(title);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
GameBoard.java
package game.checkers;
import java.awt.*;
import javax.swing.JPanel;
public class GameBoard extends JPanel {
private static final long serialVersionUID = 5777309661510989631L;
private static final Color[] DEFAULT_TILE_COLORS = new Color[] { Color.LIGHT_GRAY, Color.WHITE };
private BoardZone[][] zones;
private Color[] tileColors;
private int rows;
private int cols;
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getCols() {
return cols;
}
public void setCols(int cols) {
this.cols = cols;
}
public GameBoard(int rows, int cols, Color[] tileColors) {
super();
this.rows = rows;
this.cols = cols;
this.tileColors = tileColors;
initialize();
}
public GameBoard(int rows, int cols) {
this(rows, cols, DEFAULT_TILE_COLORS);
}
protected void initialize() {
this.setLayout(new GridLayout(rows, cols, 0, 0));
generateZones();
}
private void generateZones() {
this.setLayout(new GridLayout(rows, cols, 0, 0));
this.zones = new BoardZone[rows][cols];
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
this.add(zones[row][col] = new BoardZone());
}
}
}
public void placeChecker(Checker checker, int row, int col) {
zones[row][col].add(checker);
}
public Checker getChecker(int row, int col) {
return (Checker) zones[row][col].getComponent(0);
}
public void removeChecker(Checker checker, int row, int col) {
zones[row][col].remove(checker);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int tileWidth = this.getWidth() / cols;
int tileHeight = this.getHeight() / rows;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
int x = col * tileWidth;
int y = row * tileHeight;
g.setColor(tileColors[(row + col) % 2]);
g.fillRect(x, y, tileWidth, tileHeight);
}
}
}
}
Checker.java
package game.checkers;
import java.awt.*;
import javax.swing.JComponent;
public class Checker extends JComponent {
private static final long serialVersionUID = -4645763661137423823L;
private int radius;
private Color color;
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public String getHexColor() {
return String.format("#%06X", getColor() == null ? 0 : getColor().getRGB());
}
public Checker(int radius, Color color) {
super();
this.setPreferredSize(new Dimension(radius, radius));
this.radius = radius;
this.color = color;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (this.radius <= 0 || this.color == null) {
return; // Do not draw it.
}
g.setColor(this.color);
g.fillOval(0, 0, this.radius - 1, this.radius - 1);
}
}
BoardZone.java
package game.checkers;
import java.awt.BorderLayout;
import javax.swing.JPanel;
public class BoardZone extends JPanel {
private static final long serialVersionUID = 8710283269464564251L;
public BoardZone() {
this.setOpaque(false);
this.setLayout(new BorderLayout());
}
}
CheckerMouseListener.java
package game.checkers;
import java.awt.event.*;
public class CheckerMouseListener implements MouseListener {
private Checker target;
public CheckerMouseListener(Checker target) {
this.target = target;
}
private String getCheckerName() {
String hexCode = target.getHexColor();
switch (hexCode) {
case "#FFFF0000":
return "RED";
case "#FF00FF00":
return "GREEN";
case "#FF0000FF":
return "BLUE";
default:
return hexCode;
}
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println("Released click over " + getCheckerName() + " checker.");
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("Pressed on " + getCheckerName() + " checker.");
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println("Finished hovering over " + getCheckerName() + " checker.");
}
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("Began hovering over " + getCheckerName() + " checker.");
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Clicked on " + getCheckerName() + " checker.");
}
}

Game of Life - Java, doesn't work (not showing cells)

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
+ "]";
}
}

How Do I Make These JLabels of JButtons invisible

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);

Categories