3

Volume を 0.0 に設定し、while ループでボリュームを少しずつ変更します。それでも、ボリュームは 0.0 から 1.0 に跳ね上がりますか? 音量をスムーズに変更するにはどうすればよいですか? 私は試した

public class EngineSound extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        mp3File = new File(metronom);
        media = new Media(mp3File.toURI().toURL().toString());
        mediaPlayer = new MediaPlayer(media);
        mediaView = new MediaView(mediaPlayer);
        mediaPlayer.play();
        mediaPlayer.setVolume(0.0);
        slider = new Slider();

        slider.valueProperty().addListener(new ChangeListener<Number>() {
            public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) {
                EventQueue.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        mediaPlayer.setVolume(slider.getValue());

                    }
                });
            }
        });

        double count = 1;
        while (count != 101) {
            for (int i = 0; i < 100000000; i++) {

            }
            slider.setValue(count / 100);
            count++;
            System.out.println(mediaPlayer.getVolume());
        }
    }
}
4

1 に答える 1

3

コードにはいくつか問題があります。

  • JavaFX コードは、Swing イベント ディスパッチ スレッドではなく、JavaFX アプリケーション スレッドで実行する必要があります。

EventQueue.invokeLaterを使用して Swing スレッドで実行する代わりに、 Platform.runLaterを使用して JavaFX スレッドで実行します。

  • Swing イベント ディスパッチ スレッドを使用する理由はまったくありません。

プログラムは JavaFX コントロールのみを使用するため、Swing スレッドでは何も実行しないでください。

  • 通常、ChangeListener.

使用EventQueue.invokeLaterは間違っていますが、この場合Platform.runLaterは JavaFX アプリケーション スレッドだけが Slider 値を変更する必要があるため、どちらも行う必要はありません。JavaFXノードのドキュメントで確認できるルールがあります。

アプリケーションは、ノードをシーンにアタッチし、すでにシーンにアタッチされているノードを JavaFX アプリケーション スレッドで変更する必要があります。

  • JavaFX アプリケーション スレッドで忙しく待機しないでください。

1 億までカウントするループは、アプリケーション スレッドをブロックするだけで、UI を更新するためにコントロールがフレームワークに返されることはないため、UI がフリーズします。

  • ループ内でスライダーの値を変更しないでください。

UI コントロールに値を設定したら、コントロールを JavaFX フレームワークに戻して、値の変更がコントロールとユーザーに反映されるようにする必要があります。

TimelineBindingを使用して上記の問題をすべて解決する次のコードを試してください。

import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.event.*;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.media.*;
import javafx.stage.Stage;
import javafx.util.Duration;

public class EngineSound extends Application {
  private static final String MEDIA_URL = 
    "http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv";

  private static final Duration FADE_DURATION = Duration.seconds(2.0);

  public static void main(String[] args) { launch(args); }

  @Override public void start(Stage stage) throws Exception {
    final MediaPlayer mediaPlayer = new MediaPlayer(
      new Media(
        MEDIA_URL
      )
    );
    final MediaView mediaView = new MediaView(mediaPlayer);

    HBox layout = new HBox(5);
    layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
    layout.getChildren().addAll(
      createVolumeControls(mediaPlayer), 
      mediaView
    );
    stage.setScene(new Scene(layout, 650, 230));
    stage.show();           

    mediaPlayer.play();
  }

  public Region createVolumeControls(final MediaPlayer mediaPlayer) {
    final Slider volumeSlider = new Slider(0, 1, 0);
    volumeSlider.setOrientation(Orientation.VERTICAL);

    mediaPlayer.volumeProperty().bindBidirectional(volumeSlider.valueProperty());

    final Timeline fadeInTimeline = new Timeline(
      new KeyFrame(
        FADE_DURATION,
        new KeyValue(mediaPlayer.volumeProperty(), 1.0)
      )
    );

    final Timeline fadeOutTimeline = new Timeline(
      new KeyFrame(
        FADE_DURATION,
        new KeyValue(mediaPlayer.volumeProperty(), 0.0)
      )
    );

    Button fadeIn = new Button("Fade In");
    fadeIn.setOnAction(new EventHandler<ActionEvent>() {
      @Override public void handle(ActionEvent t) {
        fadeInTimeline.play();
      }
    });
    fadeIn.setMaxWidth(Double.MAX_VALUE);

    Button fadeOut = new Button("Fade Out");
    fadeOut.setOnAction(new EventHandler<ActionEvent>() {
      @Override public void handle(ActionEvent t) {
        fadeOutTimeline.play();
      }
    });
    fadeOut.setMaxWidth(Double.MAX_VALUE);

    VBox controls = new VBox(5);
    controls.getChildren().setAll(
      volumeSlider,
      fadeIn,
      fadeOut
    );
    controls.setAlignment(Pos.CENTER);
    VBox.setVgrow(volumeSlider, Priority.ALWAYS);

    controls.disableProperty().bind(
      Bindings.or(
        Bindings.equal(Timeline.Status.RUNNING, fadeInTimeline.statusProperty()),
        Bindings.equal(Timeline.Status.RUNNING, fadeOutTimeline.statusProperty())
      )
    );

    return controls;
  }
}

コードはビデオを制御しますが、オーディオのみを行うには、メディア URL を mp3 や aac などのオーディオのみの形式に設定するだけです。

ボリュームコントロールサンプル

于 2013-03-18T19:46:45.363 に答える