Как сделать паузу в цикле java for на 1/2 секунды между каждой итерацией?

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

// это цикл. Метод changeGrid отображает игровую сетку в графическом // интерфейсе, но на экране видна только 25-я итерация. Я хотел бы, чтобы каждый // был виден примерно за полсекунды до продолжения цикла. // Я видел здесь ответы на некоторые вопросы, которые очень близки к тому, что я задаю, // но я просто не очень понимаю, как применить это к моей программе.. // спасибо за любую помощь.


person Bryan    schedule 29.05.2011    source источник


Ответы (3)


Если код, выполняемый симуляцией, быстрый и не потребляет слишком много ресурсов ЦП и времени, рассмотрите возможность использования таймера Swing для создания циклов и задержки. В противном случае вам нужно будет использовать фоновый поток, например, с объектом SwingWorker.

Например, при использовании Swing Timer и 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
      }
   }
person Hovercraft Full Of Eels    schedule 29.05.2011
comment
@hovercraft, хм, ты прав ... даже не подумал об этом +1 - person hvgotcodes; 29.05.2011
comment
@Hovercraft Full Of Eels больше ничего не согласовывал с этим, чтобы избежать Thread.sleep(int внутри ActionListener) +1, uuuupssss, где эти два сообщения потерялись .... :-) - person mKorbel; 29.05.2011
comment
вау, какие вы быстрые! Я новичок в java, так что извините за мое невежество. Но не могли бы вы дать мне немного больше деталей или ссылку, где я могу прочитать об использовании этого? спасибо! - person Bryan; 29.05.2011
comment
@Bryan: Учебники Swing - это то, к чему вам нужно идти. Ознакомьтесь с разделами Как использовать таймеры Swing и Параллелизм в Swing - person Hovercraft Full Of Eels; 29.05.2011
comment
не может найти символ в строке с SwingwWorker(). что мне нужно для этого импортировать? - person Bryan; 29.05.2011
comment
@Bryan, я предполагаю, что changeGrid() - это просто какой-то метод игровой логики, но @Hovercraft Full Of Eel предположил, что это метод, выводящий что-то на экран (улучшите, он поместил его в done(), чтобы поток диспетчеризации событий Swing выполнял его) . Если changeGrid() действительно является игровым методом, приведенный выше код можно упростить, но вам все равно понадобится SwingWorker. - person toto2; 29.05.2011
comment
@ Брайан, SwingWorker является классом-членом пакета javax.swing. Он у вас есть независимо от того, какую версию Java вы используете. - person toto2; 29.05.2011
comment
@toto я импортировал javax.swing.*; все еще получение не может найти символ. changeGrid() на самом деле просто меняет цвет кнопок в моем графическом интерфейсе. Я думаю, что я выше головы. хаха. Возможно, придется отнести это моему учителю. спасибо всем за то, что вы были так полезны. - person Bryan; 29.05.2011
comment
@ Брайан, хорошо, так что Hover прав, changeGrid должен выполняться в потоке событий Swing с done. Swing раздражает... вам нужно понимать работу с потоками, чтобы использовать его. - person toto2; 29.05.2011
comment
@Brian Вы можете использовать более простое решение от @ratchet freak, если ваш runSimulationOneGen выполняется быстро. С его решением ваш метод будет выполняться в основном потоке Swing. Если runSimulationOneGen выполняется слишком долго, все ваше приложение зависнет на пользователе во время его выполнения. Но, может быть, это не является большой проблемой для вас прямо сейчас. - person toto2; 29.05.2011
comment
@ Брайан о том, что не получил символ: ты правильно написал? в одном из ваших постов вы написали это SwingwWorker(). По-видимому, SwingWorker существует только с java 6 (в 2006 году). - person toto2; 29.05.2011

НИКОГДА НЕ БЛОКИРУЙТЕ ПОТОК СОБЫТИЙ GUI

вы можете использовать для этого таймер, и он сработает только 25 раз

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();

Кстати, причина, по которой показана только последняя итерация, заключается в том, что обновления графического интерфейса (перерисовки) выполняются в отдельном событии, но чтобы запустить другое событие, вам нужно вернуться из метода прослушивателя, который вы не сделали

Таймер, который я показал, представляет собой более сложную итерацию, которая позволяет запускать другие события между итерациями, позволяя графическому интерфейсу отображать изменения.

person ratchet freak    schedule 29.05.2011
comment
Спасибо, мне легче следовать этому, чем судну на воздушной подушке. но я получаю сообщение об ошибке «идентификатор», ожидаемое при вызове таймера t. - person Bryan; 29.05.2011
comment
Я отредактировал код, чтобы он компилировался на моей машине (это проблема с кодом, написанным непосредственно в SO;)) - person ratchet freak; 29.05.2011
comment
Урод @ratchet все еще не работает для меня. Я не знаю почему. это похоже на то, что компилятор не распознает t как таймер и хочет, чтобы я повторно объявлял его в каждом случае. Спасибо за помощь. - person Bryan; 29.05.2011
comment
@ Брайан, осторожно с java.util.Timer против javax.swing.Timer. - person toto2; 29.05.2011
comment
@toto runSimulationOneGen() выполняется быстро, я пытаюсь заставить это работать. я не понимаю ваш последний комментарий, быть осторожным с чем? во всяком случае, это просто не работает для меня, и я не понимаю, почему бы и нет. Спасибо за ваш вклад. - person Bryan; 29.05.2011
comment
@Brian Если это быстро, то это решение лучше. Если у вас есть import java.util.* и import javax.swing.*, вы получите сообщение об ошибке, если вы используете Timer где-то в своем коде. Я не уверен, какое именно сообщение. Чтобы быть в безопасности, вы можете ввести final javax.swing.Timer t = new javax.swing.Timer(500, null);. В противном случае, какое сообщение об ошибке вы получите? - person toto2; 29.05.2011
comment
@toto то, что сделал и код в его вопросе (без задержки в 0,5 секунды, которую он хотел) - person ratchet freak; 29.05.2011
comment
@toto это именно то, что я хочу. запустите один раз, подождите 0,5 секунды, затем снова запустите в общей сложности 25 раз. это таймер java.util.Timer или javax.swing.Timer? Ошибка, которую я получаю, является ожидаемой ‹идентификатором›. В приведенном выше коде это будут строки 2, 11 и 12. - person Bryan; 29.05.2011
comment
(Я удалил свой глупый комментарий...) урод с храповиком использует Swing Timer. Утилита Timer не имеет ничего общего с actionPerformed и ActionEvent. - person toto2; 29.05.2011
comment
@bryan, чтобы подтвердить, что это таймер свинга (import java.swing.Timer;, чтобы избежать конфликтов) - person ratchet freak; 29.05.2011
comment
Снова используйте таймер Swing. Для увеличения этот импорт должен быть javax.swing.Timer. но если есть сомнения, вообще не импортируйте, а используйте полные имена классов при их использовании. - person Hovercraft Full Of Eels; 29.05.2011
comment
У меня все получилось, большое спасибо всем вам, ребята! Это великолепный сайт. Все так полезно. Я очень ценю это. И спасибо за терпение к новому парню. - person Bryan; 29.05.2011
comment
@toto Я скомпилировал его в eclipse, NetBeans мне просто не подходит - person ratchet freak; 29.05.2011

проверьте мой пост, в котором показаны оба метода java.swing.Timer #setDelay(int)

и

правильное использование Thread.sleep (целое число)

проблема с отображением курсора ожидания Java

person mKorbel    schedule 29.05.2011