Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java swing应用程序中线程化音频的设计模式:如何通知midi执行器关闭以驱动GUI状态更改?_Java_Multithreading_Swing_Swingworker_Javasound - Fatal编程技术网

Java swing应用程序中线程化音频的设计模式:如何通知midi执行器关闭以驱动GUI状态更改?

Java swing应用程序中线程化音频的设计模式:如何通知midi执行器关闭以驱动GUI状态更改?,java,multithreading,swing,swingworker,javasound,Java,Multithreading,Swing,Swingworker,Javasound,我的应用程序正在显示各种GUI状态更改,并根据Midi文件成功完成播放的情况启用用户输入。在while循环中等待的最佳方式是更改GUI状态、在ExecutorService上播放midi、更新模型并等待midi文件完成播放,然后再重复播放整个while?目前,我的代码如下所示: public void startTraining() { int i = 0; while( i != Model.getTestIteration() + 1) { //create

我的应用程序正在显示各种GUI状态更改,并根据Midi文件成功完成播放的情况启用用户输入。在
while
循环中等待的最佳方式是更改GUI状态、在
ExecutorService
上播放midi、更新模型并等待midi文件完成播放,然后再重复播放整个while?目前,我的代码如下所示:

public void startTraining() {
    int i = 0;
    while( i != Model.getTestIteration() + 1) {

        //create GUI state changes and schedule on EDT
        myButton.setButtonSelected( true);
        Timer t = new Timer( DELAY_TIME, new ActionListener() {
            public void actionPerformed( ActionEvent avt) {
                 myButton.setButtonSelected( false);
                                 }
                });)
        t.setRepeats( false);
        t.start();

        //MidiplaybackController uses ScheduluedExecutorService
        //to start and stop playback with its own ScheduluedFuture<?> for stopping
        //at a fixed interval
        _midiPlaybackController.playQueue( (int)aCue));

        //TODO: pause somehow relative to midiplayback finishing

        Model.updateTestIteration();
        myButton.setSelected( true);
        i++;
    }
}
public void startTraining(){
int i=0;
而(i!=Model.getTesteration()+1){
//在EDT上创建GUI状态更改和计划
myButton.setButtonSelected(true);
计时器t=新计时器(延迟时间,新ActionListener(){
已执行的公共无效操作(ActionEvent avt){
myButton.setButtonSelected(false);
}
});)
t、 设置重复(假);
t、 start();
//MidiplaybackController使用ScheduluedExecutorService
//使用自己的计划开始和停止播放,并在将来停止播放
//以固定的间隔
_playQueue((int)aCue));
//TODO:相对于MIDI播放结束暂停
Model.updateSettings();
myButton.setSelected(true);
i++;
}
}
这里最好的款式是什么。我希望状态变化发生在EDT上,MIDITuff在它自己的线程上进行调度,然后等待midi带来另一个系列或GUI状态变化。我是否应该创建一个
SwingWorker
,然后在
SwingWorker
中运行Midiplayback
ExecutorServices
?或者,我应该在Todo处创建一个类似于倒计时闩锁的东西,等待midi执行器关闭和计时器t完成吗


附带问题:同时设置图标和选定图标,然后在setSelected(布尔b)调用之间切换以反映按钮的状态,这是否有问题?

我不确定您是否真的需要GUI中的while循环。您可以将GUI设置为接收消息吗?例如,当MIDI文件结束时,如果这是重要信息,请让MIDI文件上的侦听器向GUI面板发送所需的任何消息,可能还包括更新或重新绘制()

对于SourceDataLine播放,有一个LineListener可以在播放结束时激活。我很确定MIDI播放也有类似的功能

[编辑:在本教程中,有一节“指定特殊事件侦听器”可能会有所帮助。]

如果我确实想暂停线程,我的第一个选择是thread.sleep()。如果您需要比您所选择的时间更早地退出,可以向sleep命令发送一个中断。sleep命令的准确性受到系统时钟中断的限制,在某些Microsoft操作系统上,该命令最多可关闭15秒——这是唯一的缺点。从计时器设置“唤醒呼叫”具有相同的计时精度限制

如果您投入活动来消磨时间,那么您可能会不必要地消耗cpu周期,从而可能会减慢程序的其余部分


我不能说我完全理解你的设置从我试图阅读你的问题,我希望这至少是有点帮助

我不确定您是否真的需要GUI中的while循环。您可以将GUI设置为接收消息吗?例如,当MIDI文件结束时,如果这是重要信息,请让MIDI文件上的侦听器向GUI面板发送所需的任何消息,可能还包括更新或重新绘制()

对于SourceDataLine播放,有一个LineListener可以在播放结束时激活。我很确定MIDI播放也有类似的功能

[编辑:在本教程中,有一节“指定特殊事件侦听器”可能会有所帮助。]

如果我确实想暂停线程,我的第一个选择是thread.sleep()。如果您需要比您所选择的时间更早地退出,可以向sleep命令发送一个中断。sleep命令的准确性受到系统时钟中断的限制,在某些Microsoft操作系统上,该命令最多可关闭15秒——这是唯一的缺点。从计时器设置“唤醒呼叫”具有相同的计时精度限制

如果您投入活动来消磨时间,那么您可能会不必要地消耗cpu周期,从而可能会减慢程序的其余部分


我不能说我完全理解你的设置从我试图阅读你的问题,我希望这至少是有点帮助

我想你可以接受这样的事情:

_midiPlaybackController.playQueue((int)aCue, new MyMidiPlaybackListener());
其中,
MyMidiPlaybackListener
是您自己创建的一个类,看起来像这样

public class MyMidiPlaybackListener implements MidiPlaybackListener
{
    public void onPlaybackComplete()
    {
        // Since onPlaybackComplete is likely called by a worker thread
        // And we don't want to update the GUI from a worker thread
        // (because that would violate Swing's threading policy)
        // we update the GUI via a SwingUtilities.invokeLater Runnable
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                myButton.setSelected(true);
            }
        });
    }
}
该类实现了MidiPlaybackListener接口,该接口也是您自己创建的:

public interface MidiPlaybackListener 
{
    public void onPlaybackComplete();
}

修改
MidiPlaybackController
playQueue
方法以支持接受侦听器参数(如图所示)
MidiPlaybackController
也必须进行修改,以存储侦听器并在适当的时间调用它(可能是在播放结束时)。

我认为您可能会接受类似的操作:

_midiPlaybackController.playQueue((int)aCue, new MyMidiPlaybackListener());
其中,
MyMidiPlaybackListener
是您自己创建的一个类,看起来像这样

public class MyMidiPlaybackListener implements MidiPlaybackListener
{
    public void onPlaybackComplete()
    {
        // Since onPlaybackComplete is likely called by a worker thread
        // And we don't want to update the GUI from a worker thread
        // (because that would violate Swing's threading policy)
        // we update the GUI via a SwingUtilities.invokeLater Runnable
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                myButton.setSelected(true);
            }
        });
    }
}
该类实现了MidiPlaybackListener接口,该接口也是您自己创建的:

public interface MidiPlaybackListener 
{
    public void onPlaybackComplete();
}
修改
MidiPlaybackController
playQueue
方法以支持接受侦听器参数(如图所示)
MidiPlaybackController
还必须修改以存储侦听器并在适当的时间调用它(可能是播放结束)。

如果我在TODO处插入一个“while”循环,看起来像while(!\MidiPlaybackController.I