2015-01-29 6 views
-1

Мне нужна одноразовая пауза в этой программе для того, что я пытаюсь сделать. Я показываю некоторый текст в Java Swing JFrame, перерисовывает его, я жду 1,5 секунды, затем меняю текст.Не могу понять Java Swing Timers. Как сделать 1 временную задержку?

В принципе, я начал с этим:

statusLabel.setText(s);  
appFrame.repaint(); 
Thread.sleep(1500); 
statusLabel.setText(y); 
appFrame.repaint(); 

Но это не работает. Thread.sleep() будет ссылаться до того, как перекраска закончится, что означает, что s никогда не будет отображаться. Я читал много мест, в которых вы не должны использовать Thread.sleep() в приложениях swing, потому что он приостанавливает все потоки, даже потоки, пытающиеся перерисовать, и чтобы приостановить что-то, вызванное , вам нужно использовать Java Swing Timer.

Что все хорошо и хорошо, за исключением того, что я не могу найти ни одного места, которое предлагает достойное объяснение того, как они работают. Поскольку, насколько я могу судить, таймеры специально используются для повторения событий по таймеру. Я просто хочу 1,5-секундную задержку между двумя рецензиями.

Я попытался сделать это ...

statusLabel.setText(s);  
appFrame.repaint(); 

Timer timer = new Timer(1500, new ActionListener() 
{ 
    public void actionPerformed(ActionEvent ae) 
    { 

    } 
}); 

timer.setInitialDelay(1500); 
timer.setRepeats(false); 
timer.start(); 

statusLabel.setText(y); 
appFrame.repaint(); 

... добавить таймер с 1,5 сек начальной задержки, не повторяющимся, и не тела к его событию actionPerformed, так что буквально ничего не делает, но ждать что 1,5 с, но это не сработало.

+0

Возможный дубликат [Использование SwingWorker и Timer для отображения времени на ярлыке?] (Http://stackoverflow.com/questions/9855037/using-swingworker-and-timer-to-display-time-on-a- label) – GSerg

ответ

1

Вы пытались разместить statusLabel.setText(y); внутри метода actionPerformed вашего ActionListener?

statusLabel.setText(s);  

Timer timer = new Timer(1500, new ActionListener() 
{ 
    public void actionPerformed(ActionEvent ae) 
    { 
     statusLabel.setText(y); 
    } 
}); 

timer.setRepeats(false); 
timer.start(); 

Если это все еще не работает, то рассмотреть возможность предоставления runnable example, который демонстрирует вашу проблему. Это приведет к уменьшению путаницы и лучше ответов

Обновленные

Что вы «кажется», чтобы желать сделать, это создать ряд событий, которые получают триггер в разное время ... Вместо того, используя отдельные Timer s, вы должны использовать один Timer как цикл, каждый раз, когда он тикает, вы проверить его состояние и принять некоторые решения о том, что должно быть сделано, например ...

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Flashy { 

    public static void main(String[] args) { 
     new Flashy(); 
    } 

    public Flashy() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public static class TestPane extends JPanel { 

     private JLabel flash; 
     private JButton makeFlash; 

     protected static final Color[] FLASH_COLORS = new Color[]{Color.BLUE, Color.RED, Color.GREEN, Color.YELLOW}; 
     protected static final int[] FLASH_DELAY = new int[]{1000, 2000, 3000, 4000}; 
     private int flashPoint; 

     public TestPane() { 
      setLayout(new GridBagLayout()); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridwidth = GridBagConstraints.REMAINDER; 

      flash = new JLabel("Flash"); 
      flash.setOpaque(true); 
      makeFlash = new JButton("Make Flash"); 

      add(flash, gbc); 
      add(makeFlash, gbc); 

      makeFlash.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        flashPoint = -1; 
        Timer timer = new Timer(0, new ActionListener() { 
         @Override 
         public void actionPerformed(ActionEvent e) { 
          Timer timer = ((Timer)e.getSource()); 
          flashPoint++; 
          if (flashPoint < FLASH_COLORS.length) { 
           flash.setBackground(FLASH_COLORS[flashPoint]); 
           System.out.println(FLASH_DELAY[flashPoint]); 
           timer.setDelay(FLASH_DELAY[flashPoint]); 
          } else { 
           flash.setBackground(null); 
           timer.stop(); 
           makeFlash.setEnabled(true); 
          } 
         } 
        }); 
        timer.setInitialDelay(0); 
        timer.start();     
        makeFlash.setEnabled(false); 
       } 
      }); 

     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

    } 

} 

