dolnuea
dolnuea

Reputation: 33

When double-clicked, circle needs to disappear

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

Answers (2)

vs97
vs97

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:

  1. Delete everything in mousePressed. We dont need it, mouseClicked is already essentially just mousePressed + mouseReleased.
  2. 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

arcy
arcy

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

Related Questions