I am trying to make an oval move smoothly by taping the buttons (up,down,...)and I try to use threads with the try and catch it\'s work inside the class but when I use it he
Thread.sleep()
on the Event Dispatch Thread. EVER!!It never accomplishes anything good, and it makes your screen freeze until the sleep is over. So don't do it!!
The best way to animate in Swing is to use a javax.swing.Timer to fire events that change your drawing properties periodically. This happens on a different thread so the screen stays responsive. You can set this timer to run all the time, but have it do nothing when the circle should not be moving. Here's the code for the Timer
's ActionListener
t = new Timer(TIMER_DELAY, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(deltaX == 1 && x >= frame.getWidth() - CIRCLE_WIDTH) deltaX = 0;
if(deltaY == 1 && y >= frame.getHeight() - CIRCLE_HEIGHT) deltaY = 0;
if(deltaX == -1 && x <= 0) deltaX = 0;
if(deltaY == -1 && y <= 0) deltaY = 0;
x += deltaX;
y += deltaY;
if(deltaX != 0 || deltaY != 0) {
frame.repaint();
}
}
});
t.start();
Then, your buttons just tell the timer to animate in the correct direction by setting the delta value, e.g.
class movingup implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
deltaY = -1;
}
}// moving up end
As you can see, I create a timer object inside start
method, and just tell the timer to start animating by pressing the button. The timer has it's own, different ActionListener
(implemented as an anonymous class here) that actually tells the parameters to change and then repaints if something has moved. You could optimize it further by telling Swing to only redraw the part of the screen that needs redrawing with JComponent.repaint(Rectangle), but this is just an example. If you do this, make sure the repaint is large enough to get both where the circle was and where it is now.
Here's the complete program, including the constants CIRCLE_WIDTH
and CIRCLE_HEIGHT
, the new timer logic, and all four buttons changed:
package swingWork;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class movingball {
private static final int CIRCLE_WIDTH = 100;
private static final int CIRCLE_HEIGHT = 100;
private static final int TIMER_DELAY = 50;
JFrame frame;
int x = 0;
int y = 0;
int deltaX = 0;
int deltaY = 0;
Timer t;
public static void main(String[] args) {
movingball ball = new movingball();
ball.start();
}
public void start() {
ballDrawer drawer = new ballDrawer();
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton up = new JButton("UP");
JButton down = new JButton("DOWN");
JButton left = new JButton("LEFT");
JButton right = new JButton("RIGHT");
frame.getContentPane().add(BorderLayout.NORTH, up);
frame.getContentPane().add(BorderLayout.SOUTH, down);
frame.getContentPane().add(BorderLayout.WEST, left);
frame.getContentPane().add(BorderLayout.EAST, right);
frame.getContentPane().add(BorderLayout.CENTER, drawer);
// setting up the action listener:
up.addActionListener(new movingup());
down.addActionListener(new movingdown());
left.addActionListener(new movingleft());
right.addActionListener(new movingright());
frame.setSize(300, 300);
frame.setVisible(true);
t = new Timer(TIMER_DELAY, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(deltaX == 1 && x == frame.getWidth() - CIRCLE_WIDTH) deltaX = 0;
if(deltaY == 1 && y == frame.getHeight() - CIRCLE_HEIGHT) deltaY = 0;
if(deltaX == -1 && x == 0) deltaX = 0;
if(deltaY == -1 && y == 0) deltaY = 0;
x += deltaX;
y += deltaY;
if(deltaX != 0 || deltaY != 0) {
frame.repaint();
}
}
});
t.start();
}// start method end
// here we have the listeners
class movingup implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
deltaY = -1;
}
}// moving up end
class movingdown implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
deltaY = 1;
}
}// movingdown end
class movingleft implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
deltaX = -1;
}
}// moving left end
class movingright implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
deltaX = 1;
}
}// moving right end
class ballDrawer extends JPanel {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.black);
g.fillOval(x, y, CIRCLE_WIDTH, CIRCLE_HEIGHT);
}// PaintComponents End
}// ball drawer class end
}// main class endreading: http://stackoverflow.com/q/15511282/1768232