Reputation: 33
The problem in my code is that, I tried to make a program that when you click a cell in the grid, a circle should appear inside that cell. I am good with that. However, when you click for the second time, the circle should disappear. I don't know how to do that.
I tried repainting the circle to the same color as background in the implemented method, mouse-pressed, but that wasn't very effective. It only "disappears" when you press it, but I want it to disappear when it's clicked.
I wrote it into mouse-pressed, because I didn't know how to use that in mouse-clicked method.
Here's my code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
/**
* In this program, when user clicks a square, a circle appears until the user clicks it again.
*/
public class DD_GridFiller extends JFrame {
private int gridRows;
private int gridColumns;
private Color[][] circleColor; //color of circles
private Color lineColor; //color of lines
/**
* constructor
*/
public DD_GridFiller() {
setTitle("My Grid Filler");
setSize(600,600);
setLayout(new GridLayout(4,4));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
circleColor = new Color[4][4]; //stores the colors in arrays
gridRows = 4;
gridColumns = 4;
lineColor = Color.RED;
setPreferredSize( new Dimension(90*4, 90*4) );
setBackground(Color.BLACK); // set the background color for this panel.
addMouseListener(new MouseListener());
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int top, left; // position for top left corner of the window
left = ( screenSize.width - getWidth() ) / 2;
top = ( screenSize.height - getHeight() ) / 2;
setLocation(left,top);
setResizable(false);
setVisible(true);
pack();
}
public void paint(Graphics g) {
g.setColor(getBackground());
g.fillRect(0,0,getWidth(),getHeight());
int row, col;
double cellWidth = (double)getWidth() / gridColumns; //get cell width
double cellHeight = (double)getHeight() / gridRows; //get cell height
//create circles in every cell
for (row = 0; row < gridRows; row++) {
for (col = 0; col < gridColumns; col++) {
if (circleColor[row][col] != null) {
int x1 = (int)(col*cellWidth);
int y1 = (int)(row*cellHeight);
g.setColor(circleColor[row][col]);
g.fillOval(x1-2, y1-2, 23*4, 23*4);
}
}
}
//CREATES THE LINES
if (lineColor != null) {
g.setColor(lineColor);
for (row = 1; row < gridRows; row++) {
int y = (int)(row*cellHeight);
g.drawLine(0,y,getWidth(),y);
}
for (col = 1; col < gridRows; col++) {
int x = (int)(col*cellWidth);
g.drawLine(x,0,x,getHeight());
}
}
}
/**
* Finds the row
* @param pixelY location on x-axis
* @return rows
*/
private int findRow(int pixelY) {
return (int)(((double)pixelY)/getHeight()*gridRows);
}
/**
* Finds the column
* @param pixelX location of y-axis
* @return columns
*/
private int findColumn(int pixelX) {
return (int)(((double)pixelX)/getWidth()* gridColumns);
}
private class MouseListener implements java.awt.event.MouseListener {
@Override
public void mouseClicked(MouseEvent e) {
int row, col; // the row and column in the grid of squares where the user clicked.
row = findRow( e.getY() ); col = findColumn( e.getX() ); //find the location of cells clicked
circleColor[row][col] = new Color(0,223,197);
repaint(); // redraw the panel by calling the paintComponent method.
}
@Override
public void mousePressed(MouseEvent e) {
int row, col; // the row and column in the grid of squares where the user clicked.
row = findRow( e.getY() ); col = findColumn( e.getX() ); //find the location of cells clicked
circleColor[row][col] = new Color(0);
repaint(); // redraw the panel by calling the paintComponent method.
}
@Override public void mouseReleased(MouseEvent e) { }
@Override public void mouseEntered(MouseEvent e) { }
@Override public void mouseExited(MouseEvent e) { }
}
public static void main (String[] args) {
new DD_GridFiller();
}
}
Upvotes: 1
Views: 321
Reputation: 5859
Your problem was that mousePressed
kept setting your Color to black. Even if you detected that when you pressed the circle the color was not black, in mousePressed you set it to black again and then circle gets drawn again, and like this in a loop.
The solution is quite simple actually:
mousePressed
. We dont need it, mouseClicked is already essentially just mousePressed + mouseReleased.Add this to your mouseClicked method:
@Override
public void mouseClicked(MouseEvent e) {
int row, col; // the row and column in the grid of squares where the user clicked.
row = findRow( e.getY() ); col = findColumn( e.getX() ); //find the location of cells clicked
System.out.println("Cell color: " + circleColor[row][col]); //will let you see whats happening
if (circleColor[row][col] == null) {
circleColor[row][col] = new Color(0,223,197);
} else {
circleColor[row][col] = null;
}
repaint(); // redraw the panel by calling the paintComponent method.
}
What we are doing - initially all our colors are null (before, in your code, mousePressed set them to RGB [0,0,0], i.e. Black). So when we first click on the cell and see that the cell color is "null", i.e. its empty, we set the circle color to our new color and draw the circle. If we press again, we are detecting that the Color is no longer "null", i.e. the cell has a circle inside - we then set the cell back to null.
Some people may not like the notion of "null" for Colors - if instead of null you want to have RGB [0, 0, 0], simply convert any initial occurrence of a null to RGB [0, 0, 0] and then use that:
public void mouseClicked(MouseEvent e) {
...
//initial setup
if (circleColor[row][col] == null) {
circleColor[row][col] = new Color(0);
}
System.out.println("Cell color: " + circleColor[row][col]); //will let you see whats happening
if (circleColor[row][col].equals(Color.getHSBColor(0,0,0))) {
circleColor[row][col] = new Color(0,223,197);
} else {
circleColor[row][col] = new Color(0) ;
}
repaint(); // redraw the panel by calling the paintComponent method.
}
Upvotes: 2
Reputation: 13113
Your paint
method tests the row/col position for a color; if it is non-null, it draws a circle, right? Perhaps in mousePressed, you can test whether circleColor in that position is non-null and, if it is, make it null.
It is not clear to me whether the repaint is filling in the cells; it might need to do that to overwrite the circle after the circle is drawn.
It is typical in applications like this to calculate the minimum rectangle that needs repainting and only repaint it -- you do this by calculating that rectangle and passing its coordinates into the repaint method, then only drawing the portion of the component(s) that intersect with the changed rectangle.
Upvotes: 0