Re: More bouncing balls...
Re: More bouncing balls...
Quote:
how can I adjust my program to create multiple (unlimited) balls at the click of a button?
Use the paintComponent method in the BallControl call to call the balls for them to display themselves. Have a list of balls that it calls passing each the Graphics object.
When you click a button a new button is created and added to the list.
Re: More bouncing balls...
Re: More bouncing balls...
Here is a corrected version with random colors for each ball and avoiding the use of List<> sintaxis that is not yet covered in chapter 18 of Liang´s Java programming book 8th edition from where this exercise is extracted, so unsafe check alert would appear when compiling it.
Code:
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Exercise18_19 extends JApplet
{
private static ArrayList ballList = new ArrayList();
private JButton jbtPlusOne = new JButton("+1");
private JButton jbtMinusOne = new JButton("-1");
public Exercise18_19()
{
add(new BallControl());
}
public static void main(String[] args)
{
Exercise18_19 applet = new Exercise18_19();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Exercise18_19");
frame.add(applet, BorderLayout.CENTER);
frame.setSize(400, 300);
frame.setVisible(true);
}
class BallControl extends JPanel
{
private Ball ball = new Ball();
private JButton jbtSuspend = new JButton("Suspend");
private JButton jbtResume = new JButton("Resume");
private JScrollBar jsbDelay = new JScrollBar();
public BallControl()
{
// Group buttons in a panel
JPanel panel = new JPanel();
panel.add(jbtSuspend);
panel.add(jbtResume);
panel.add(jbtPlusOne);
panel.add(jbtMinusOne);
// Add ball and buttons to the panel
ball.setBorder(new javax.swing.border.LineBorder(Color.red));
jsbDelay.setOrientation(JScrollBar.HORIZONTAL);
ball.setDelay(jsbDelay.getMaximum());
setLayout(new BorderLayout());
add(jsbDelay, BorderLayout.NORTH);
add(ball, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
// Register listeners
jbtSuspend.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
ball.suspend();
}
});
jbtResume.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
ball.resume();
}
});
jsbDelay.addAdjustmentListener(new AdjustmentListener()
{
public void adjustmentValueChanged(AdjustmentEvent e)
{
ball.setDelay(jsbDelay.getMaximum() - e.getValue());
}
});
jbtPlusOne.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
ball.increment();
}
});
jbtMinusOne.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
ball.decrement();
}
});
}
}
public class Ball extends JPanel
{
private int delay = 1000;
// Create a timer with delay 1000 ms
private Timer timer = new Timer(delay, new TimerListener());
private int x = 0;
private int y = 0; // Current ball position
private int radius = 5; // Ball radius
private int dx = 2; // Increment on ball's x-coordinate
private int dy = 2; // Increment on ball's y-coordinate
private Color[] colorPalette = new Color[]{Color.red, Color.blue, Color.cyan,
Color.green, Color.gray, Color.yellow, Color.black, Color.magenta,
Color.darkGray, Color.LIGHT_GRAY, Color.orange, Color.pink, Color.white};
private Color color;
public Ball()
{
timer.start();
}
public void setColor(Color color)
{
this.color = color;
}
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
for (Object ball : ballList) // if you use List<Ball> then change
// to: for(Ball ball : ballList)
{
// Check boundaries
if (((Ball) ball).x < radius) ((Ball) ball).dx = // If you use List<Ball>
Math.abs(((Ball) ball).dx); // instead of ArrayList
// change these lines
// to the following:
// if(ball.x < radius)
// ball.dx = Math.abs
// (ball.dx);
// etc., etc...
if (((Ball) ball).x > getWidth() - radius) ((Ball) ball).dx =
-Math.abs(((Ball) ball).dx); // Eliminating Math.abs
// from this line has
// the same result
if (((Ball) ball).y < radius) ((Ball) ball).dy =
Math.abs(((Ball) ball).dy);
if (((Ball) ball).y > getHeight() - radius) ((Ball) ball).dy =
-Math.abs(((Ball) ball).dy); // Eliminating Math.abs
// from this line
// has the same result
// Adjust ball position
((Ball) ball).x += ((Ball) ball).dx;
((Ball) ball).y += ((Ball) ball).dy;
g.setColor(((Ball) ball).color);
g.fillOval(((Ball) ball).x - radius,
((Ball) ball).y - radius, radius * 2, radius * 2);
} //close for loop
} //close paint method
private class TimerListener implements ActionListener
{
/**
* Handle the action event
*/
public void actionPerformed(ActionEvent e)
{
repaint();
}
}//close timer class
public void suspend()
{
timer.stop(); // Suspend timer
jbtPlusOne.setEnabled(false);
jbtMinusOne.setEnabled(false);
}
public void resume()
{
timer.start(); // Resume timer
jbtPlusOne.setEnabled(true);
jbtMinusOne.setEnabled(true);
}
public void setDelay(int delay)
{
this.delay = delay;
timer.setDelay(delay); //Adjusts delay per slider
}
public void increment()
{
int colorPaletteIndex = (int) (Math.random() * colorPalette.length);
Ball tempBall = new Ball();
tempBall.setColor(colorPalette[colorPaletteIndex]);
ballList.add(tempBall);
}
public void decrement()
{
int lastBall = ballList.size();
if (lastBall >= 1)
ballList.remove(lastBall - 1);
}
} //close ball class
} //close class -- end of file
Re: More bouncing balls...
A definitive version:
Code:
import java.util.ArrayList;
import java.util.List;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Exercise18_19 extends JApplet {
private static List<Ball> ballList = new ArrayList<Ball>();
public Exercise18_19() {
add(new BallControl());
}
public static void main(String[] args) {
Exercise18_19 applet = new Exercise18_19();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Exercise18_19");
frame.add(applet, BorderLayout.CENTER);
frame.setSize(400, 320);
frame.setVisible(true);
}
class BallControl extends JPanel {
private Ball ball = new Ball();
private JButton jbtSuspend = new JButton("Suspend");
private JButton jbtResume = new JButton("Resume");
private JButton jbtPlusOne = new JButton("+1");
private JButton jbtMinusOne = new JButton("-1");
private JScrollBar jsbDelay = new JScrollBar();
public BallControl() {
// Group buttons in a panel
JPanel panel = new JPanel();
panel.add(jbtSuspend);
panel.add(jbtResume);
panel.add(jbtPlusOne);
panel.add(jbtMinusOne);
// Add ball and buttons to the panel
ball.setBorder(new javax.swing.border.LineBorder(Color.red));
jsbDelay.setOrientation(JScrollBar.HORIZONTAL);
ball.setDelay(jsbDelay.getMaximum());
setLayout(new BorderLayout());
add(jsbDelay, BorderLayout.NORTH);
add(ball, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
// Register listeners
jbtSuspend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ball.suspend();
}
});
jbtResume.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ball.resume();
}
});
jsbDelay.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
ball.setDelay(jsbDelay.getMaximum() - e.getValue());
}
});
jbtPlusOne.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ball.increment();
}
});
jbtMinusOne.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ball.decrement();
}
});
}
}
//***************************************************************
public class Ball extends JPanel {
private int delay = 1000;
// Create a timer with delay 1000 ms
private Timer timer = new Timer(delay, new TimerListener());
private int x = 0;
private int y = 0; // Current ball position
private int radius = 5; // Ball radius
private int dx = 2; // Increment on ball's x-coordinate
private int dy = 2; // Increment on ball's y-coordinate
private Color[] colorPalette = new Color[]{Color.red, Color.blue, Color.cyan, Color.green, Color.gray, Color.yellow, Color.black, Color.magenta,
Color.darkGray, Color.LIGHT_GRAY, Color.orange, Color.pink, Color.white};
private Color color;
public Ball() {
timer.start();
}
public void setColor(Color color) {
this.color = color;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Ball ball : ballList) {
// Check boundaries
if (ball.x < radius) ball.dx = Math.abs(ball.dx);
if (ball.x > getWidth() - radius) ball.dx = -Math.abs(ball.dx);
if (ball.y < radius) ball.dy = Math.abs(dy);
if (ball.y > getHeight() - radius) ball.dy = -Math.abs(ball.dy);
// Adjust ball position
ball.x += ball.dx;
ball.y += ball.dy;
g.setColor(ball.color);
g.fillOval(ball.x - radius, ball.y - radius, radius * 2, radius * 2);
}//close for loop
}//close paint method
private class TimerListener implements ActionListener {
/**
* Handle the action event
*/
public void actionPerformed(ActionEvent e) {
repaint();
}
}//close timer class
public void suspend() {
timer.stop(); // Suspend timer
}
public void resume() {
timer.start(); // Resume timer
}
public void setDelay(int delay) {
this.delay = delay;
timer.setDelay(delay); //Adjusts delay per slider
}
public void increment() {
int colorPaletteIndex = (int) (Math.random() * colorPalette.length);
Ball tempBall = new Ball();
tempBall.setColor(colorPalette[colorPaletteIndex]);
ballList.add(tempBall);
}
public void decrement() {
int lastBall = ballList.size();
if (lastBall >= 1)
ballList.remove(lastBall - 1);
}
}//close ball class
}