0
private class MultipleGensListener implements ActionListener
   {
    public void actionPerformed(ActionEvent e)
        {
            for(int i = 0; i < 25; i++)
            {
                game.runSimulationOneGen();
                changeGrid();
            }
        }
   }

//this is the loop. The changeGrid method displays a game grid on a GUI but // only the 25th iteration is visible on screen. I would like each one to be // visible for about a half a second before the loop continues. // I have seen some questions answered on here that are very close to what I'm asking, // but I just don't really understand how to apply it to my program.. // thanks for any help.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Bryan
  • 9
  • 1
  • 2

3 Answers3

5

If the code performed by the simulation is quick and does not consume too much CPU and time, then consider using a Swing Timer to do your looping and delay. Otherwise, you'll need to use a background thread such as can be done with a SwingWorker object.

For e.g. if using both Swing Timer and SwingWorker:

   private class MultipleGensListener implements ActionListener {
      protected static final int MAX_INDEX = 25;

      public void actionPerformed(ActionEvent e) {
         int timerDelay = 500; // ms delay
         new Timer(timerDelay, new ActionListener() {
            int index = 0;

            public void actionPerformed(ActionEvent e) {
               if (index < MAX_INDEX) { // loop only MAX_INDEX times
                  index++;

                  // create the SwingWorker and execute it
                  new SwingWorker<Void, Void>() {
                     @Override
                     protected Void doInBackground() throws Exception {
                        game.runSimulationOneGen(); // this is done in background thread.
                        return null;
                     }

                     @Override
                     protected void done() {
                        changeGrid(); // this is called on EDT after background thread done.
                     }
                  }.execute(); // execute the SwingWorker
               } else {
                  ((Timer) e.getSource()).stop(); // stop the timer
               }
            }
         }).start(); // start the Swing timer
      }
   }
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • @hovercraft, hmm you are right...didn't even think of that +1 – hvgotcodes May 29 '11 at 14:14
  • 1
    @Hovercraft Full Of Eels nothing else only agreed with that, to avoid to Thread.sleep(int inside ActionListener) +1, uuuupssss where these two posts lost .... :-) – mKorbel May 29 '11 at 14:21
  • wow, you guys are quick! I'm new to java so sorry for my ignorance. But can you give me a little more detail or a link to where i can read up on using this? thank you! – Bryan May 29 '11 at 14:24
  • @Bryan: The Swing tutorials are where you need to go. Please check out: [How to use Swing Timers](http://download.oracle.com/javase/tutorial/uiswing/misc/timer.html) and [Concurrency in Swing](http://download.oracle.com/javase/tutorial/uiswing/concurrency/index.html) – Hovercraft Full Of Eels May 29 '11 at 14:26
  • cannot find symbol on line with SwingwWorker(). what do I need to import for this? – Bryan May 29 '11 at 14:31
  • @Bryan, my guess is that `changeGrid()` is just some game logic method, but @Hovercraft Full Of Eel assumed that it was a method printing something out to screen (enhance he put it in `done()`, so that the Swing event dispatching thread executes it). If `changeGrid()` is indeed just a game method, the above code can be simplified, but you still need a `SwingWorker`. – toto2 May 29 '11 at 14:51
  • @Brian, `SwingWorker` is a member class of package `javax.swing`. You have it no matter what version of Java you are using. – toto2 May 29 '11 at 14:54
  • @toto i've imported javax.swing.*; still getting cannot find symbol. changeGrid() really just changes the color of buttons on my GUI. I think i'm in over my head. haha. Might have to take this one to my teacher. thank you all for being so helpful. – Bryan May 29 '11 at 14:58
  • @Brian, OK so Hover is right, `changeGrid` must be executed in the Swing event thread with `done`. Swing is annoying... you do have to understand threading to use it. – toto2 May 29 '11 at 15:07
  • @Brian You can use the simpler solution from @ratchet freak if your `runSimulationOneGen` executes quickly. With his solution your method will be executed in the main Swing thread. If `runSimulationOneGen` takes too long to execute, your whole application will "freeze" on the user while it executes. But maybe it's not a big concern for you right now. – toto2 May 29 '11 at 15:12
  • @Brian about not getting symbol: did you spell it right? in one of your post you spelled it `SwingwWorker()`. Apparently `SwingWorker` only exists since java 6 (in 2006). – toto2 May 29 '11 at 15:17
3

NEVER BLOCK THE GUI EVENT THREAD

you can use a timer for that and have it only fire 25 times

final Timer t = new Timer(500,null);
t.addActionListener(new ActionListener(){
     int i=0;
     public void actionPerformed(ActionEvent e){
         game.runSimulationOneGen();//run 1 iteration per tick
         changeGrid();
         if(i>25){t.stop();}
         i++;
     }
});
t.setRepeats(true);
t.start();

btw the reason only the last iteration is shown is that gui updates (redraws) are done in a separate event, but to let another event trigger you need to return from the listener method which you didn't

the Timer I showed is a more elaborate iteration which lets other events run in between iterations allowing the gui to show the changes

ratchet freak
  • 47,288
  • 5
  • 68
  • 106
  • Thanks, this is easier for me to follow than hovercraft's. but i'm getting an error expected when the timer "t" is called. – Bryan May 29 '11 at 14:43
  • I've edited the code so it compiles on my machine (that's the problem with code written directly in SO ;) ) – ratchet freak May 29 '11 at 14:55
  • @ratchet freak still not working for me. I don't know why. it's like the compiler doesn't recognize t as a timer, and want's me to redeclare it in every instance. thanks for the help. – Bryan May 29 '11 at 15:16
  • @Brian careful with `java.util.Timer` versus `javax.swing.Timer`. – toto2 May 29 '11 at 15:18
  • @toto runSimulationOneGen() does execute quickly, im trying to make this work. i don't understand your last comment, be careful of what? anyhow, this just isn't working for me, and I don't understand why not. Thanks for your input. – Bryan May 29 '11 at 15:29
  • 1
    @Brian If it's quick then this solution is better. If you have `import java.util.*` and `import javax.swing.*`, you'll get some error message if you use `Timer` somewhere in your code. I'm not sure which message exactly. To be on the safe side, you can type `final javax.swing.Timer t = new javax.swing.Timer(500, null);`. Otherwise, what error message do you get? – toto2 May 29 '11 at 15:31
  • @toto that what the code in his question did too (sans the 0.5 second delay he wanted) – ratchet freak May 29 '11 at 15:40
  • @toto that is exactly what I want it to do. run once wait .5 secs then run again a total of 25 times. is this timer java.util.Timer or javax.swing.Timer? The error i'm getting is " expected". In the above code it would be at lines 2, 11 and 12. – Bryan May 29 '11 at 15:41
  • (I deleted my stupid comment...) ratchet freak uses a Swing `Timer`. The util `Timer` has nothing to do with `actionPerformed` and `ActionEvent`. – toto2 May 29 '11 at 15:45
  • @bryan to confirm it's a swing timer (`import java.swing.Timer;` to ensure no conflicts occur) – ratchet freak May 29 '11 at 15:48
  • Again use a **Swing** Timer. To ratchet, that import should be javax.swing.Timer. but if there's any doubt, don't import at all, but use fully qualified class names when using them. – Hovercraft Full Of Eels May 29 '11 at 15:49
  • I got it working, thanks so much to all you guys! this is a great site. Everyone is so helpful. I really appreciate it. And thanks for being patient with a new guy. – Bryan May 29 '11 at 15:52
  • @toto I compiled it in eclipse, NetBeans just doesn't suit me – ratchet freak May 29 '11 at 15:54
1

check my post that shows both methods java.swing.Timer#setDelay(int)

and

correct usage of Thread.sleep(int)

java wait cursor display problem

Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319