JavaFX线程冻结GUI

JavaFX线程冻结GUI,java,multithreading,javafx,Java,Multithreading,Javafx,我对线程还是相当陌生的,我第一次使用javaFX,所以这可能是一个双重打击!我认为我的主要问题是线程。我想在跳过按钮上交叉淡入两个mediaplayer音频。因此,我相信我创建了一个线程,在两秒钟内交叉淡入音频,然后我应该结束该线程。这就是我“认为”我在做的。但是,当程序运行时,它通常在第二次跳过后冻结。我在javaFX中使用的大部分代码都来自教程,在我尝试crossfade之前,它们都能正常工作。TIA,任何建议都会很有用的! 交叉褪色等级: import javafx.scene.media

我对线程还是相当陌生的,我第一次使用javaFX,所以这可能是一个双重打击!我认为我的主要问题是线程。我想在跳过按钮上交叉淡入两个mediaplayer音频。因此,我相信我创建了一个线程,在两秒钟内交叉淡入音频,然后我应该结束该线程。这就是我“认为”我在做的。但是,当程序运行时,它通常在第二次跳过后冻结。我在javaFX中使用的大部分代码都来自教程,在我尝试crossfade之前,它们都能正常工作。TIA,任何建议都会很有用的! 交叉褪色等级:

import javafx.scene.media.MediaPlayer;
public class CrossFade extends Thread
{
private MediaPlayer mp1;
private MediaPlayer mp2;
private double currentVol;

public CrossFade(MediaPlayer mp1, MediaPlayer mp2)
{
    this.mp1 = mp1;
    this.mp2 = mp2;
    currentVol = mp1.getVolume();
    System.out.println("Vol: " + currentVol);
}

@Override
public void run() {

    mp2.setVolume(0);
    mp2.play();

    //20 increments in volume, every 100ms
    for (int i = 0; i < 20; i ++)
    {
           mp1.setVolume(mp1.getVolume()-currentVol/20);
           mp2.setVolume(mp2.getVolume()+currentVol/20);

           try
           {
               //sleep 100 ms
               Thread.sleep(100);
           }
           catch (InterruptedException e)
           {
               System.out.println("Unable to sleep on xFade");
               e.printStackTrace();
           }
    }
    mp1.stop();
    //this.interrupt();
}

}
跳过按钮的代码:

skip.setOnAction(new EventHandler<ActionEvent>() {
  @Override public void handle(ActionEvent actionEvent) {
    final MediaPlayer curPlayer = mediaView.getMediaPlayer();
    MediaPlayer nextPlayer = players.get((players.indexOf(curPlayer) + 1) % players.size());
    mediaView.setMediaPlayer(nextPlayer);
    curPlayer.currentTimeProperty().removeListener(progressChangeListener);

    //calls the crossfade in audio class (supposed to start that thread)
    Audio.crossfade(curPlayer,nextPlayer);
    //these were the "old" stop and play calls to the media
    //curPlayer.stop();
    //nextPlayer.play();
  }
});
skip.setOnAction(新的EventHandler(){
@重写公共无效句柄(ActionEvent ActionEvent){
final MediaPlayer curPlayer=mediaView.getMediaPlayer();
MediaPlayer nextPlayer=players.get((players.indexOf(curPlayer)+1)%players.size());
mediaView.setMediaPlayer(nextPlayer);
curPlayer.currentTimeProperty().RemovelListener(progressChangeListener);
//调用crossfade in音频类(应该启动该线程)
交叉淡入淡出(curPlayer,nextPlayer);
//这些都是对媒体的“老”叫停叫停
//curPlayer.stop();
//nextPlayer.play();
}
});

一般来说,您不应该从FX应用程序线程之外更改UI的任何部分。我与媒体玩家的合作不多,但我相信他们遵循同样的规则

通过使用动画API,您可能可以大大简化这一过程。
PauseTransfion
可用于管理每个暂停,您可以使用
SequentialTransition
按顺序“播放”这些暂停。这将基本上为您管理所有线程。类似(未经测试…)

更新:如果仍在使用JavaFX2.2,请将lambda表达式(
crossfade.setOnFinished(event->mp1.stop());
)替换为内部类:

crossfade.setOnFinished(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        mp1.stop();
    }
});

我将测试这个底部的代码,一旦我回到它明天,我感谢多种解决方案!p、 如果我有代表,我会投票!我对事件有问题,例如crossfade.setOnFinished(事件->mp1.stop());我如何让它接受mp1.stop()事件?您对它有什么问题?我需要在其他地方创建事件吗?我得到了“事件无法解析为变量”编辑:Java8,在Eclipse中使用e(fx)clipse。。。我在线程“JavaFX Application thread”java.lang中抛出:异常。错误:未解决的编译问题:事件无法解析为令牌“-”上的变量语法错误,应为@crossfade.setOnFinished(event->mp1.stop());
public class Audio{
public static void crossfade(MediaPlayer mp1, MediaPlayer mp2)
{
    double currentVol = mp1.getVolume();
    mp2.setVolume(0);
    mp2.play();
    SequentialTransition crossfade = new SequentialTransition();
    for (int i=0; i<20 i++) {
        PauseTransition pause = new PauseTransition(Duration.millis(100));
        pause.setOnFinished(event -> {
               mp1.setVolume(mp1.getVolume()-currentVol/20);
               mp2.setVolume(mp2.getVolume()+currentVol/20);
        });
        crossfade.getChildren().add(pause);
    }
    crossfade.setOnFinished(event -> mp1.stop());
    crossfade.play();
}
}
public class Audio {
public static void crossfade(MediaPlayer mp1, MediaPlayer mp2) {
    final double currentVolume = mp1.getVolume();
    mp2.setVolume(0);
    mp2.play();
    Timeline crossfade = new Timeline(new KeyFrame(Duration.seconds(2), 
            new KeyValue(mp1.volumeProperty(), 0), 
            new KeyValue(mp2.volumeProperty(), currentVolume)));
    crossfade.setOnFinished(event -> mp1.stop());
    crossfade.play();
}
}
crossfade.setOnFinished(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        mp1.stop();
    }
});
public static void crossfade(final MediaPlayer mp1, final MediaPlayer mp2) { ... }