So I'm trying to draw 2 circles on top of each other (kinda like a snowman) and move the snowman to the right when the user clicks on the "Start" button and stop moving the snowman when the user clicks on the "Stop" button. However, the only thing that I am able to come up with is 2 snowmen drawn next to each other that don't react to the buttons.
Here is what I've come up with:
import java.awt.Graphics2D;
public interface MoveableShape {
void draw(Graphics2D g);
void translate(int dx, int dy);
}
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
public class SnowmanShape implements MoveableShape {
private int x;
private int y;
private int width;
public SnowmanShape(int x, int y, int width){
this.x = x;
this.y = y;
this.width = width;
}
#Override
public void draw(Graphics2D g2) {
// TODO Auto-generated method stub
Ellipse2D.Double head = new Ellipse2D.Double(0, 0, 10, 10);
Ellipse2D.Double body = new Ellipse2D.Double(0, 11, 10, 10);
g2.draw(head);
g2.draw(body);
}
#Override
public void translate(int dx, int dy) {
// TODO Auto-generated method stub
x += dx;
y += dy;
}
}
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class MyPanel extends JPanel{
MoveableShape s;
public MyPanel (MoveableShape m){
s = m;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
s.draw((Graphics2D)g);
}
}
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class AnimationTester {
private static final int DEFAULT_WIDTH = 400;
private static final int DEFAULT_HEIGHT = 200;
private static final int SNOWMAN_WIDTH = 50;
final static MoveableShape shape = new SnowmanShape(0, 0, SNOWMAN_WIDTH);
final static JPanel panel = new MyPanel(shape);
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame frame = new JFrame();
frame.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
JButton startButton = new JButton("Start");
JButton stopButton = new JButton("Stop");
frame.setLayout(new BorderLayout());
frame.add(panel);
frame.add(startButton, BorderLayout.NORTH);
frame.add(stopButton, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
final int DELAY = 100;
// Milliseconds between timer ticks
Timer t = new Timer(DELAY, translateSnowman());
startButton.addActionListener(startTimer(t));
stopButton.addActionListener(stopTimer(t));
}
public static ActionListener translateSnowman(){
return new ActionListener(){
public void actionPerformed(ActionEvent event){
shape.translate(1, 0);
panel.repaint();
}
};
}
public static ActionListener startTimer(final Timer t){
return new ActionListener(){
public void actionPerformed(ActionEvent event){
t.start();
}
};
}
public static ActionListener stopTimer(final Timer t){
return new ActionListener(){
public void actionPerformed(ActionEvent event){
t.stop();
}
};
}
}
Could someone please let me know where I went wrong or point me in the right direction?
EDIT: I fixed up the AnimationListener so now it doesn't draw 2 snowmans. The snowman still won't move however. I updated the code in the post as well.
Add g2.translate(x, y); to SnowmanShape#draw, before you are painting:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
class SnowmanShape implements MoveableShape {
static final Color headColor = new Color(0xFFE9C9);
static final Color bodyColor = new Color(0xEAF6FF);
static final Color outlineColor = new Color(0x252525);
int x;
int y;
int size;
Ellipse2D.Double head;
Ellipse2D.Double body;
SnowmanShape(int x, int y, int size) {
this.x = x;
this.y = y;
this.size = size;
initModel();
}
void initModel() {
head = new Ellipse2D.Double(0, 0, size, size);
body = new Ellipse2D.Double(0, head.height, size * 1.3d, size * 1.5d);
body.x -= (body.width - head.width) * (1 / 2d);
}
#Override
public void draw(Graphics2D g2) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.translate(x, y);
g2.setColor(headColor);
g2.fill(head);
g2.setColor(outlineColor);
g2.draw(head);
g2.setColor(bodyColor);
g2.fill(body);
g2.setColor(outlineColor);
g2.draw(body);
}
#Override
public void translate(int dx, int dy) {
x += dx;
y += dy;
}
}
I not an expert on doing things like this, but if I were you I would use the timer to move the objects and then call the paint to repaint the objects in a new position. Therefore, your ShapeIcon class would just keep track of the position of your objects. That probably wasn't all that helpful, so to point you in right direction, you can check out some code in this tutorial here.
Related
Thanks in advance for help
I created a program that makes multiple bouncing balls When user clicks on the screen a new ball should appear and move around screen. But when i click on the screen a ball appears and doesn't moving at all. When another click happens, the ball created previously jumped to another position instantly.
this is the ball class: used to create balls
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.util.Random;
import javax.swing.JComponent;
public class Ball extends JComponent implements Runnable{
private final int DIAMETER = 25;
private final int v1 = 5;
private final int v2 = -5;
private final Random rnd = new Random();
private int posX;
private int posY;
private Color color;
private int xVelocity;
private int yVelocity;
public Ball(int posX, int posY) {
this.posX = posX;
this.posY = posY;
this.color = randomColor();
this.xVelocity = rnd.nextBoolean()?v1:v2;
this.yVelocity = rnd.nextBoolean()?v1:v2;
}
public void move() {
if (posX < 15) {
xVelocity = -xVelocity;
} else if(posX > 475) {
xVelocity = -xVelocity;
}
if (posY < 0) {
yVelocity = -yVelocity;
} else if(posY > 475) {
yVelocity = -yVelocity;
}
posX +=xVelocity;
posY +=yVelocity;
}
public void draw(Graphics2D g2) {
g2.setColor(color);
g2.fill(new Ellipse2D.Double(posX,posY,DIAMETER,DIAMETER));
}
private static Color randomColor() {
int r = (int)(Math.random()*255);
int g = (int)(Math.random()*255);
int b = (int)(Math.random()*255);
Color rColor = new Color(r,g,b);
return rColor;
}
#Override
public void run() {
while(!Thread.interrupted()) {
move();
repaint();
try {
Thread.sleep(60);
} catch (InterruptedException ex) {}
}
}
}
this is the ballcomponent class: used to create the panel & display the balls
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BallComponent extends JPanel{
private ArrayList<Ball> bList;
public BallComponent() {
bList = new ArrayList<Ball>();
this.setPreferredSize(new Dimension(500,500));
this.setBackground(Color.BLACK);
this.addMouseListener(new ClickListener());
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
super.paintComponent(g2);
for (Ball a : bList) {
a.draw(g2);
}
}
private class ClickListener extends MouseAdapter{
public void mouseClicked(MouseEvent e) {
Ball a = new Ball(e.getX(),e.getY());
bList.add(a);
repaint();
Thread gameThread = new Thread(a);
gameThread.start();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("Bouncing Balls");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new BallComponent());
frame.pack();
frame.setVisible(true);
}
}
Since you have a bunch of threads doing random stuff. You might as well have your JPanel update on it's own.
At the end of your main method.
new Thread( ()->{
while(true){
frame.repaint();
try{
Thread.sleep(60);
} catch(Exception e){
break;
}
}
}).start();
Usually you would do this with a timer task, but since you said you couldn't use a Timer, I just wrote a thread version.
I think repaint() is safe to call from off of the EDT since it just schedules a repaint. The paintComponent method and click method will only be called on the EDT. So you shouldn't get CCME. There are a bunch of race conditions with the multiple threads, but it seems like the only problem would be balls drawn out of position.
OK so i'm working on a school project (little animation) and I am currently trying to make rain. I'm not sure how I would go about drawing individual "drops" using JPanel. My Code so far:
Main Class:
public class RainPanel extends JPanel {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
new RainPanel();
}
private final int WIDTH = 800, HEIGHT = 800;
Drop drop;
public RainPanel() {
init();
}
public void init() {
JFrame frame = new JFrame("Rain");
JPanel drop = new Drop();
frame.setVisible(true);
frame.setSize(WIDTH, HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(drop);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
drop.paint(g);
}
Drop class:
public class Drop extends JPanel implements ActionListener{
private static final long serialVersionUID = 1L;
int x,y;
int yVel = 2;
Timer t = new Timer(5, this);
Random r = new Random();
ArrayList<Drop> DropArray;
public Drop() {
x = r.nextInt(800);
y = r.nextInt(800);
t.start();
}
public void paint(Graphics g) {
super.paintComponent(g);
DropArray = new ArrayList<>(100);
for (int i = 0; i < DropArray.size(); i++) {
DropArray.add(new Drop());
}
g.setColor(Color.BLUE);
g.fillRect(x, y, 3, 15);
}
public void update() {
y += yVel;
if (y > 800)
y = r.nextInt(800);
}
#Override
public void actionPerformed(ActionEvent e) {
update();
repaint();
}
I understand if you might be cringing hard right now (I'm fairly new to graphics coding and mostly familiar with Java itself). All i'm getting drawn currently is a single rain drop. Any suggestions are appreciated.
Don't call super.paintComponent from within paint, you're breaking the paint chain which could cause no end of issues. Override paintComponent directly instead
You shouldn't be modifying the state of a component or anything the component relies on from within any paint method, paint can be called a number of times in quick succession and this can cause no end of issues
Component based animation is not a simple task and unless you really, really need it, you should try and avoid it. Instead, write a class which is "paintable", which you can call from your paintComponent method
For example..
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class RainDropsKeepFalling {
public static void main(String[] args) {
new RainDropsKeepFalling();
}
public RainDropsKeepFalling() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new RainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class RainPane extends JPanel {
private List<Drop> drops = new ArrayList<>(100);
public RainPane() {
for (int index = 0; index < 100; index++) {
drops.add(new Drop(getPreferredSize()));
}
Timer timer = new Timer(5, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Drop drop : drops) {
drop.update(getSize());
repaint();
}
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Drop drop : drops) {
Graphics2D g2d = (Graphics2D) g.create();
drop.paint(g2d);
g2d.dispose();
}
}
}
protected static final Random random = new Random();
public static class Drop {
private double vDelta = random.nextDouble() + 0.5;
private int height = 15;
private int width = 3;
private double x;
private double y = -height;
private Rectangle2D shape;
public Drop(Dimension size) {
x = random.nextInt(size.width - width) + width;
y = random.nextInt(size.height - height) + height;
shape = new Rectangle2D.Double(x, y, width, height);
}
public void paint(Graphics2D g2d) {
g2d.setColor(Color.BLUE);
g2d.fill(shape);
}
public void update(Dimension size) {
y += vDelta;
if (y > size.height) {
y = -height;
x = random.nextInt(size.width - width) + width;
}
shape.setRect(x, y, width, height);
}
}
}
Ok so i made this program that moves the picture to the end and when you click on a button, it draws a line from the picture to this point. I am able to make the whole button thing, however, I suck at layouts and stuff. So when i run my program, it opens 2 java programs, one where the animation is happening and one for button.. I dont want that.. I want the button to be on the same java program as the animation. Also, I am trying to set the background color but it isn't working.. I am sure it has to do with frames or something.. idk. Please help. Here is my class for main method:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class example extends JFrame implements Runnable, ActionListener{
private int W=1000;
private int H=1500;
private Thread thread;
private int c=1;
int q=0;
Image image= new ImageIcon("Pictures/car.png").getImage();
private move greenCar;
public example(){
setBounds(100,100,W,H);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setBackground(Color.CYAN);
thread= new Thread(this);
greenCar=new move(image,30,70,98,40);
thread.start();
}
public void paint(Graphics g){
super.paint(g);
//draws the image on the screen
g.drawImage(greenCar.getImg(), greenCar.getX(), greenCar.getY(), this);
//c becomes 2 if the image has reached x=699 and if the button is pressed, q becomes greater than 0
if(c==2 &&q>0)
{
//and when that happens, a line gets created from stretching from the picture to a point
g.drawLine(greenCar.getX(), greenCar.getY(), 10, 20);
g.setColor(Color.BLACK);
}
}
public static void main(String[] args) {
//new example();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new example().createGui();
}
});
}
protected void createGui() {
JFrame frame = new JFrame("Button");
frame.setSize(30, 30);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridBagLayout());
frame.add(panel);
frame.getContentPane().add(panel, BorderLayout.WEST);
GridBagConstraints c = new GridBagConstraints();
JButton button1 = new JButton("Profile");
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(40, 40, 40, 40);
panel.add(button1, c);
button1.addActionListener(this);
}
public void run() {
while(true)
{
//starting the animation
greenCar.animate();
repaint();
//if the picture is above 698, set c as 2
if(greenCar.getX()>698)
{
c=2;
}
try{
thread.sleep(13);
}
catch(InterruptedException e){
}
}
}
#Override
public void actionPerformed(ActionEvent e) {
//q, which was initially 0, gets incremented
q++;
}
}
and for the animation of image:
import java.awt.Image;
public class move {
private Image img;
private int x,y,width,height;
public move(Image img, int x,int y, int width, int height){
this.x=x;
this.y=y;
this.width=width;
this.height=height;
this.img=img;
}
public Image getImg() {
return img;
}
public void setImg(Image img) {
this.img = img;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public void animate(){
if(getX()<700)
setX(getX()+1);
if(getX()>700)
x=701;
}
}
newbie programmer here.
I'm making a program that renders user-inputted equations in a Cartesian coordinate system. At the moment I'm having some issues with letting the user move the view around freely in the coordinate. Currently with mouseDragged the user can drag the view around a bit, but once the user releases the mouse and tries to move the view again the origin snaps back to the current position of the mouse cursor. What is the best way to let the user move around freely? Thanks in advance!
Here's the code for the drawing area.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JPanel;
public class DrawingArea extends JPanel implements MouseMotionListener {
private final int x_panel = 350; // width of the panel
private final int y_panel = 400; // height of the panel
private int div_x; // width of one square
private int div_y; // height of one square
private int real_y;
private int real_x;
private Point origin; // the origin of the coordinate
private Point temp; // temporary point
private static int y = 0;
private static int x = 0;
DrawingArea() {
setBackground(Color.WHITE);
real_x = x_panel;
real_y = y_panel;
setDivisionDefault();
setOrigin(new Point((real_x / 2), (real_y / 2)));
setSize(x_panel, y_panel);
addMouseMotionListener(this);
}
DrawingArea(Point origin, Point destination) {
this.origin = origin;
this.destination = destination;
panel = new JPanel();
panel.setSize(destination.x, destination.y);
panel.setLocation(origin);
this.panel.setBackground(Color.red);
panel.setLayout(null);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D line = (Graphics2D) g;
temp = new Point(origin.x, origin.y);
line.setColor(Color.red);
drawHelpLines(line);
line.setColor(Color.blue);
drawOrigin(line);
line.setColor(Color.green);
for (int i = 0; i < 100; i++) { // This is a test line
//temp = this.suora();
temp.x++;
temp.y++;
line.drawLine(temp.x, temp.y, temp.x, temp.y);
}
}
public void setOrigin(Point p) {
origin = p;
}
public void drawOrigin(Graphics2D line) {
line.drawLine(origin.x, 0, origin.x, y_panel);
line.drawLine(0, origin.y, x_panel, origin.y);
}
public void drawHelpLines(Graphics2D line) {
int xhelp= origin.x;
int yhelp= origin.y;
for (int i = 0; i < 20; i++) {
xhelp+= div_x;
line.drawLine(xhelp, 0, xhelp, y_panel);
}
xhelp= origin.x;
for (int i = 0; i < 20; i++) {
xhelp-= div_x;
line.drawLine(xhelp, 0, xhelp, y_panel);
}
for (int i = 0; i < 20; i++) {
yhelp-= div_y;
line.drawLine(0, yhelp,x_panel, yhelp);
}
yhelp= origin.y;
for (int i = 0; i < 20; i++) {
yhelp+= div_y;
line.drawLine(0, yhelp, x_panel, yhelp);
}
}
public void setDivisionDefault() {
div_x = 20;
div_y = 20;
}
#Override
public void mouseDragged(MouseEvent e) {
//Point temp_point = new Point(mouse_x,mouse_y);
Point coords = new Point(e.getX(), e.getY());
setOrigin(coords);
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
Based on this example, the following program allows the user to drag the axes' intersection to an arbitrary point, origin, which starts at the center of the panel.
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/15576413/230513
* #see https://stackoverflow.com/a/5312702/230513
*/
public class MouseDragTest extends JPanel {
private static final String TITLE = "Drag me!";
private static final int W = 640;
private static final int H = 480;
private Point origin = new Point(W / 2, H / 2);
private Point mousePt;
public MouseDragTest() {
this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mousePt = e.getPoint();
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
int dx = e.getX() - mousePt.x;
int dy = e.getY() - mousePt.y;
origin.setLocation(origin.x + dx, origin.y + dy);
mousePt = e.getPoint();
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(W, H);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(0, origin.y, getWidth(), origin.y);
g.drawLine(origin.x, 0, origin.x, getHeight());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame(TITLE);
f.add(new MouseDragTest());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
I am trying to draw circle objects with each click and then store every circle object into an Arraylist, I don't know why my program is not working! If I removed the arraylist and the line that create a new circle object, the program will work. How would I make my program store all circuit objects into an Arraylist ?
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Random;
public class CircleObj extends JPanel {
private int rColor;
private int gColor;
private int bColor;
private int radius;
private Random rand = new Random();
private int xStart;
private int yStart;
ArrayList <Circle> xxx ;
public CircleObj () {
xxx = new ArrayList<Circle>();
addMouseListener(new MouseAdapter() {
public void mouseClicked (MouseEvent e) {
xStart = e.getX();
yStart = e.getY();
rColor = rand.nextInt(256);
gColor = rand.nextInt(256);
bColor = rand.nextInt(256);
radius = rand.nextInt(20);
repaint();
}
}); // end addMouseListener
}
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.setColor(new Color(rColor, gColor, bColor));
g.fillOval(xStart, yStart, radius, radius);
xxx.add(new Circle());
}
private class Circle {
private int x;
private int y;
private int r;
private int rcol;
private int gcol;
private int bcol;
public Circle()
{
x=xStart;
y=yStart;
r=radius;
rcol= rColor;
gcol= gColor;
bcol= bColor;
}
}
}
======
import javax.swing.JFrame;
import java.awt.BorderLayout;
public class HW3 {
public static void main (String[] arg) {
JFrame frame = new JFrame("Circles");
CircleObj canvas = new CircleObj();
frame.add(canvas, BorderLayout.CENTER);
frame.setBounds(250, 98, 600, 480);
//frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
} // end main
} //end HW3
Don't add the new shape inside the paintComponent method, paintComponent can be called for any number of reasons, many of which you don't control, instead, create it when the mouseClicked event is triggered...
public void mouseClicked (MouseEvent e) {
xStart = e.getX();
yStart = e.getY();
rColor = rand.nextInt(256);
gColor = rand.nextInt(256);
bColor = rand.nextInt(256);
radius = rand.nextInt(20);
xxx.add(new Circle(xStart, yStart, new Color(rColor, gColor, bColor), radius));
repaint();
}
And then in your paintComponent, loop through the ArrayList and paint the circles...
public void paintComponent (Graphics g) {
super.paintComponent(g);
for (Circle c : xxx) {
g.setColor(c.getColor());
g.fillOval(c.getX(), c.getY(), c.getRadius(), c.getRadius());
}
}
Now, you're going to have to modify you Circle class to provide getters which the CircleObj can use in order to actually paint the circles...
Alternatively, you could make use of the Shapes API provided within Java...Have a look at Working with Geometry for more details...