-1

I am trying to draw 7 random circles across a JPanel using an array. I managed to get the array to work but now I am having trouble spacing out the circles. When i run the program i see multiple circles being drawn but they are all on the same spot. All the circles are of different size and color. The other problem i have is making the circles move towards the bottom of the screen.

public class keyExample extends JPanel implements ActionListener, KeyListener{

    private Circle[] circles = new Circle[7];

    Timer t = new Timer(5,this);
    //current x and y
    double x = 150, y = 200;
    double changeX = 0, changeY = 0;

    private int circlex = 0,circley = 0; // makes initial starting point of circles 0
    private javax.swing.Timer timer2;

    public keyExample(){
        t.start();
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
        NewCircle();
        timer2 = new javax.swing.Timer(33,new MoveListener());
        timer2.start();
    }

    public void NewCircle(){
        Random colors = new Random();
        Color color = new Color(colors.nextInt(256),colors.nextInt(256),colors.nextInt(256));

        Random num= new Random();
        int radius = num.nextInt(45);

        for (int i = 0; i < circles.length; i++)
            circles[i] = new Circle(circlex,circley,radius,color);
        }
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setColor(Color.BLUE);
        g2.fill(new Rectangle2D.Double(x,y,40,40));
        for (int i = 0; i < circles.length; i++)
            circles[i].fill(g);
    }

    public void actionPerformed(ActionEvent e){
        repaint();
        x += changeX;
        y += changeY;
        changeX = 0;
        changeY = 0;
    }

    public void up() {
        if (y != 0){
            changeY = -3.5;
            changeX = 0;
        }
    }

    public void down() {
        if (y <= 350){
            changeY = 3.5;
            changeX = 0;
        }
    }

    public void left() {
        if (x >= 0) {
            changeX = -3.5;
            changeY = 0;
        }
    }

    public void right() {
        if (x <= 550) {
            changeX = 3.5;
            changeY = 0;
        }
    }

private class MoveListener implements ActionListener{

    public void actionPerformed(ActionEvent e){
        repaint();
        Random speed = new Random();
        int s = speed.nextInt(8);
        }
    }

    public void keyPressed(KeyEvent e){
        int code = e.getKeyCode();
        if (code == KeyEvent.VK_UP){
            up();
        }
        if (code == KeyEvent.VK_DOWN){
            down();
        }
        if (code == KeyEvent.VK_RIGHT){
            right();
        }
        if (code == KeyEvent.VK_LEFT){
            left();
        }
    }

    public void keyTyped(KeyEvent e) { }

    public void keyReleased(KeyEvent e) { }
}



Circle class


import java.awt.*;

