I need help changing the color of a rectangle in a grid. So far, I have the rectangles and the grid (which are lines drawn separating the rectangles), and I want to change the color of a single rectangle when it's clicked.
I added the line "System.out.println("Something")" in the loop where the color is supposed to change, and it always returns "Something." That's why I'm confused. Thanks for any and all help!
Class Grid:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.Timer;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Grid extends JPanel{
private int a = 50;
private int b = 50;
private Lifeform[][] Life;
private boolean[][]life = new boolean[a][b];
private Timer t;
Grid(){
//creates grid of rectangles
Life = new Lifeform[a][b];
int ypos = 0;
for(int i = 0; i < Life.length; i++){
int xpos = 0;
for(int j = 0; j < Life[0].length; j++){
Rectangle r = new Lifeform();
r.setBounds(xpos, ypos, 50, 50);
Life[i][j] = (Lifeform) r;
xpos += 50;
}
ypos += 50;
}
t = new Timer(64, new Movement());
this.addMouseListener(new mouse());
}
public void paintComponent(Graphics g){
for(Lifeform[] n : Life){
//makes rectangles white
g.fillRect(this.getX(), this.getY(), this.getWidth(), this.getHeight());
g.setColor(Color.white);
}
for (int i = 0; i <= 25; i++){
g.drawLine(0, 50*i, 1500, 50*i);
g.setColor(Color.black);
}
for (int i = 0; i <= 25; i++){
g.drawLine(50*i, 0, 50*i, 750);
g.setColor(Color.black);
}
}
private JFrame createGrid(){
JFrame frame = new JFrame("Alveolate");
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(700,700);
frame.setVisible(true);
return frame;
}
public class mouse implements MouseListener{
//colors rectangles (it doesn't work)
public void mouseClicked(MouseEvent e) {
Point p = new Point(e.getX(),e.getY());
for(int i = 0; i < Life.length; i++){
for(int j = 0; j < Life[i].length; j++){
Lifeform spot = Life[i][j];
if (spot.contains(p)){
spot.setColor(Color.red);
System.out.println("Something");
}
}
}
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
public class Movement implements ActionListener{
public void actionPerformed ( ActionEvent e ){
for (int i = 0; i < Life.length; i++){
for (int j = 0; j < Life[i].length; j++){
if(Life[i][j].getColor().equals(Color.black)){
life[i][j] = true;
}
else{
life[i][j] = false;
}
}
}
repaint();
}
}
public void startTimer(){
t.start();
}
public void stopTimer(){
t.stop();
}
public static void main(String[] args) {
Grid ABC = new Grid();
ABC.createGrid();
ABC.startTimer();
}
}
Class Lifeform:
import java.awt.Color;
import java.awt.Rectangle;
public class Lifeform extends Rectangle {
private Color c;
public Lifeform() {
c = Color.WHITE;
}
public Color getColor() {
return c;
}
public boolean setColor( Color c ) {
boolean rtn = false;
if( c != null ) {
this.c = c;
rtn = true;
}
return rtn;
}
}
try
for(Lifeform[] n : Life){
for(Lifeform lf : n){
g.setColor(lf.getColor());
g.fillRect((int)lf.getX(), (int)lf.getY(), (int)lf.getWidth(), (int)lf.getHeight());
}
}
in your paintComponent method
try this:
for(int i = 0; i < 50; i++){
for(int j = 0; j < 50; j++){
....
}
}
Didn't read all you code but it seems like you definitely set the color of your Lifeform to red. This means that your rendering code never actually uses this fact to display that Lifeform. It seems like the only time you draw your rectangles is in paintComponent. This paint needs to be called each time you want a redraw to happen. You can use repaint on your JFrame or JPanel to get this to happen. Also, the render code you have there seems to only ever display white rectangles
g.fillRect(this.getX(), this.getY(), this.getWidth(), this.getHeight());
g.setColor(Color.white);
This is in a loop through your Lifeform[][]. Instead you should probably have a double for loop to get every Lifeform and use the x and y and color from that to draw. Something like:
g.fillRect(Life[i][j].getX(), Life[i][j].getY(), ..., ..., Life[i][j].getColor())
Also, Life should be named life with a lowercase 'l'. It's way confusing seeing names without conventions.
Related
I'm currently trying to reproduce the Game of Life. The implementation is done, but I want to add a painting mode. If this mode is activated the user should be able to turn every dead cell the mouse is currently on into a living one by dragging their mouse over them (dragging, not clicking, just like drawing something in Paint). Each JLabel-object on the grid represents one cell. The state of the cell is determined by its color. I got the paint-mode to work, but it only works when I start dragging the mouse on the background of the JPanel, if I start doing it on a JLabel, it does nothing. Should I perhaps use something else than a JPanel? Here is my code so far (CellLabel inherits from JLabel):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.Random;
public class CellLabelGrid extends JPanel {
private final CellGrid cellGrid;
private final CellLabel[][] cellLabels;
private Color aliveColor;
private Color deadColor;
public CellLabelGrid(Game game, int rows, int cols) {
initializeColors();
this.cellGrid = new CellGrid(rows, cols);
this.cellLabels = new CellLabel[rows][cols];
this.setLayout(new GridLayout(rows, cols));
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
CellLabel cellLabel = new CellLabel(game, cellGrid.getCellAtIndex(i, j), aliveColor, deadColor);
cellLabels[i][j] = cellLabel;
this.add(cellLabel);
}
}
this.setBackground(Color.WHITE);
this.setPreferredSize(new Dimension(rows * 50, cols * 50));
MouseMotionListener mouseMotionListener = new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
if (game.getGameMode().equals(Mode.PAINT)) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (mouseX >= cellLabels[i][j].getX() && mouseX <= cellLabels[i][j].getX() + cellLabels[i][j].getWidth() && mouseY >= cellLabels[i][j].getY() && mouseY <= cellLabels[i][j].getY() + cellLabels[i][j].getHeight()) {
if (cellLabels[i][j].getBackground().equals(deadColor)) {
cellLabels[i][j].setBackground(aliveColor);
cellLabels[i][j].getCell().setState(CellState.ALIVE);
}
}
}
}
}
}
#Override
public void mouseMoved(MouseEvent e) {
}
};
this.addMouseMotionListener(mouseMotionListener);
this.setVisible(true);
}
public CellGrid getCellGrid() {
return cellGrid;
}
public CellLabel[][] getCellLabels() {
return cellLabels;
}
private void initializeColors() {
Random rand = new Random();
float r = rand.nextFloat();
float g = rand.nextFloat();
float b = rand.nextFloat();
aliveColor = new Color(r, g, b);
float r2 = rand.nextFloat();
float g2 = rand.nextFloat();
float b2 = rand.nextFloat();
deadColor = new Color(r2, g2, b2);
}
public Color getAliveColor() {
return aliveColor;
}
public Color getDeadColor() {
return deadColor;
}
}
The printout of the array lifegrid2 just gives all zeros. I tested the lifegrid array in MyPanel and that is populating, but the values are pulling through as zeros. I checked by putting some values in lifegrid2 and they are being wiped, so it is pulling through from MyPanel, but only zeros. There are no errors being reported.
I have made a small test program with a 2d array which does pull values through.
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import java.awt.*;
import java.awt.event.*;
public class SwingPaintDemo3 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame f = new JFrame("Swing Paint Demo");
f.setPreferredSize(new Dimension(1280,800));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
JPanel subPanel = new JPanel();
JButton start = new JButton("START");
subPanel.add(start);
start.setPreferredSize(new Dimension(100,50));
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae1) {
System.out.println("START");
int [][][] lifegrid2 = new int [12][12][2];
int temp;
for (int i=0; i<12; i++) {
for (int j=0; j<12; j++) {
**MyPanel obj = new MyPanel();
temp = obj.lifegrid [i][j][0];
lifegrid2 [i][j][0] = temp;**
if (j<11)
{System.out.print(lifegrid2 [j] [i] [0]);}
else
{System.out.println(lifegrid2 [j] [i] [0]);}}}
}
});
f.add(subPanel, BorderLayout.EAST);
}
}
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
class MyPanel extends JPanel {
public int [][][] lifegrid = new int [12][12][2];
private int squareX = 1280;
private int squareY = 800;
private int gridX, gridY ;
public MyPanel() {
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
squareX = e.getX();
squareY = e.getY();
if ((squareX>50 & squareX <550) & (squareY>50 & squareY <550) ){
gridX =(squareX-50)/50+1;
gridY =(squareY-50)/50+1;
squareX = (squareX -50)/50 * 50 + 50;
squareY = (squareY -50)/50 * 50 + 50;
System.out.println(gridX + " " + gridY);
lifegrid [gridX] [gridY] [0] = 1;
repaint(squareX,squareY,50,50);}
else {
}
}
});
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("This is my custom Panel!",10,20);
g.setColor(Color.RED);
g.fillRect(squareX,squareY,48,48);
g.setColor(Color.BLACK);
g.drawRect(squareX,squareY,48,48);
}
}
I have made a small test program with a 2d array
int [][][] lifegrid2 = new int [12][12][2];
That is a 3D array.
A 2D array is defined as:
int [][] lifegrid2 = new int [12][12];
The logic to initialize the array belongs in the constructor of your class:
MyPanel()
{
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
lifegrid [i][j] = 0)
}
}
}
Then your paintComponent() method needs to iterate through the 2D grid and only paint the grids that have a value of 1.
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
if (lifegrid[i][j] = 1)
// paint the grid
}
}
}
}
Edit:
As best as I can tell you are trying to create a grid based game. When you click on a cell in the grid the cell turns red. The are two common ways to approach this:
Use components. In this approach you have a parent panel using a GridLayout and you add a child panel to each cell in the grid. You would also add your MouseListener to each child panel. When you click on the child panel you change the background of the panel to red.
Do custom painting. In this approach you have a single JPanel. This class keep a 2D Array for the "state" of each cell in the grid. You add a single MouseListener to the panel. When you click on the panel you determine which cell was clicked and then you update the state of that cell. In the paintComponent() method you iterate through the 2D Array and paint each cell where that state has changed.
Your approach seems to be some kind of hybrid between the two and is not working.
Hello sorry I'm very weak in programming.
I'm trying to make my Box each a different shade of green. However, when I implement my code it keeps changing colors even when my box loop is finished.
The finished product is suppose to be a tetris with boxes that have different color of green.
So tetris class creates a lot of boxes in a array .
The method for the tetris is to create each box having its unique position of i and j
import javax.swing.*;
import java.awt.*;
class Main extends JFrame {
class App extends JPanel {
Grid grid;
public App() {
setPreferredSize(new Dimension(900, 720));
grid = new Grid();
}
#Override
public void paint(Graphics g) {
grid.paint(g, getMousePosition());
}
}
public static void main(String[] args) throws Exception {
Main window = new Main();
window.run();
}
private Main() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
App canvas = new App();
this.setContentPane(canvas);
this.pack();
this.setVisible(true);
}
public void run() {
while (true) {
this.repaint();
}
}
}
import java.awt.*;
class Grid {
//fields
Cell[][] cells = new Cell[20][20];
// constructor
public Grid(){
for(int i = 0; i < cells.length; i++){
for(int j = 0; j < cells[i].length; j++){
cells[i][j] = new Cell(10+35*i,10+35*j);
}
}
}
// methods
public void paint(Graphics g, Point mousePos){
for(int i = 0; i < cells.length; i++){
for(int j = 0; j < cells[i].length; j++){
cells[i][j].paint(g, mousePos);
}
}
}
}
import java.awt.*;
import java.util.Random;
class Cell extends Rectangle {
// fields
int random_int;
int minyellow = 50;
int maxyellow = 100;
static int size = 35;
//constructors
public Cell(int x, int y){
super(x,y,size,size);
}
//methods
void paint(Graphics g, Point mousePos){
int random_int = (int)(Math.random() * (maxyellow - minyellow + 1) + minyellow);
this.random_int=random_int;
if(contains(mousePos)){
g.setColor(Color.GRAY);
}
else {
g.setColor(Color.getHSBColor(255, random_int, 60));
}
g.fillRect(x,y,size,size);
g.setColor(Color.BLACK);
g.drawRect(x,y,size,size);
}
public boolean contains(Point p){
if (p != null){
return super.contains(p);
} else {
return false;
}
}
}
A problem in your code is that you pick the random number for your colour inside Cell's paint method, so every time it is painted, it gets a new random colour.
For a cell to have a stable colour, the simplest fix is to set random_int once, in the constructor, and not update it.
public Cell(int x, int y) {
super(x, y, size, size);
random_int = (int) (Math.random() * (maxyellow - minyellow + 1) + minyellow);
}
void paint(Graphics g, Point mousePos) {
if (contains(mousePos)) {
g.setColor(Color.GRAY);
}
else {
g.setColor(Color.getHSBColor(255, random_int, 60));
}
g.fillRect(x,y,size,size);
g.setColor(Color.BLACK);
g.drawRect(x,y,size,size);
}
Whenever I tried to run the program, yes the text is moving but it leaves a trace of its last position. Like for example the text "test" is in first positioned at x=50, y=100 then in the next update, the x=50, y=120. The problem is, the last position which is the x=50, y=100 is still in display. I would like to remove the last position of the text every time it updates.
Can you guys help me?
(The j label is in the Action performed method)
This is my core class.
package GAME;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class GameFrame extends JPanel implements ActionListener{
Image background = Toolkit.getDefaultToolkit().createImage("D:\\SHIPMATH TEXTURES\\simple-water-animation-597-x-800.gif");
Timer mainTimer;
shipPlayer player;
enemyShips enemy;
int level = 5;
int enemyCount = 5;
int numCount = 10;
int y=0;
// arraylists are arrays that has no capacity limit
static ArrayList<Numbers> number = new ArrayList<Numbers>();
static ArrayList<enemyShips> enemies = new ArrayList<enemyShips>();
static ArrayList<Cannons> cannon_balls = new ArrayList<Cannons>();
JLabel numbers;
Random rn = new Random();
public GameFrame() {
// calls the actionPerformed method every 10 milliseconds
mainTimer = new Timer(10, this);
mainTimer.start();
setLayout(null);
setFocusable(true);
player = new shipPlayer(0, 500);
addKeyListener(new KeyAdapt(player));
startGame();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(background, 0, 0, this);
player.draw(g2d);
repaint();
for(int i=0; i<enemies.size(); i++) {
// the value of 'i' is the location/index used to find the value stored in the ArrayList
enemyShips enemy = enemies.get(i);
enemy.draw(g2d);
}
for(int i=0; i<cannon_balls.size(); i++) {
Cannons cannon = cannon_balls.get(i);
cannon.draw(g2d);
}
}
public void actionPerformed(ActionEvent e) {
player.update();
// where movement of the enemy happens
for(int i=0; i<enemies.size(); i++) {
enemyShips enemy = enemies.get(i);
enemy.update();
}
// Later...
for(int i=0; i<cannon_balls.size(); i++) {
Cannons cannon = cannon_balls.get(i);
cannon.update();
}
/////////////////////////////////////
y++;
numbers = new JLabel("TEST");
numbers.setBounds(200, y, 100, 100);
add(numbers);
////////////////////////////////////
repaint();
}
public static void addEnemy(enemyShips e) {
enemies.add(e);
// stores what the user puts in the enemyShips' object into the ArrayList "enemies"
}
public static void removeEnemy(enemyShips e) {
enemies.remove(e);
// removes what the user inputs from the ArrayList
}
public static ArrayList<enemyShips> getEnemyList() {
return enemies;
}
public static void addNumbers(Numbers n) {
number.add(n);
}
public static void addCannons(Cannons c) {
cannon_balls.add(c);
// stores what the user puts in the Cannons' object into the ArrayList "cannon_balls"
}
public static void removeCannons(Cannons c) {
cannon_balls.remove(c);
// removes what the user inputs from the ArrayList
}
public static ArrayList<Cannons> getCannonsList() {
return cannon_balls;
}
public void startGame() {
// enemyCount = level * 5;
// runs 5 times
for(int x=0; x<enemyCount; x++) {
addEnemy(new enemyShips(rn.nextInt(500), -rn.nextInt(800)));
}
}
}
This is the output of this program.
Click here for the output of the program
you can use getContentPane().repaint() over and over in a loop or something else like some sort of timer.
I am currently working on creating the game Snake. I had the idea of creating a basic 2-dimensional arraylist so I can create cells but I can't find any form of help on creating that 2d arraylist to store the x and y values of each of the cells. I need help on how to create that 2d arraylist and how to use it.
Snake.java
package snake;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.List;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Snake extends JPanel implements KeyListener {
private static final long serialVersionUID = 1L;
static final int BOX_WIDTH = 600;
static final int BOX_HEIGHT = BOX_WIDTH;
int UPDATE_RATE = 300;
ArrayList<Cell> CellList = new ArrayList<Cell>();
//ode below????
//2d arrayList
ArrayList[][] Cell = new ArrayList[10][10];
public Snake() {
setPreferredSize(new Dimension(BOX_WIDTH, BOX_HEIGHT));
/*for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
CellList.add(new Cell(i,j));
}
} */
Thread gameThread = new Thread() {
public void run() {
while(true){
repaint();
try {Thread.sleep(1000/UPDATE_RATE);}
catch (InterruptedException ex) {}
}
}
};
gameThread.start();
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("SNEK");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Snake snake = new Snake();
frame.setContentPane(snake);
frame.setSize(BOX_WIDTH, BOX_HEIGHT);
frame.pack();
frame.addKeyListener(snake);
frame.setVisible(true);
}
});
}
public void paintComponent(Graphics g) {
g.setColor(Color.pink);
g.fillRect(0, 0, BOX_WIDTH, BOX_HEIGHT);
/*for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
CellList.get(i,j).draw(g);
}
} */
}
#Override
public void keyPressed(KeyEvent arg0) {
}
#Override
public void keyReleased(KeyEvent arg0) {
}
#Override
public void keyTyped(KeyEvent arg0) {}
}
Cell.java
package snake;
import java.awt.Color;
import java.awt.Graphics;
public class Cell extends Snake{
private static final long serialVersionUID = 1L;
final int CELL_HEIGHT = 10;
final int CELL_WIDTH = 10;
int status = 0;
int xPos;
int yPos;
public Cell(int x, int y) {
xPos = x * 120;
yPos = y * 120;
}
public void draw(Graphics g) {
g.setColor(Color.magenta);
g.fillRect(xPos, yPos, CELL_WIDTH, CELL_HEIGHT);
}
}
If you want to make games using java, I suggest you to use game-development application framework-libGDX
Download: https://libgdx.badlogicgames.com/download.html
It's easy to use, plus you build games for desktop,android,ios and html at the same time.There are lots of tutorial on YouTube about libGDX.
Here are some of them:
https://www.youtube.com/watch?v=QKK4kDogg-8&list=PLaNw_AbDFccHbzuObI4xHHp6WtiN2cRQv
https://www.youtube.com/watch?v=EJwXzmUQChg&list=PLXY8okVWvwZ0JOwHiH1TntAdq-UDPnC2L
https://www.youtube.com/watch?v=a8MPxzkwBwo&list=PLZm85UZQLd2SXQzsF-a0-pPF6IWDDdrXt
You most certainly don't need a 2d array list.
Instead, you need a 2d array of Cells:
Instead of this:
ArrayList[][] Cell = new ArrayList[10][10];
Use this:
Cell[][] cells = new Cell[10][10];
Then in the constructor:
public Snake() {
setPreferredSize(new Dimension(BOX_WIDTH, BOX_HEIGHT));
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
cells[i][j] = new Cell(/*do what ever you ned here*/);
}
}
...