本文介绍了JavaFX,MediaPlayer-音量问题!为什么mediaPlayer的音量没有一点一点变化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将Volume设置为0.0,然后在while循环中逐位更改音量.但是,音量从0.0跳到1.0?如何平稳地调节音量?我尝试过

I setVolume to 0.0, and then change the volume bit by bit in the while loop. Yet, the volume jumps from 0.0 to 1.0 ? How can I change the volume smoothly?I tried

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

推荐答案

您的代码有些错误.

  • JavaFX代码应在JavaFX应用程序线程上执行,而不是在Swing事件分配线程上执行.

代替使用EventQueue.invokeLater在Swing线程上执行,而使用 Platform.runLater 可以在JavaFX线程上执行.

Instead of using EventQueue.invokeLater to execute on the Swing thread, use Platform.runLater to execute on the JavaFX thread.

  • 根本没有理由使用Swing事件分发线程.

您的程序仅使用JavaFX控件,因此不要在Swing线程上运行任何东西.

Your program only makes use of JavaFX controls, so don't run anything on the Swing thread.

  • 您通常不需要在ChangeListener中进行任何线程切换调用.
  • You usually don't need any thread switching calls in a ChangeListener.

即使使用EventQueue.invokeLater是错误的,在这种情况下,您甚至都不需要Platform.runLater,因为只有JavaFX应用程序线程才应该修改Slider值.您可以在JavaFX Node 文档:

Even though using EventQueue.invokeLater is wrong, in this case you don't even need to Platform.runLater either as only the JavaFX application thread should be modifying the Slider value anyway. There is a rule you can see in the JavaFX Node documentation:

  • 不要忙于等待JavaFX Application Thread.
  • 计数为1亿的循环只会阻塞应用程序线程,从而导致UI冻结,因为控件永远不会返回到框架来更新UI.

    The loop where you count to one hundred million will just block the application thread resulting in a frozen UI as control will never be returned to the framework to update the UI.

    一旦在UI控件上设置了值,就必须将控件返回到JavaFX框架,以允许值更改反映在控件和用户中.

    Once you set a value on a UI control, you must return control back to the JavaFX framework to allow the value change to be reflected in the control and to the user.

    尝试使用以下代码,通过使用时间轴绑定.

    Try the following code which addresses all of the above issues through the use of Timeline and Binding.

    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)的问题.

    The code controls a Video, but making it do audio only is just a matter of setting the Media URL to an audio only format such as mp3 or aac.

    这篇关于JavaFX,MediaPlayer-音量问题!为什么mediaPlayer的音量没有一点一点变化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-19 15:49