Danielle Shwed
Danielle Shwed

Reputation: 23

Draw multiple circles using graphics in java

I'm working on a connect four game and I'm trying to get multiple circles to show up when I click on the screen. Right now, every time I make a new click, the circle I just drew disappears.

Any help is appreciated.

protected void paintComponent(Graphics g) {

        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;    // create 2d object
        g2d.setStroke(new BasicStroke(2));  // set thickness of line

        // each box is 100 x 100
        // draws the vertical lines
        for (int i = 0; i < 8; i++) {
            g2d.drawLine(140 + i * DISC_RADIUS, 30, 140 + i * DISC_RADIUS, 690);
        }
        // draws the horizontal lines
        for (int i = 0; i < 7; i++) {
            g2d.drawLine(140, 90 + i * DISC_RADIUS, 840, 90 + i * DISC_RADIUS);
        }
        // draws the circles
        for (int i = 0; i < 6; i++) {       // new vertical row of circles
            for (int j = 0; j < 7; j++) {   // new horizontal row of circles
                g2d.drawOval(140 + j * DISC_RADIUS, 90 + i * DISC_RADIUS, DISC_RADIUS, DISC_RADIUS);
            }
        }

        // if at the start of the game, will not draw the counters
        if (start == true) {
            // draws blue counter
            g2d.drawOval(20, 90, DISC_RADIUS, DISC_RADIUS);
            g2d.setColor(Color.BLUE);       // sets colour to blue
            g2d.fillOval(20, 90, DISC_RADIUS, DISC_RADIUS); // draws the circle

            // draws red counter
            g2d.setColor(Color.BLACK);
            g2d.drawOval(875, 90, DISC_RADIUS, DISC_RADIUS);
            g2d.setColor(Color.RED);            // sets the colour to red
            g2d.fillOval(875, 90, DISC_RADIUS, DISC_RADIUS);    // draws the circle


        }
        //print on the screen who's turn it is


        // draws blue counter stand;
        g2d.setStroke(new BasicStroke(4));  // sets the line width
        g2d.setColor(Color.BLACK);          // changes the outline colour to black
        g2d.drawPolygon(poly1);             // draw the outline
        g2d.setColor(Color.GRAY);           // changes the fill colour to grey
        g2d.fillPolygon(poly1);             // draws the filling

        // draws bred counter stand;
        g2d.setColor(Color.BLACK);  // changes the outline colour to black
        g2d.drawPolygon(poly2);     // draws the outline
        g2d.setColor(Color.GRAY);   // changes the fill colour to grey
        g2d.fillPolygon(poly2);     // draws the filling

        repaint();

        if(Player.getPlayer() == "Blue"){
            g2d.setColor(Color.BLACK);  
            if(draw == true){
                g2d.drawString("Blue's Turn", 40, 300); 
                g2d.drawOval(xPos, yPos, DISC_RADIUS, DISC_RADIUS);
                g2d.setColor(Color.BLUE);       // sets colour to blue
                g2d.fillOval(xPos, yPos, DISC_RADIUS, DISC_RADIUS); // draws the circle
            }
        }

        if(Player.getPlayer() == "Red"){
            g2d.drawString("Red's Turn", 900, 300);
            if(draw == true){
                g2d.drawOval(xPos, yPos, DISC_RADIUS, DISC_RADIUS);
                g2d.setColor(Color.RED);        // sets colour to blue
                g2d.fillOval(xPos, yPos, DISC_RADIUS, DISC_RADIUS); // draws the circle
            }
        }
    }
}

Upvotes: 2

Views: 2664

Answers (2)

nIcE cOw
nIcE cOw

Reputation: 24616

One shouldn't be calling repaint() from within the paintComponent() method, as repaint() will somehow call paintComponent(), thus leading to recursive calls.

Moreover, as call to repaint() takes place, the whole JComponent is actually painted from initial state. In order, for you to draw the circles already on the JPanel/JComponent, one can simply use a Collection/Array to keep track of what has been drawn. So that the code can iterate on this Collection/Array to redraw all circles previously drawn and the new circle that is to be drawn.

Here is small sample example:

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;

public class CircleExample {

    private static final int GAP = 5;

    private JPanel drawingBoard;    

    private void displayGUI() {
        JFrame frame = new JFrame("Circle Drawing Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        contentPane.setLayout(new BorderLayout(GAP, GAP));
        contentPane.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));

        drawingBoard = new DrawingBoard();
        contentPane.add(drawingBoard);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new CircleExample().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}

class DrawingBoard extends JPanel {

    private static final int WIDTH = 300;
    private static final int HEIGHT = 350;

    private List<MyCircle> circles;
    private Random random;

    private MouseAdapter mouseAdapter = new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent me) {
            System.out.println("Mouse Clicked");
            int x = me.getX();
            int y = me.getY();
            circles.add(new MyCircle(x, y, getRandomColour()));
            DrawingBoard.this.repaint();
        }
    };

    public DrawingBoard() {
        super();
        circles = new ArrayList<MyCircle> ();
        random = new Random();
        setOpaque(true);
        addMouseListener(mouseAdapter);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(WIDTH, HEIGHT);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (MyCircle circle : circles) {
            circle.drawCircle(g);
        }
    }

    private Color getRandomColour() {
        return new Color(random.nextFloat(), random.nextFloat(),
                            random.nextFloat(), random.nextFloat());
    }
}

class MyCircle {

    private int x;
    private int y;
    private Color backgroundColour;

    private static final int RADIUS = 20;

    public MyCircle(int x, int y, Color backgroundColour) {
        this.x = x;
        this.y = y;
        this.backgroundColour = backgroundColour;
    }

    public void drawCircle(Graphics g) {
        g.setColor(backgroundColour);
        g.fillOval(x, y, RADIUS, RADIUS);
    }
}

Upvotes: 0

MadProgrammer
MadProgrammer

Reputation: 347184

Painting is destructive, that is, every time paintComponent is called, you are expected to repaint the entire state of the component from scratch.

What you should do is create some kind of model which maintains information about which player has which cell selected.

For example, you could just use a 2D array of String, where a null means no-body, Red is for red player and Blue is for blue player. You would then use a simple compound loop to loop through the array and paint the UI accordingly...

Now, if(Player.getPlayer() == "Blue"){ is not how String comparison works in Java, you should be using something more like if("Blue".equals(Player.getPlayer())){ instead.

Don't update or modify the state of the UI from within any paint method directly or indirectly, this could setup an infinite loop of paint requests which will consume your CPU cycles...

Upvotes: 1

Related Questions