import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MovingCircleGUI
{
JFrame frame;
public int x,y;
public int vx = 30,vy=20;
public int width = 500,height = 500;
public int diameter=100;
CircleDrawPanel drawPanel;
Color color = Color.magenta.darker();
JButton button;
Timer timer2 = new Timer(10, new AnimateCircleListener());
boolean isRunning = false;
public static void main (String[] args)
{
MovingCircleGUI gui = new MovingCircleGUI();
gui.go();
}
//this method sets up the JFrame and adds the draw panel to the frame
public void go()
{
frame = new JFrame("MovingCircleGUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawPanel = new CircleDrawPanel();
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
button = new JButton("Click me to start the animation");
drawPanel.add(button);
frame.getContentPane().add(BorderLayout.SOUTH , button);
button.addActionListener(new AnimateCircleListener());
frame.setSize(width,height);
frame.setVisible(true);
}
class CircleDrawPanel extends JPanel
{
public void paintComponent (Graphics g)
{
super.paintComponent(g);
Graphics2D g2=(Graphics2D)g;
g2.setColor(color);
g2.fillOval(x,y,diameter,diameter);
}
}
public void MovingBall()
{
x = x + vx;
y = y + vy;
if( y >= height)
{
y=0;
boolean xIsSame = true;
int randomX = 0;
do
{
randomX = Math.round((float)Math.random()*width);
if (randomX != x)
{
x = randomX;
}
}
while(!xIsSame);
}
if(x <= 0)
{
x = width+x;
}
if (x >= width)
{
x = x-width;
}
timer2.start();
frame.repaint();
}
class AnimateCircleListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource()== button)
{
if(isRunning)
{
isRunning = false;
button.setText("Click me to start the animation");
button.revalidate();
}
else
{
isRunning = true;
MovingBall();
button.setText("Click me to stop the animation");
button.revalidate();
}
}
}
}
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;
}
}
I am trying to construct a one button which handles two events mainly to start and stop the animation. What I am trying to do is when the user clicks the button the animation of the bouncing ball will start, and the text of the button will change to "Click me to stop", and when the user clicks the button again the animation will stop. I am using the timer.
The animation is okay, I worked that out, and that when the user clicks the button, the animation start that's okay too. The only problem I've got is how am I going to handle another event to the same button?
You could do something similar to this. This way you only need one Action Listener and a boolean to tell it which action to do.
boolean isRunning = false
button.addActionListener(new YourActionListener());
public class YourActionListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==button)
{
if(isRunning)
{
isRunning = false;
button.setText("Click me to start");
button.revalidate();
}
else
{
isRunning = true;
button.setText("Click me to stop");
button.revalidate();
}
}
}
}
Edit
Your code now works. What you wanted to do was call the MoveBall method when timer2 fired the Action Listener.
This can be done by
if(e.getSource()==timer2)
{
MovingBall();
}
so in your code it would look like.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MovingCircleGUI
{
JFrame frame;
public int x,y;
public int vx = 10,vy=5;
public int width = 500,height = 500;
public int diameter=50;
CircleDrawPanel drawPanel;
Color color = Color.magenta.darker();
JButton button;
Timer timer2 = new Timer(25, new AnimateCircleListener());
boolean isRunning = false;
public static void main (String[] args)
{
MovingCircleGUI gui = new MovingCircleGUI();
gui.go();
}
//this method sets up the JFrame and adds the draw panel to the frame
public void go()
{
frame = new JFrame("MovingCircleGUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawPanel = new CircleDrawPanel();
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
button = new JButton("Click me to start the animation");
drawPanel.add(button);
frame.getContentPane().add(BorderLayout.SOUTH , button);
button.addActionListener(new AnimateCircleListener());
frame.setSize(width,height);
frame.setVisible(true);
}
class CircleDrawPanel extends JPanel
{
public void paintComponent (Graphics g)
{
super.paintComponent(g);
Graphics2D g2=(Graphics2D)g;
g2.setColor(color);
g2.fillOval(x,y,diameter,diameter);
}
}
public void MovingBall()
{
x = x + vx;
y = y + vy;
if( y >= height)
{
y=0;
boolean xIsSame = true;
int randomX = 0;
do
{
randomX = Math.round((float)Math.random()*width);
if (randomX != x)
{
x = randomX;
}
}
while(!xIsSame);
}
if(x <= 0)
{
x = width+x;
}
if (x >= width)
{
x = x-width;
}
frame.repaint();
}
class AnimateCircleListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource()== button)
{
if(timer2.isRunning())
{
button.setText("Click me to start the animation");
button.revalidate();
timer2.stop();
}
else
{
button.setText("Click me to stop the animation");
button.revalidate();
timer2.start();
}
}
if(e.getSource()==timer2)
{
MovingBall();
}
}
}
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;
}
}
You can remove the previous ActionListener on the JButton using button.removeActionListener(<your first action listener>) and then add the second action listener using button.addActionListener(<your second action listener>). Then, to change the text on the button, just use button.setText("Your Text Here").
Related
I have a question.
I'm studying java.
In this code, I want to slower/faster the ball that created after I clicked "slower/faster" Menu button.
I mean, when I added ball and when the ball I added is moving, and then I click slow or fast button, and the ball that was moving has the same speed, and the ball that created after I clicked button, that ball's speed have to be changed.
I tried lock and unlock method in BallRunnable class, but it doesn't work.
Could you give me an advice? Thanks :)
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
import java.util.List;
import java.util.concurrent.locks.*;
public class BallBounce {
public static void main(String[] args) {
JFrame frame = new BounceFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
/**
A runnable that animates a bouncing ball.
*/
class BallRunnable implements Runnable {
public BallRunnable(Ball aBall, JPanel ballPanel) {
ball = aBall; this.ballPanel = ballPanel;
ballLock = new ReentrantLock();
}
public void run() {
ballLock.lock();
try {
for (int i = 1; i <= STEPS; i++) {
ball.move(ballPanel.getBounds()); // update the location of the ball
ballPanel.paint(ballPanel.getGraphics());
Thread.sleep((long)(DELAY * change));
}
} catch (InterruptedException e) { System.out.println("what"); }
finally { ballLock.unlock(); }
}
public static void print() { System.out.println(DELAY * change); }
public static void setdoublechange() {
change = change * 2;
}
public static void sethalfchange() {
change = change / 2;
}
private Ball ball;
private JPanel ballPanel;
public static final int STEPS = 1000;
public static final int DELAY = 3;
private static double change = 1;
private static Lock ballLock;
}
class BallRunnable2 implements Runnable {
public BallRunnable2(Ball aBall, JPanel ballPanel) {
ball = aBall; this.ballPanel = ballPanel;
}
public void run() {
ballLock.lock();
try {
Thread.sleep(100);
for (int i = 1; i <= STEPS; i++) {
ball.move(ballPanel.getBounds()); // update the location of the ball
ballPanel.paint(ballPanel.getGraphics());
Thread.sleep(DELAY * change);
}
} catch (InterruptedException e) { }
finally { ballLock.unlock(); }
}
public static void setdoublechange() {
change = change * 2;
}
public static void sethalfchange() {
change = change / 2;
}
private Ball ball;
private JPanel ballPanel;
public static final int STEPS = 1000;
public static final int DELAY = 3;
public static int change = 1;
private Lock ballLock;
}
/**
A ball that moves and bounces off the edges of a rectangle
*/
class Ball {
/**
Moves the ball to the next position, reversing direction if it hits one of the edges
*/
public void move(Rectangle2D bounds) { // java.awt.geom.Rectangle2D
x += dx; y += dy;
if (x < bounds.getMinX()) { x = bounds.getMinX(); dx = -dx; }
if (x + XSIZE >= bounds.getMaxX()) { x = bounds.getMaxX() - XSIZE; dx= -dx; }
if (y < bounds.getMinY()) { y = bounds.getMinY(); dy = -dy; }
if (y + YSIZE >= bounds.getMaxY()) { y = bounds.getMaxY() - YSIZE; dy = -dy; }
}
/**
Gets the shape of the ball at its current position.
*/
public Ellipse2D getShape() { return new Ellipse2D.Double(x, y, XSIZE, YSIZE); }
private static final int XSIZE = 15;
private static final int YSIZE = 15;
private double x = 0;
private double y = 0;
private double dx = 1;
private double dy = 1;
}
/**
The panel that draws the balls.
*/
class BallPanel extends JPanel {
/**
Add a ball to the panel.
#param b the ball to add
*/
public void add(Ball b) {
balls.add(b);
}
public void paintComponent (Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (Ball b : balls) { g2.fill(b.getShape()); }
}
private List<Ball> balls = new ArrayList<>();
}
class BounceFrame extends JFrame {
public BounceFrame() {
setTitle("BounceThread");
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
ballPanel = new BallPanel(); add(ballPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
addButton(buttonPanel, "Add 1", new ActionListener() {
public void actionPerformed(ActionEvent event) { addBall1(); }
});
addButton(buttonPanel, "Add 2", new ActionListener() {
public void actionPerformed(ActionEvent event) { addBall2(); }
});
addButton(buttonPanel, "Close", new ActionListener() {
public void actionPerformed(ActionEvent event) { System.exit(0); }
});
// addButton(buttonPanel, "Close", (ActionEvent event) -> System.exit(0));
add(buttonPanel, BorderLayout.SOUTH);
JMenu speedMenu = new JMenu("Speed");
JMenuItem fasterItem = speedMenu.add(new fasterAction("Faster"));
JMenuItem slowerItem = speedMenu.add(new slowerAction("Slower"));
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
menuBar.add(speedMenu);
}
private void addButton(Container container, String title, ActionListener listener) {
JButton button = new JButton(title);
container.add(button);
button.addActionListener(listener);
}
/**
Adds a bouncing ball to the canvas and starts a thread to make it bounce
*/
public void addBall1() {
Ball b = new Ball();
ballPanel.add(b);
Runnable r = new BallRunnable(b, ballPanel);
Thread t = new Thread(r);
t.start();
}
public void addBall2() {
Ball b1 = new Ball();
Ball b2 = new Ball();
ballPanel.add(b1);
ballPanel.add(b2);
Runnable r1 = new BallRunnable(b1, ballPanel);
Runnable r2 = new BallRunnable2(b2, ballPanel);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
private BallPanel ballPanel;
public static final int DEFAULT_WIDTH = 450;
public static final int DEFAULT_HEIGHT = 350;
}
class fasterAction extends AbstractAction {
public fasterAction(String name) { super(name); }
public void actionPerformed(ActionEvent event) {
BallRunnable.sethalfchange();
BallRunnable2.sethalfchange();
}
}
class slowerAction extends AbstractAction {
public slowerAction(String name) { super(name); }
public void actionPerformed(ActionEvent event) {
BallRunnable.setdoublechange();
BallRunnable2.setdoublechange();
}
}
Increase Thread.sleep() value (it is in milliseconds)
Changing dx and/or dy of the ball (when a certain condition is met).
If I am correct <dx, dy> is the velocity of the ball.
I'm making Arkanoid game in Java Swing. When I run my game KeyEvent not working.
Why is the game not detecting key events?
Main class in my program make a frame (JFrame). Also I have Manage class which managing all classes from my game.
This is the code: Player class is class of paddle in my game.
//imports
public class Player extends JPanel implements ActionListener, KeyListener
{
private int x, y, width, height;
private Timer timer;
private int fps = 60;
private int delay = 1000/fps;
public Player(int x, int y, int width, int height)
{
//setFocusable(true);
addKeyListener(this);
this.x = x;
this.y = y;
this.width = width;
this.height = height;
timer = new Timer(delay, this);
timer.start();
}
#Override
public void actionPerformed(ActionEvent e)
{
timer.start();
repaint();
}
#Override
public void keyPressed(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_A:
if (x <= 0) {
x = 0;
} else {
x -= 3;
}
break;
case KeyEvent.VK_D:
if (x >= 600) {
x = 600;
} else {
x += 3;
}
break;
}
}
public void paint(Graphics g)
{
g.setColor(Color.BLUE);
g.fillRect(x, y, width, height);
}
#Override
public void keyTyped(KeyEvent e) { }
#Override
public void keyReleased(KeyEvent e) { }
}
The main problem with that code was that the custom painted component was neither focusable nor focused (so could not receive key events).
This code fixes those problems as well as a couple more (check code comments for details).
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Player extends JPanel implements ActionListener, KeyListener {
private int x, y, width, height;
private final Timer timer;
private final int fps = 60;
private final int delay = 1000 / fps;
public Player(int x, int y, int width, int height) {
addKeyListener(this);
this.x = x;
this.y = y;
this.width = width;
this.height = height;
timer = new Timer(delay, this);
timer.start();
// a component must be focusable to get key events!
setFocusable(true);
}
#Override
public void actionPerformed(ActionEvent e) {
//timer.start(); // Timer should already be started!
repaint();
}
#Override
// correct method for custom painting a JComponent is paintComponent!
public void paintComponent(Graphics g) {
// call the super method to ensure previous paints are erased!
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(x, y, width, height);
}
#Override
// a custom painted component should suggest a size to be used by the
// layout manager
public Dimension getPreferredSize() {
return new Dimension(400,100);
}
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_A:
if (x <= 0) {
x = 0;
} else {
x -= 3;
}
break;
case KeyEvent.VK_D:
if (x >= 600) {
x = 600;
} else {
x += 3;
}
break;
}
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
public static void main(String[] args) {
Runnable r = () -> {
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationByPlatform(true);
Player player = new Player(2, 2, 5, 20);
f.setContentPane(player);
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
// a component must be focused to detect key events!
player.requestFocusInWindow();
};
SwingUtilities.invokeLater(r);
}
}
I'm all new to this site and to Java, so please be lenient.
I'm writing a program that allows to draw different type of shapes with a button click and after hitting another button move/stop/reset them.
I've made already the most part I think (the shapes are correctly creating and storing in an arraylist, the same with the reset, which clear the screen), but I can't figure out how to make them move.I got a function for movement but can't find a way to make the shapes form the arraylist to move. Can anyone give me a little advise.
Thanks
P.S. If there is something wrong/bad coding and needs to be fixed I'll be grateful if you will point at them.
Here is my code:
MyShape class is for creating different shapes.
import java.awt.*;
import java.util.Random;
public abstract class MyShape extends Component {
protected Color color;
private int x, y, dimX, dimY;
public Random random = new Random();
public MyShape(int x, int y, int dimX, int dimY){
this.x = x;
this.y = y;
this.dimX = dimX;
this.dimY = dimY;
color = new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255));
}
public abstract void draw(Graphics g);
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 getDimX() {
return dimX;
}
public void setDimX(int dimX) {
this.dimX = dimX;
}
public int getDimY() {
return dimY;
}
public void setDimY(int dimY) {
this.dimY = dimY;
}
}
CircleShape - creating circles.
import java.awt.*;
public class CircleShape extends MyShape {
public CircleShape(int x, int y, int dimX, int dimY) {
super(x, y, dimX, dimY);
}
#Override
public void draw(Graphics g) {
g.setColor(color);
g.fillOval(getX(), getY(), getDimX(), getDimY());
}
}
RectangleShape - rectangles
import java.awt.*;
public class RectangleShape extends MyShape {
public RectangleShape(int x, int y, int dimX, int dimY) {
super(x, y, dimX, dimY);
}
#Override
public void draw(Graphics g) {
g.setColor(color);
g.fillRect(getX(), getY(), getDimX(), getDimY());
}
}
and the DrawShape class which handles pretty much everything
public class DrawShapes extends JPanel {
private JButton addButton, resumeAllButton, stopAllButton, resetButton;
private final int FRAME_WIDTH = 800;
private final int FRAME_HEIGHT = 530;
private int x, y, dimX, dimY;
private Random random = new Random();
public List<MyShape> myShapeList = new CopyOnWriteArrayList<MyShape>();
private Timer timer = null;
public boolean move = false;
public DrawShapes() {
this.setLayout(null);
addButton = new JButton("Add Shape");
resumeAllButton = new JButton("Resume Shapes");
stopAllButton = new JButton("Stop All Shapes");
resetButton = new JButton("Reset");
addButton.setBounds(40, 20, 150, 30);
resumeAllButton.setBounds(230, 20, 150, 30);
stopAllButton.setBounds(420, 20, 150, 30);
resetButton.setBounds(610, 20, 150, 30);
this.add(addButton);
this.add(resumeAllButton);
this.add(stopAllButton);
this.add(resetButton);
stopAllButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
move = false;
}
});
resumeAllButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
move = true;
}
});
addButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Thread thread = new Thread() {
public void run() {
init();
}
};
thread.start();
}
});
resetButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < myShapeList.size(); i++) {
myShapeList.clear();
repaint();
}
}
});
}
public void moveIt() {
boolean directionUp = random.nextBoolean();
boolean directionLeft = random.nextBoolean();
boolean directionDown = !directionUp;
boolean directionRight = !directionLeft;
while (move) {
if (x <= 0) {
directionRight = true;
directionLeft = false;
}
if (x >= FRAME_WIDTH - dimX) {
directionRight = false;
directionLeft = true;
}
if (y <= 70) {
directionUp = false;
directionDown = true;
}
if (y >= FRAME_HEIGHT + 50 - dimY) {
directionUp = true;
directionDown = false;
}
if (directionUp)
y--;
if (directionDown)
y++;
if (directionLeft)
x--;
if (directionRight)
x++;
}
}
public void init() {
x = 0;
y = 0;
dimX = (random.nextInt(FRAME_WIDTH) + 100) / 2;
dimY = (random.nextInt(FRAME_HEIGHT) + 100) / 2;
while (x <= 0)
x = (random.nextInt(FRAME_WIDTH) - dimX);
while (y <= 70)
y = (random.nextInt(FRAME_HEIGHT) - dimY);
int choice = 0;
choice = random.nextInt(2) + 1;
switch (choice) {
case 1:
RectangleShape rectangleShape = new RectangleShape(x, y, dimX, dimY);
myShapeList.add(rectangleShape);
timer.start();
repaint();
break;
case 2:
CircleShape circleShape = new CircleShape(x, y, dimX, dimY);
myShapeList.add(circleShape);
repaint();
break;
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0, 70, 800, 530);
for (MyShape aMyShapeList : myShapeList) {
aMyShapeList.draw(g);
}
}
public static void main(String args[]) {
JFrame jFrame = new JFrame();
jFrame.add(new DrawShapes());
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setSize(800, 600);
jFrame.setResizable(false);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
jFrame.setLocation(dim.width / 2 - jFrame.getSize().width / 2, dim.height / 2 - jFrame.getSize().height / 2);
jFrame.setLocationRelativeTo(null);
jFrame.setVisible(true);
}
}
From the code you posted I can see that you are not calling your moveIt() method anywhere.
You have the right idea of how to move things around. The basic algorithm is:
Calculate new positions
Repaint the view
I can recommend you do the following:
You are currently calling your init method in a thread. I am not sure this is needed. Remove the thread logic and just call the method on the main thread.
Introduce another button tho start the actual animation. When clicking, create a thread that will call your moveIt() method.
I want to add 2 buttons to the following code that will let me "FREEZE" and "START" the ball move as it bounces on the window. I've been trying to do this for the last hour but I cant figure this out. I did some work but it mostly crap, if anyone wants please let me know to post it(avoided it in order not to extend my coding). Anyone can help me with this?
Open to any suggestions.
Thanks
import java.awt.*;
import javax.swing.*;
public class BallMoves extends JPanel implements Runnable {
Color color = Color.red;
int dia = 30;
long delay = 40;
private int x = 1;
private int y = 1;
private int dx = 3;
private int dy = 7;
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
g.fillOval(x,y,30,30); // adds color to circle
g.setColor(Color.red);
g2.drawOval(x,y,30,30); // draws circle
}
public void run() {
while(isVisible()) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move();
repaint();
}
}
public void move() {
if(x + dx < 0 || x + dia + dx > getWidth()) {
dx *= -1;
color = getColor();
}
if(y + dy < 0 || y + dia + dy > getHeight()) {
dy *= -1;
color = getColor();
}
x += dx;
y += dy;
}
private Color getColor() {
int rval = (int)Math.floor(255);
int gval = (int)Math.floor(0);
int bval = (int)Math.floor(0);
return new Color(rval, gval, bval);
}
private void start() {
while(!isVisible()) {
try {
Thread.sleep(25);
} catch(InterruptedException e) {
System.exit(1);
}
}
Thread thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
public static void main(String[] args) {
BallMoves test = new BallMoves();
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(test);
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
test.start();
}
}
Update version
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class BallMoves extends JPanel implements Runnable {
Color color = Color.red;
int dia = 30;
long delay = 40;
private int x = 1;
private int y = 1;
private int dx = 3;
private int dy = 7;
private boolean isRunning;
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
g.fillOval(x,y,30,30); // adds color to circle
g.setColor(Color.red);
g2.drawOval(x,y,30,30); // draws circle
}
public void run() {
while(isVisible()) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move();
repaint();
}
}
public void move() {
if (isRunning) {
if(x + dx < 0 || x + dia + dx > getWidth()) {
dx *= -1;
color = getColor();
}
if(y + dy < 0 || y + dia + dy > getHeight()) {
dy *= -1;
color = getColor();
}
x += dx;
y += dy;
}
}
private Color getColor() {
int rval = (int)Math.floor(255);
int gval = (int)Math.floor(0);
int bval = (int)Math.floor(0);
return new Color(rval, gval, bval);
}
private void start() {
while(!isVisible()) {
try {
Thread.sleep(25);
} catch(InterruptedException e) {
System.exit(1);
}
}
Thread thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
final BallMoves test = new BallMoves();
JFrame f = new JFrame();
JButton start = new JButton("start");
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
test.isRunning = true;
}
});
JButton stop = new JButton("stop");
stop.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
test.isRunning = false;
}
});
JPanel panel = new JPanel();
panel.add(start);
panel.add(stop);
f.add(panel, java.awt.BorderLayout.NORTH);
f.getContentPane().add(test);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(new Dimension(400, 400));
f.setLocationRelativeTo(null);
f.setVisible(true);
test.start();
}
});
}
}
Create a flag and switch it on button click.
private volatile boolean isRunning;
public void move() {
if (isRunning) {
// your existing code
...
}
}
on start button click
isRunning = true;
on stop button click
isRunning = false;
Im working on an assignment where an image moves around and when the user clicks on the panel the image stops. When the user clicks on the panel again the image starts. As of now i can only start and stop the image once before it stays going. I need help to loop this process so that the user can keep starting and stopping the image.
Here is my code
Main:
import javax.swing.*;
public class Rebound {
//-----------------------------------------------------------------
// Displays the main frame of the program.
//-----------------------------------------------------------------
public static void main (String[] args)
{
JFrame frame = new JFrame ("Rebound");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ReboundPanel());
frame.pack();
frame.setVisible(true);
}
}
Panel:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ReboundPanel extends JPanel
{
private final int DELAY = 10, IMAGE_SIZE = 35;
private ImageIcon image;
private Timer timer;
private int x, y, moveX, moveY;
public ReboundPanel()
{
timer = new Timer(DELAY, new ReboundListener());
addMouseListener (new StopListener());
image = new ImageIcon ("happyFace.gif");
x = 0;
y = 40;
moveX = moveY = 3;
setPreferredSize (new Dimension(1900, 1000));
setBackground (Color.black);
timer.start();
}
public void paintComponent (Graphics page)
{
super.paintComponent (page);
image.paintIcon (this, page, x, y);
}
private class ReboundListener implements ActionListener
{
public void actionPerformed (ActionEvent event)
{
x += moveX;
y += moveY;
if (x <= 0 || x >= 1900-IMAGE_SIZE)
moveX = moveX * -1;
if (y <= 0 || y >= 1000-IMAGE_SIZE)
moveY = moveY * -1;
repaint();
}
}
// Represents the action listener for the timer.
public class StopListener extends MouseAdapter
{
public void mouseClicked (MouseEvent event)
{
if (event.getButton() == MouseEvent.BUTTON1)
{
timer.stop();
}
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent event) {
if(event.getButton() == MouseEvent.BUTTON1)
{
timer.start();
removeMouseListener(this);
}
}
});
}
}
}
You can simply reuse the same listener, and check the state of the timer before starting/stopping it:
public void mouseClicked(MouseEvent event)
{
if (event.getButton() == MouseEvent.BUTTON1)
{
if (timer.isRunning()) {
timer.stop();
}
else {
timer.start();
}
}
}
In you StopListener class have an instance variable bool isMoving = true;
Then in your handler should use that to determine whether to stop or start the timer:
public void mouseClicked( MouseEvent event )
{
if( event.getButton() == MouseEvent.BUTTON1 )
{
if( isMoving )
timer.stop();
else
timer.start();
isMoving = !isMoving;
}
}