java - 将事件分派(dispatch)线程置于搁置状态,直到 Swing 计时器停止

标签 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();
    }
}

“轮到你了”打印得太快。如果有帮助的话,计时器的重点是让程序触发音频音符,更新钢琴图形,以便您可以看到按下的音符,加载将要演奏的下一个音符,然后重复直到序列完成。

最佳答案

使用观察者模式的变体来通知定时器何时完成。例如,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();
         }
      });
   }
}

关于java - 将事件分派(dispatch)线程置于搁置状态,直到 Swing 计时器停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24715579/

相关文章:

java - 将来自不同 Activity 的值添加到 ArrayList

java - 如何在抽象方法中给出不同的参数?

java - 从静态工厂方法创建工厂,然后在该 id 上调用静态工厂方法

Java:多线程字符流解码

javax swing html 解析器不拾取 img 标签

java - 使用 for 循环添加一个字符串数组和另一个字符串数组

c++ - 条件变量的谓词

Java 同步方法

java - 对话框在没有应用程序的情况下可见。在替代选项卡上

java - 组件未显示在 JFrame 中