1

I'm trying to make a while loop that increments a double by 0.1 once every second:

    public void keyReleased(KeyEvent e)
    {
    //When a key is released, look for any collision problems
    airOrGround(xPos, yPos);
    collision(xPos, yPos);
    //As long as onGround (which is set to false or true in airOrGround) is false,
    //yPos should increment by 1 every second
    while(onGround == false)
    {
        try {
            Thread.sleep(1*1000);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        yPos += 0.1;
        yPos = (Math.round(yPos * 10) / 10.0);
        start.setText("X = " + xPos + ", Y = " + yPos);
        airOrGround(xPos, yPos);
    }
}

Once I run it, as soon as the keyReleased() runs, the program freezes. I've also tried putting the while loop inside the try, but that doesn't work either. No errors appear in the console and without the Thread.sleep part it doesn't freeze

Koen
  • 23
  • 8
  • 2
    It's freezing because you're putting the Event Despatch Thread to sleep. You might want to read up about: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html – tddmonkey Feb 07 '16 at 16:30
  • Perhaps `onGround` never changes to `true'? – pablochan Feb 07 '16 at 16:30
  • 2
    `Thread.sleep(1*1000)`? Why not just `1000`? – Jonah Feb 07 '16 at 16:32
  • 1
    I suggest taking a look at a [SwingWorker](https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html). With that you can safely update a Swing Component on the EDT while doing calculations on a separate thread with a delay. – Jonah Feb 07 '16 at 16:36
  • By the way, you dont need to compare a boolean with either true or false. In order to loop for as long as a boolean is false, you need to do the following: `loop(!boolean){...}` and for true `loop(boolean){...}`. The reason it freezes is because the loop blocks and it is running on the main thread so it blocks the main thread. Use a timer implementation or run the loop asynchronously. – fill͡pant͡ Feb 07 '16 at 17:12

2 Answers2

1

You should look at javax.swing.Timer class.

public class Whatever
{
    javax.swing.Timer t = new javax.swing.Timer( 1000, new MyListener() );
    ...
    t.start();
}

public class MyListener() implements ActionListener
{
    public void actionPerformed( ActionEvent e )
    {
        if( !onGround )
        {
            ...
        }
    }
}

For clarity I should explain that this means you don't actually need a while loop. The Timer does the sleeping part for you, effectively.

Also, when I've used the Timer class I've had the ActionListener class (my implementation) be an inner class, so it shares instance variables.

plainOldNerd
  • 305
  • 2
  • 8
1

Here is an example of a SwingWorker

I suggest using this if you would like to have a multi-threaded Swing application that needs to update a component. It does it safely on the EDT so your application doesn't freeze up.

SwingWorker<Void, Integer> updater = new SwingWorker<Void, Integer>()
    {
        @Override
        protected Void doInBackground() throws Exception
        {
            boolean something = false;
            int someInt = 3;

            while(!something)
            {
                publish(someInt++); 
                //publish() adds someInt to the chunks list 
                //in the process method so you can access it later.

                Thread.sleep(1000);

                if(someInt == 10)
                {
                    something = true;
                }
            }
            return null;
        }

        @Override
        protected void process(java.util.List<Integer> chunks)
        {
            for(int num : chunks)
            {
                label.setText(String.valueOf(num));
            }
            //This gets each value you added to the chunks list
            //So you can update the label with each value
        }

        @Override
        protected void done()
        {
            //Leave blank or add something to do when the process is finished
        }
    };
    updater.execute();
River
  • 8,585
  • 14
  • 54
  • 67
Jonah
  • 1,013
  • 15
  • 25