JavaFX 线程卡住 GUI

标签 java multithreading javafx

我对线程还很陌生,而且我是第一次使用 javaFX,所以这可能是双重打击!我相信我的主要问题是线程。我想在跳过按钮上交叉淡入淡出两个媒体播放器音频。因此,我相信我创建了一个线程来在两秒内交叉淡入淡出音频,然后我应该结束该线程。这就是我“认为”我正在做的事情。然而,当程序运行时,它通常会在第二次跳过后卡住。我用于 javaFX 的大部分代码都来自教程,并且在我尝试交叉淡入淡出之前按预期工作。任何建议都会很有用,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();
}

}

音频类:

import javafx.scene.media.MediaPlayer;
public class Audio{
public static void crossfade(MediaPlayer mp1, MediaPlayer mp2)
{
    Thread xFade = new Thread(new CrossFade(mp1,mp2));
    xFade.start();
}
}

跳过按钮的代码:

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

最佳答案

一般来说,您不应该从 FX 应用程序线程外部更改 UI 的任何部分。我没有太多使用 MediaPlayers,但我相信它们遵循相同的规则。

您可以通过使用动画 API 来简化这一过程。 PauseTransition 可用于管理每次暂停,并且您可以使用 SequentialTransition 按顺序“播放”这些暂停。这基本上将为您管理所有线程。类似的东西(这没有经过测试......)

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

当然,如果您要使用动画 API,那么您也可以以“顺利”完成所有操作的方式使用它,而不是离散步骤:

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

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

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

您还需要将 mp1 声明为 final:

public static void crossfade(final MediaPlayer mp1, final MediaPlayer mp2) { ... }

关于JavaFX 线程卡住 GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23069460/

相关文章:

java - 将 xml 转换为特定编程语言的设计模式

java - Solr CloudSolrClient : Caused by: java. lang.ClassCastException : java. lang.String 无法转换为 java.util.Map

multithreading - 有没有办法让 Rust 闭包只将一些变量移入其中?

event-handling - JavaFX:setOnMouseClicked() 和 addEventHandler() 方法之间的区别?

java - 为什么 .fxml 文件无法在场景生成器中打开?

java - 该算法不会在 O(m log n) 中运行吗?

java - hibernate 列表

java - 没有堆栈跟踪的线程异常

c++ - 跨线程的 sigslot 信号

javafx - 从JavaFx访问网络摄像头