将事件派发线程置于保持状态,直到Swing计时器停止

时间:2014-07-12 17:32:52

标签: java multithreading swing timer

我创建了一个在钢琴上播放一系列音符的程序,然后确定用户在钢琴上的点击是否与刚播放的内容相匹配。我让程序使用Swing计时器自动播放一系列音符,但我需要等到序列完成播放才能继续播放。这是我现在所拥有的简化示例:

import java.awt.event.*;
import javax.swing.*;

public class myProgram {

    Timer timer = new Timer(1000, new AutoPlay());

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                myProgram myProgram = new myProgram();
                System.out.println("Computer plays notes.");
                myProgram.compTurn();
                System.out.println("Your turn.");
            }
        });   
    }

    class AutoPlay implements ActionListener {

        int i = 0;

        public void actionPerformed(ActionEvent e) {
            System.out.println("Auto-played note.");
            i++;
            if (i == 2) timer.stop();
        }
    }

    // TODO - Play a melody for the user to repeat
    public void compTurn() {
        timer.start();
    }
}

"轮到你"打印太快了。如果它有帮助,计时器的目的是让程序触发音频笔记,更新钢琴图形,这样你就可以看到按下的音符,加载下一个要播放的音符,然后重复直到序列完成。

2 个答案:

答案 0 :(得分:1)

使用观察者模式的变体来通知计时器何时完成。例如,PropertyChangeListener可以很好地工作。例如......

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;

public class MyProg2 extends JPanel {
   public static final String TIMER_COMPLETE = "timer complete";
   private static final int TIMER_DELAY = 1000;
   private Timer timer;
   public MyProg2() {
      // TODO create GUI
   }

   public void playNotes() {
      if (timer != null && timer.isRunning()) {
         return;
      }
      timer = new Timer(TIMER_DELAY, new TimerListener());
      timer.start();
   }

   private class TimerListener implements ActionListener {
      private int i = 0;

      @Override
      public void actionPerformed(ActionEvent e) {
         System.out.println("Auto-played note.");
         i++;
         if (i == 2) {
            timer.stop();
            firePropertyChange(TIMER_COMPLETE, false, true);
         }
      }
   }

   private static void createAndShowGui() {
      System.out.println("Starting program");
      MyProg2 mainPanel = new MyProg2();
      mainPanel.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent pcEvt) {
            if (MyProg2.TIMER_COMPLETE.equals(pcEvt.getPropertyName()) && pcEvt.getNewValue() == Boolean.TRUE) {
               System.out.println("Your turn");
            }
         }
      });
      mainPanel.playNotes();

      JFrame frame = new JFrame("MyProg2");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

答案 1 :(得分:1)

计算机开始播放时禁用用户输入选项。当用户转向时启用它们。永远不要禁用edt。