Reputation: 1491
I have a program that animates a ball in a Jpanel. I have two buttons Stop and Go. Stop stops the ball moving and go is meant for the ball to move around. In my ball class I have a boolean variable that if it is true the ball moves and if it is false the ball doesn't move. So I thought in my main class when I create the frame and put the ball class in the panel I could use the buttons to change the variable to false or true depending on the button press.
public class BallTask extends JPanel implements ActionListener{
public static boolean run = false;
public BallTask(){
this.setPreferredSize(new Dimension(width, height));
Thread gameThread = new Thread() {
public void run() {
while (run) {
.... working code
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame window = new JFrame();
window.setLayout(new BorderLayout());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.add(new BallTask());
JPanel buttons = new JPanel();
JButton stop = new JButton("STOP");
stop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
run = false;
}
});
JButton go = new JButton("GO");
go.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
run = true;
}
});
buttons.add(go);
buttons.add(stop);
window.add(buttons,BorderLayout.SOUTH);
window.pack();
window.setVisible(true);
}
});
The problem I have with the code is that the buttons don't actually change the boolean value in the BallTask class. Any ideas?
Upvotes: 0
Views: 294
Reputation: 208944
Look into using a javax.swing.Timer
. Your while loop will block the EDT not allowing the button events to be dispatched.
With the timer, you can just use it's methods stop
and start
to, well, start and stop the timer. You can see an example here
Here's a runnable example using a Timer
with your code. The code in the link above is cleaner, using a Ball
object. I just threw this one together really quick
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class BallTask {
public static boolean run = false;
private Timer timer;
private BallPanel ballPanel = new BallPanel();
public BallTask() {
timer = new Timer(30, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (ballPanel.x < 0 || ballPanel.x > ballPanel.getWidth()) {
ballPanel.dx = -ballPanel.dx;
}
if (ballPanel.y < 0 || ballPanel.y > ballPanel.getHeight()) {
ballPanel.dy = -ballPanel.dy;
}
// Adjust ball position
ballPanel.x += ballPanel.dx;
ballPanel.y += ballPanel.dy;
ballPanel.repaint();
}
});
JPanel buttons = new JPanel();
JButton stop = new JButton("STOP");
buttons.add(stop);
stop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.stop();
}
});
JButton go = new JButton("GO");
buttons.add(go);
go.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(ballPanel);
mainPanel.add(buttons, BorderLayout.SOUTH);
JFrame window = new JFrame();
window.add(mainPanel);
window.pack();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
private class BallPanel extends JPanel {
private int x;
private int y;
int dx = 4; // Increment on ball's x-coordinate
int dy = 4; // Increment on ball's y-coordinate
int radius = 15; // Ball radius
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillOval(x, y, 30, 30);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(500, 300);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new BallTask();
}
});
}
}
Upvotes: 2