dark_matter88 dark_matter88 - 1 month ago 5
Java Question

How to make a shape move by pressing key once in Java?

I have a task in university to draw an ellipse and make it move step by step on the screen pressing the button only once. Here is my code:

public class Window extends JPanel {

private static Ellipse2D.Double Ellipse;
private JFrame frame;

public Window() {
super();
int width = 20;
int height = 30;
Ellipse = new Ellipse2D.Double(width, height, 100, 50);
}

public Dimension getPreferredSize()
{
return (new Dimension(frame.getWidth(), frame.getHeight()));
}

@Override
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D brush = (Graphics2D) g;
int width = getWidth();
int height = getHeight();
g.clearRect(0, 0, width, height);
brush.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
brush.draw(Ellipse);
}
public class MoveCircle implements KeyListener, ActionListener {

@Override
public void keyPressed(KeyEvent e) {
System.out.println("Working on top!");
double newX = 0; double newY = 0;
if (e.getKeyCode() == Event.ENTER) {
for (int i = 0; i < 26; i ++)
{
System.out.println("Working on bottom!");
newX = Ellipse.x + 10;
Ellipse.x = newX;
newY = Ellipse.y + 10;
Ellipse.y = newY;
repaint();
}
}
}

@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}

@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}

@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub

}
}
private void createAndDisplayGUI(Window window)
{
frame = new JFrame();
Container container = frame.getContentPane();
container.add(window);
window.addKeyListener(new MoveCircle());
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
window.requestFocusInWindow();
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Window window = new Window();
window.createAndDisplayGUI(window);
}
});
}


}

Although I call the function repaint() in cycle each time still the ellipse just moves radically from the original point to the point defined in the last iteration without drawing position of the ellipse in each iteration.
Is it possible to use a Swing Timer to make it repaint the ellipse in each iteration? I will be very glad to get help in this.

Answer

You have two problems: The first is that your loop is being run on the UI thread. The second is your misunderstanding in how repaint works. All repaint does is adds a request to the UI thread to do a repaining. It does perform a repaint in and of itself. So if you are running operations on the UI thread, calling it multiple times will have no effect. As you suggested, you can fix this with a Swing Timer, as I've put together below

ActionListener al = new ActionListener() {
  int iterations = 0;
  public void actionPerformed(ActionEvent ae) {
           if (iterations == 25) {
             timer.stop();
           }
           interations++;
           System.out.println("Working on bottom!");
            newX = Ellipse.x + 10;
            Ellipse.x = newX;
            newY = Ellipse.y + 10;
            Ellipse.y = newY;   
            repaint();                  
  }
};

final timer = new javax.swing.Timer(delay, al);
timer.start();