簡體   English   中英

JavaFX線程凍結GUI

[英]JavaFX Thread Freezing GUI

我對線程技術還很陌生,而且我是第一次使用javaFX,所以這可能是雙重打擊! 我認為,我的主要問題是線程。 我想在“跳過”按鈕上淡入淡出兩個Mediaplayer音頻。 因此,我相信我創建了一個線程來淡化音頻兩秒鍾,然后結束線程。 這就是我“想”我正在做的事情。 但是,程序運行時,通常在第二次跳過后凍結。 我為javaFX使用的大多數代碼來自教程,並且在嘗試進行淡入淡出之前按預期工作。 任何建議都將得到充分利用,TIA! CrossFade課程:

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 Application Thread外部更改UI的一部分。 我與MediaPlayers的合作不多,但我相信他們的游戲遵循相同的規則。

您可以通過使用Animation 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();
}
}

當然,如果您要使用Animation 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) { ... }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM