Reputation: 23
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
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
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