2013-06-23 34 views
0

我想在自定义MIDI播放器上实现重复功能,但我无法实现重复功能。以下是我正在使用的课程:向简单的MIDI播放器添加重复功能

NotePlayer - 使用Java的MIDI包播放MIDI音符。

GuitarTunerGUI

  • 接口到NotePlayer类。
  • 为每个吉他字符串提供六个JButtons,用于选择所需调谐的JComboBox以及用于切换重复功能的JCheckBox。
  • 提供toggleRepeat()用于切换repeatEnabled字段,该字段是GuitarTunerGUI类的私有字段。

我创建了一个SwingWorker,负责在单独的线程中播放MIDI音符。这解决了在笔记播放时保持GUI响应的问题。 但是,启用重复并且用户按下多个按钮时会出现问题。

当用户按下六个Jbutton将之一听者执行以下操作:

public void actionPerformed(ActionEvent event) { 
    // The note param is a private field of the listener object 
    MusicianWorker clapton = new MusicianWorker(note); 
    clapton.execute(); 
} 

的执行方法执行以下操作:

protected Void doInBackground() throws Exception { 
    do { 
     NotePlayer.playNote(thisNote); 
     try { 
      Thread.sleep(3000); 
     } catch (InterruptedException ex) { 
      System.out.println(ex.getMessage()); 
     } 
    } while (repeatEnabled); 

    return null; 
} 

当用户按压多个按钮没有问题出现切换重复。例如,当顺序按下'A'按钮和'E'按钮时,创建两个线程,并且'A'和'E'音符是两个都重复播放,直到repeatEnabled被切换为止。当用户按下一个JButton时,我需要首先确定是否有任何工作线程正在执行,如果这样,在播放指定音符之前杀掉这些线程。预先感谢您的时间和反馈。

+0

类似的问题被检查[这里](http://stackoverflow.com/q/17226579/230513Z)。 – trashgod

回答

0

您需要保持工人之间的共享状态。引入新的布尔变量“玩”。在执行前检查播放标志是否设置为true,执行后再次设置为false。

0

你给出的代码很棒,只需要稍微调整就可以了。当你创建你的SwingWorker时,你应该在一个实例变量中跟踪它(如果你打算在某个时候想要播放多个音符,那么可以在List中)。然后,在播放新音符前,检查最后一个音符是否完成,如果没有,则取消它。

取消是否对您的MusicianWorker有影响取决于您。工作线程将被中断,这意味着如果您的Thread.sleep方法在运行时会过早终止 - 您必须检查文档以查看它对NotePlayer的影响。

最后,似乎根本不需要使用SwingWorker,因为您的后台任务不与UI进行交互。您可能需要调查Executors

你可以尝试这样的事:

public class AlbertHall { 
    private final ExecutorService es = Executors.newSingleThreadExecutor(); 
    // No longer a local variable in the listener 
    private Future<Void> clapton; // ... or maybe a Collection of Futures 

    private class Listener implements ActionListener { 
    private final Note note; 

    public Listener(Note note) { 
     this.note = note; 
    } 

    public void actionPerformed(ActionEvent event) { 
     // Watch out, Clapton may finish after you have asked if he is done 
     // but before you call cancel 
     if (clapton != null && !clapton.isDone()) clapton.cancel(true); 

     // You may need to have a wait loop here if Clapton takes a while 
     // to leave the stage 

     // Next note 
     clapton = es.submit(new MusicianWorker(note)); 
    } 
    } 

    static class MusicianWorker implements Runnable { 
    private final Note note; 

    public MusicianWorker(Note note) { 
     this.note = note; 
    } 

    public void run() { 
     boolean cancelRequested = false; 
     do { 
     NotePlayer.playNote(thisNote); 
     try { 
      Thread.sleep(3000); 
     } catch (InterruptedException ex) { 
      // Looks like we got cancelled 
      cancelRequested = true; 
     } 
     } while (repeatEnabled && !cancelRequested); 
    } 
    } 
} 
+0

非常感谢您的反馈,并很抱歉没有及时回复。我有一段时间没有机会看看我的吉他调音器代码。我会尝试你的建议,并让你知道结果如何。 – Denton