public class Circle{

private int centerX, centerY, radius, coord;
private Color color;

public Circle(int x, int y, int r, Color c){
centerX = x;
centerY = y;
radius = r;
color = c;

}

public void draw(Graphics g){
Color oldColor = g.getColor();
g.setColor(color);
g.drawOval(centerX - radius, centerY - radius, radius * 2, radius * 2);
g.setColor(oldColor);

}

public void fill(Graphics g){
Color oldColor = g.getColor();
g.setColor(color);
g.fillOval(centerX - radius, centerY - radius, radius *2, radius * 2);
g.setColor(oldColor);
}

public boolean containsPoint(int x, int y){
int xSquared = (x - centerX) * (x - centerX);
int ySquared = (y - centerY) * (y - centerY);
int RadiusSquared = radius * radius;
return xSquared + ySquared - RadiusSquared <=0;
}



public void move(int xAmount, int yAmount){
centerX = centerX + xAmount;
centerY = centerY + yAmount;

}
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
user3076906
  • 33
  • 10

1 Answers1

3

This is one of the problems with relying on borrowed code that you don't understand...

Basically, all you need to do is change the creation of the circles, for example...

for (int i = 0; i < circles.length; i++) {
    circles[i] = new Circle(circlex, circley, radius, color);
    circlex += radius;
}

You may wish to re-consider the use of KeyListener, in favour of Key Bindings before you discover that KeyListener doesn't work the way you expect it to...

For some strange reason, you're calling NewCirlces from within the MoveListener's actionPerfomed method, meaning that the circles are simply being re-created on each trigger of the Timer...instead, call it first in the constructor

You're also calling within your paintComponent method...this should mean that the circles never move and instead, random change size...

Updated with runnable example...

I modified your paint code NewCircle and the MoveListener a little...

Drop circles

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.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
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 CircleExample extends JPanel implements ActionListener, KeyListener {

    public static void main(String[] args) {
        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 CircleExample());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    private Circle[] circles = new Circle[7];

    Timer t = new Timer(5, this);
    //current x and y
    double x = 150, y = 200;
    double changeX = 0, changeY = 0;

    private int circlex = 0, circley = 0; // makes initial starting point of circles 0
    private javax.swing.Timer timer2;

    public CircleExample() {
        NewCircle();
        t.start();
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
        timer2 = new javax.swing.Timer(33, new MoveListener());
        timer2.start();
    }

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

    public void NewCircle() {
        for (int i = 0; i < circles.length; i++) {
            Random colors = new Random();
            Color color = new Color(colors.nextInt(256), colors.nextInt(256), colors.nextInt(256));

            Random num = new Random();
            int radius = num.nextInt(90);
            circles[i] = new Circle(circlex, circley, radius, color);
            circlex += radius;
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setColor(Color.BLUE);
        g2.fill(new Rectangle2D.Double(x, y, 40, 40));
        for (int i = 0; i < circles.length; i++) {
            circles[i].fill(g);
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        repaint();
        x += changeX;
        y += changeY;
        changeX = 0;
        changeY = 0;
    }

    public void up() {
        if (y != 0) {
            changeY = -3.5;
            changeX = 0;
        }
    }

    public void down() {
        if (y <= 350) {
            changeY = 3.5;
            changeX = 0;
        }
    }

    public void left() {
        if (x >= 0) {
            changeX = -3.5;
            changeY = 0;
        }
    }

    public void right() {
        if (x <= 550) {
            changeX = 3.5;
            changeY = 0;

        }
    }

    private class MoveListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            Random speed = new Random();

            for (Circle circle : circles) {
                int s = speed.nextInt(8);
                circle.move(0, s);
            }
            repaint();
        }
    }

    public void keyPressed(KeyEvent e) {
        int code = e.getKeyCode();
        if (code == KeyEvent.VK_UP) {
            up();
        }
        if (code == KeyEvent.VK_DOWN) {
            down();
        }
        if (code == KeyEvent.VK_RIGHT) {
            right();
        }
        if (code == KeyEvent.VK_LEFT) {
            left();
        }
    }

    public void keyTyped(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {
    }

    public class Circle {

        private int centerX, centerY, radius, coord;
        private Color color;

        public Circle(int x, int y, int r, Color c) {
            centerX = x;
            centerY = y;
            radius = r;
            color = c;

        }

        public void draw(Graphics g) {
            Color oldColor = g.getColor();
            g.setColor(color);
            g.drawOval(centerX, centerY, radius, radius);
            g.setColor(oldColor);

        }

        public void fill(Graphics g) {
            Color oldColor = g.getColor();
            g.setColor(color);
            g.fillOval(centerX, centerY, radius, radius);
            g.setColor(oldColor);
        }

        public boolean containsPoint(int x, int y) {
            int xSquared = (x - centerX) * (x - centerX);
            int ySquared = (y - centerY) * (y - centerY);
            int RadiusSquared = radius * radius;
            return xSquared + ySquared - RadiusSquared <= 0;
        }

        public void move(int xAmount, int yAmount) {
            centerX = centerX + xAmount;
            centerY = centerY + yAmount;

        }

    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • i tried the code you posted above and it helped but when i run the program it continues to draw circles across the JPanel until there is nothing at all on the JPanel. So the screen stays blank. the keylistener class is used to control a rectangle that i drew on the JPanel. – user3076906 Dec 08 '13 at 07:26
  • 1- Did you remove all the calls to `NewCircle` and place a single in the constructor? 2- `KeyListener` has serious focus issues which are solved by simply making the component focusable. The preferred way to interact with the keyboard is through the Key Bindings API; 3- Since you never supplied the code to the `Circle`, I can't say how you might fix your movement problem, but you will need to supply the `move` method with some idea about the height/width of the area it can move within, for [example](http://stackoverflow.com/questions/13022754/java-bouncing-ball/13022788#13022788) – MadProgrammer Dec 08 '13 at 07:32
  • `NewCircle` creates all the circles each time it's called. So basically (if you use my code snippet with it), the balls with basically "look" like they've moved to the right off the screen. It only needs to be called once, within the constructor, to initialise the array... – MadProgrammer Dec 08 '13 at 07:39
  • It's probably because all the circles are at the same position and are the same radius... – MadProgrammer Dec 08 '13 at 08:24
  • thanks the code worked but if you don't mind helping me with one last thing. would it be possible to make the circles appear back at the top of the screen when they reach the bottom of the screen. So if any of the circles reaches the bottom that circle will go back to the top of the screen – user3076906 Dec 08 '13 at 10:43
  • @user3076906: This is one of the problems when relying on someone else's code that you don't understand. – Gilbert Le Blanc Dec 08 '13 at 15:11
  • @GilbertLeBlanc yeah you are right but I was close to figuring out the problem. I don't want someone do all the work for me. All I want at this point is a hint on what my next step should be. I am sure that making the cirlcles appear back at the top should not be too hard but I cant figure it out. – user3076906 Dec 08 '13 at 16:24
  • @user3076906: Write a test within your Circle class for reaching bottom, and write a method in your Circle class for setting the top. Run the bottom tests in a loop in your MoveListener. – Gilbert Le Blanc Dec 09 '13 at 13:16
  • @GilbertLeBlanc so in my test I would be looking for the Y value of the circles right. I have been trying to do something similar to what you just said except I could not figure out how to keep track of the Y value of the circles. Could you give me an example of what the test method should look like. I tried making a method in my Circle class to keep track of the Y value of my circle but it wouldn't work – user3076906 Dec 10 '13 at 11:24
  • Like the one from you [other question](http://stackoverflow.com/questions/20462128/how-can-i-draw-a-circle-again-if-it-goes-too-far-on-a-jpanel)? – MadProgrammer Dec 10 '13 at 19:15
  • @MadProgrammer thanks so much. That is exactly what I have been trying to do – user3076906 Dec 11 '13 at 02:34