Теперь, если вы хотел сделать что-то действительно фантастическое, вы могли бы разработать серию o f ключевых кадров за определенный период времени.

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

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.text.NumberFormat; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Flashy { 

    public static void main(String[] args) { 
     new Flashy(); 
    } 

    public Flashy() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public static class TestPane extends JPanel { 

     private JLabel flash; 
     private JButton makeFlash; 

     protected static final Color[] FLASH_COLORS = new Color[]{Color.BLUE, Color.RED, Color.GREEN, Color.YELLOW}; 
     protected static final double[] FLASH_DELAY = new double[]{0, 0.2, 0.4, 0.6}; 

     public TestPane() { 
      setLayout(new GridBagLayout()); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridwidth = GridBagConstraints.REMAINDER; 

      flash = new JLabel("Flash"); 
      flash.setOpaque(true); 
      makeFlash = new JButton("Make Flash"); 

      add(flash, gbc); 
      add(makeFlash, gbc); 

      makeFlash.addActionListener(new ActionListener() { 
       private int playTime = 10000; 
       private long startTime; 
       private int currentFrame = -1; 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        startTime = System.currentTimeMillis(); 

        Timer timer = new Timer(50, new ActionListener() { 
         @Override 
         public void actionPerformed(ActionEvent e) { 
          Timer timer = ((Timer) e.getSource()); 
          long now = System.currentTimeMillis(); 
          long duration = now - startTime; 

          double progress = (double) duration/(double) playTime; 
          int keyFrame = 0; 
          for (keyFrame = 0; keyFrame < FLASH_DELAY.length; keyFrame++) { 

           double current = FLASH_DELAY[keyFrame]; 
           double next = 1d; 
           if (keyFrame + 1 < FLASH_DELAY.length) { 
            next = FLASH_DELAY[keyFrame + 1]; 
           } 

           if (progress >= current && progress < next) { 
            break; 
           } 

          } 

          if (keyFrame < FLASH_COLORS.length) { 

           flash.setBackground(FLASH_COLORS[keyFrame]); 

          } 

          if (duration >= playTime) { 
           timer.stop(); 
           makeFlash.setEnabled(true); 
           flash.setBackground(null); 
          } 

         } 
        }); 
        timer.setInitialDelay(0); 
        timer.start(); 
        makeFlash.setEnabled(false); 
       } 
      }); 

     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

    } 

} 

гораздо более продвинутая концепция, которая демонстрируется в this answer

+0

Хотя это работает для этого конкретного примера, это не работает для других, которые я пытаюсь сделать. Например, другой задает текст 3 раза, с задержкой 1 с между 1-й и 2-й и 0,5-секундной задержкой после 2-го и 3-го. Из моих экспериментов и из того, что сказал Атсби, он будет стоять в очереди на таймеры практически одновременно, а 0,5 секунды уйдут первым, а 1 сек. И хотя я мог бы просто поставить 1,5 секунды на второй, чтобы он ушел вовремя, я не пытаюсь научиться жесткому коду, я пытаюсь научиться правильно переводить поток в качели. – CSDragon

+0

* «Например, еще один устанавливает текст 3 раза, с задержкой 1 с между 1-м и 2-м». * Используйте счетчик в «Таймер», чтобы отслеживать, где вы находитесь. * «Мое экспериментирование и из того, что сказал Атсби, он будет стоять в очереди таймеров практически одновременно» * - Затем используйте один «Таймер» и закодируйте логику внутри, чтобы предоставить необходимые вам изменения в зависимости от количества раз 'Timer' был вызван – MadProgrammer

+1

*« Я пытаюсь научиться правильно спать поток в свинге »* - Простой ответ на этот вопрос: do not – MadProgrammer

3

Как указано в вашем примере, похоже, что таймер «работает», он просто ничего не делает, потому что метод actionPerformed пуст. Возможно, вы думаете, что timer.start() блокирует и ждет, пока таймер запустится, но он сразу же вернется. Работа таймеров заключается в том, что метод таймера actionPerformed будет вызываться из потока пользовательского интерфейса, когда он должен быть. Размещение кода внутри метода actionPerformed таймера - это хороший способ периодически обновлять состояние пользовательского интерфейса.

+0

Итак, если он не блокирует и не ждет для запуска таймера, как мне это сделать? – CSDragon

+1

Как правило, вы не должны. Вы можете сделать это, используя синхронизацию, например, с помощью атомной переменной, которую вы обновляете из метода 'actionPerformed'. Но тогда он будет иметь такое же поведение, как «Thread.sleep». Это нехорошие решения. Правильный способ сделать это - это реорганизовать ваш код, чтобы на самом деле использовать обратный вызов таймера, чтобы делать все, что нужно, и ждать ожидания от другого потока. – Atsby

+1

Ну, это ... смущает. – CSDragon