Search code examples
javaswingjframeosx-mountain-lion

Java Moving JFrames Choppy Motion


I have the following three classes: Rndm:

import java.util.*;
public class Rndm {
    private static Random rn;
    public static String randInt(int min, int max)
    {
        return Integer.toString((min + (int)(Math.random()*(max-min))));
    }
    public static String randInt(int max)
    {
        return Integer.toString(((int)(Math.random()*(max))));
    }
    public static int intRandInt(int min, int max)
    {
         return (min + (int)(Math.random()*(max-min)));
    }
    public static int intRandInt(int max)
    {
        return (int)(Math.random()*(max));
    }
    public static String randString(int length)
    {
        String randstr="";
        for (int i=0; i<=length; i++)
        {
            int charset = 1 + (int)(Math.random()*3);
            if (charset==1)
            {
                char randChar = (char) (48 + (int)(Math.random()*(57-48)));
                randstr += randChar;
            }
            else if (charset==2)
            {
                char randChar = (char) (65 + (int)(Math.random()*(90-65)));
                randstr += randChar;
            }
            else if (charset==3)
            {
                char randChar = (char) (97 + (int)(Math.random()*(122-97)));
                randstr += randChar;
            }
        }
        return randstr;
    }
}

MovingWindow (a moving JFrame):

import java.awt.*;
import javax.swing.*;
import java.util.*;

public class MovingWindow implements Runnable {
    private JFrame frame;
    private Point location;
    private Thread t;
    private int x;
    private int y;
    private int increment = 15;
    private int delay = 1;
    public MovingWindow(String tName) {
        t = new Thread(this, tName);
        t.start();
    }
    public void run() {
        drawFrame();
    }
    private void drawFrame() {
        frame = new JFrame("Moving Window");
        x = Rndm.intRandInt(70, 1000);
        y = Rndm.intRandInt(70, 1000);
        location = new Point(x, y);
        frame.setSize(500, 50);
        frame.setLocation(location);
        frame.setVisible(true);
        moveAround();
    }
    public void moveAround() {
        while(true) {
            int dir = Rndm.intRandInt(0, 9);
            switch(dir) {
                case 1:
                    quad1();
                    break;
                case 2:
                    quad2();
                    break;
                case 3:
                    quad3();
                    break;
                case 4:
                    quad4();
                    break;
                case 5:
                    quad5();
                    break;
                case 6:
                    quad6();
                    break;
                case 7:
                    quad7();
                    break;
                case 8:
                    quad8();
                    break;
                default:
            }
        }
    }
    public void quad1() {
        while (x<1000 && y<1000) {
            try { Thread.sleep(delay); } catch (java.lang.InterruptedException e) {}
            setX(x+increment);
            setY(y+increment);
        }
    }
    public void quad2() {
        while (x<1000 && y>0) {
            try { Thread.sleep(delay); } catch (java.lang.InterruptedException e) {}
            setX(x+increment);
            setY(y-increment);
        }
    }
    public void quad3() {
        while (x>0 && y>0) {
            try { Thread.sleep(delay); } catch (java.lang.InterruptedException e) {}
            setX(x-increment);
            setY(y-increment);
        }
    }
    public void quad4() {
        while (x>0 && y<1000) {
            try { Thread.sleep(delay); } catch (java.lang.InterruptedException e) {}
            setX(x-increment);
            setY(y+increment);
        }
    }
    public void quad5() {
        while (x>0) {
            setX(x-increment);
        }
    }
    public void quad6() {
        while (x<1000) {
            setX(x+increment);
        }
    }
    public void quad7() {
        while (y>0) {
            setY(y-increment);
        }
    }
    public void quad8() {
        while (y<1000) {
            setY(y+increment);
        }
    }
    public void setX(int x) {
        this.x = x;
        location = new Point(x, y);
        frame.setLocation(location);
    }
    public void setY(int y) {
        this.y = y;
        location = new Point(x, y);
        frame.setLocation(location);
    }
}

and WindowManager (instantiates MovingWindow objects):

import java.util.ArrayList;
public class WindowManager {
    public static void main(String[] args) {
        ArrayList<MovingWindow> windows = new ArrayList<MovingWindow>();
        for (int i=0; i<Integer.parseInt(args[0]); i++) {
            windows.add(new MovingWindow(Rndm.randString(10)));
        }
    }
}

The program behaves as expected until more than one frame is created. At that point, all but one or two frames slow down dramatically for a little while, resume moving normally for a few seconds, and then begin moving slowly again. I have a two part question: 1: Why is this happening? 2: How can I fix it? I am running java 7 on OSX Mavericks. Thanks in advance


Solution

  • You're calling moveAround() from the main thread, and you're changing the GUI from there. That's a big no-no. All changes to the GUI have to be on the Event Dispatching Thread, or EDT.

    However, you should never call Thread.sleep() on the EDT, so your current approach won't work.

    I would look into using a Swing Timer instead.