简体   繁体   中英

Simple animation using Thread.sleep() in ActionListener

I'm having trouble with this code I am using to create a roulette wheel. The goal is to spin the wheel when I click the "SPIN!" button. I have done this by creating a for loop that should change the status of the wheel from true to false, which changes the orientation. This, when done fast enough, should create the illusion of movement.

THE PROBLEM I AM HAVING : is that my wheel is only repainting after the whole for loop is done, despite my placement of the repaint(). So, it only spins one tick.

Here is some sample code of my ActionListener:

public class spinListener implements ActionListener
{
    RouletteWheel wheel;
    int countEnd = (int)(Math.random()+25*2);
    public spinListener(RouletteWheel w)
    {
        wheel = w;
    }
    public void actionPerformed(ActionEvent e)
    {
        for (int i = 0; i <countEnd; i++)
        {
            try 
            {
                Thread.sleep(100);
                if (wheel.getStatus() == true)
                {
                    wheel.setStatus(false);
                    repaint();
                }
                if (wheel.getStatus() == false)
                {
                    wheel.setStatus(true);
                    repaint();
                }
            } 
            catch (InterruptedException ex) 
            {
                Logger.getLogger(WheelBuilder.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

UPDATE: I figured out the problem. Here are the changes I made for anyone having a similar problem.

public class spinListener implements ActionListener
{
    Timer tm = new Timer(100, this);
    int count = 0;

    public void actionPerformed(ActionEvent e)
    {
        tm.start();
        changeWheel();
    }
    public void changeWheel()
    {
        int countEnd = (int)(Math.random()+20*2);
        if (count < countEnd)
        {
            wheel.setStatus(!wheel.getStatus());
            repaint();
            count++;
        }
    }
}

Swing is a single threaded environment, anything that blocks the Event Dispatching Thread, will prevent it from been able to process new events, including, paint events.

The use of Thread.sleep within the actionPerformed method is blocking the EDT, preventing it from processing new events, including paint events, until the actionPerformed method is exited.

You should use a javax.swing.Timer instead.

Take a look at Concurrency in Swing and How to Use Swing Timers for more details

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM