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 代码应该在 JavaFX 应用程序线程上执行,而不是在 Swing 事件调度线程上执行。

不要使用EventQueue.invokeLater在 Swing 线程上执行,而是使用Platform.runLater在 JavaFX 线程上执行。

  • 根本没有理由使用 Swing 事件调度线程。

您的程序只使用 JavaFX 控件,所以不要在 Swing 线程上运行任何东西。

  • 您通常不需要在ChangeListener.

即使使用EventQueue.invokeLater是错误的,在这种情况下,您甚至都不需要这样做,Platform.runLater因为无论如何只有 JavaFX 应用程序线程应该修改 Slider 值。您可以在 JavaFX节点文档中看到一条规则:

应用程序必须在 JavaFX 应用程序线程上将节点附加到场景,并修改已附加到场景的节点。

  • 不要忙于等待 JavaFX 应用程序线程。

你数到一亿的循环只会阻塞应用程序线程,导致 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 回答