JavaFX - 拖动鼠标按钮后设置滑块值 [英] JavaFX - Set Slider value after dragging mouse button

查看:16
本文介绍了JavaFX - 拖动鼠标按钮后设置滑块值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写音乐播放器,但我不知道如何编写滑块拖动处理程序以在用户释放鼠标按钮后设置值.当我编写简单的 MouseDragged 方法时,拖动会带来非审美的倒带"声音,因为媒体播放器每次滑块移动时都会更改值.播放滑块时,媒体播放器侦听器会自动更改值以与曲目持续时间同步.这是我目前得到的.

I'm writing music player and I don't know how to code slider dragging handler to set value after user frees mouse button. When I write simple MouseDragged method dragging brings non estetic "rewinding" sound because mediaplayer changes value every time slider moves. While playing slider automatic changes value by mediaplayer listener to synchronize with track duration. This is what I got so far.

ChangeListener<Duration> timeListener =  new ChangeListener<Duration>() {
    @Override
    public void changed(
            ObservableValue<? extends Duration> observableValue,
            Duration duration,
            Duration current) {
        durSlider
                .setValue(current
                        .toSeconds());
    }
};

durSlider.setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {

                    mediaPlayer.seek(Duration.seconds(durSlider.getValue()));

                    }

                });

推荐答案

valueChanging 滑块的属性 指示滑块是否正在更改.它是一个可观察的属性,因此您可以直接为其附加一个侦听器,并在值停止更改时做出响应:

The valueChanging property of the slider indicates if the slider is in the process of being changed. It is an observable property, so you can attach a listener directly to it, and respond when the value stops changing:

durSlider.valueChangingProperty().addListener(new ChangeListener<Boolean>() {
    @Override
    public void changed(ObservableValue<? extends Boolean> obs, Boolean wasChanging, Boolean isNowChanging) {
        if (! isNowChanging) {
            mediaPlayer.seek(Duration.seconds(durSlider.getValue()));
        }
    }
});

如果用户点击滑块上的轨道"或使用键盘移动它,这不会改变播放器的位置.为此,您可以使用 value 属性注册一个侦听器.在这里你需要小心,因为值也会通过你的时间监听器改变.理论上,时间监听器应该设置滑块的值,然后应该会导致尝试将播放器的当前时间设置为其已有的确切值(这将导致无操作).但是,舍入错误可能会导致很多小的调整,从而导致您观察到的静态".要解决此问题,请仅在更改超过某个小的最小值时移动媒体播放器:

This won't change the position of the player if the user clicks on the "track" on the slider, or uses the keyboard to move it. For that, you can register a listener with the value property. You need to be careful here, because the value is also going to change via your time listener. In theory, the time listener should set the value of the slider, and then that should cause an attempt to set the current time of the player to the exact value it already has (which would result in a no-op). However, rounding errors will likely result in a lot of small adjustments, causing the "static" you are observing. To fix this, only move the media player if the change is more than some small minimum amount:

private static double MIN_CHANGE = 0.5 ; //seconds

// ...

durSlider.valueProperty().addListener(new ChangeListener<Number>() {
    @Override
    public void changed(ObservableValue<? extends Number> obs, Number oldValue, Number newValue) {
        if (! durSlider.isValueChanging()) {
            double currentTime = mediaPlayer.getCurrentTime().toSeconds();
            double sliderTime = newValue.doubleValue();
            if (Math.abs(currentTime - sliderTime) > 0.5) {
                mediaPlayer.seek(newValue.doubleValue());
            }
        }
    }
});

最后,如果用户尝试拖动滑块,您不希望您的时间侦听器移动滑块:

Finally, you don't want your time listener to move the slider if the user is trying to drag it:

ChangeListener<Duration> timeListener =  new ChangeListener<Duration>() {
    @Override
    public void changed(
            ObservableValue<? extends Duration> observableValue,
            Duration duration,
            Duration current) {
        if (! durSlider.isValueChanging()) {
            durSlider.setValue(current.toSeconds());
        }
    }
};

这是一个完整的示例(为简洁起见,使用 lambdas):

Here's a complete example (using lambdas for brevity):

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;
import javafx.util.Duration;

public class VideoPlayerTest extends Application {

    private static final String MEDIA_URL =
            "http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv";

    private static final double MIN_CHANGE = 0.5 ;

    @Override
    public void start(Stage primaryStage) {
        MediaPlayer player = new MediaPlayer(new Media(MEDIA_URL));
        MediaView mediaView = new MediaView(player);

        Slider slider = new Slider();
        player.totalDurationProperty().addListener((obs, oldDuration, newDuration) -> slider.setMax(newDuration.toSeconds()));

        BorderPane root = new BorderPane(mediaView, null, null, slider, null);

        slider.valueChangingProperty().addListener((obs, wasChanging, isChanging) -> {
            if (! isChanging) {
                player.seek(Duration.seconds(slider.getValue()));
            }
        });

        slider.valueProperty().addListener((obs, oldValue, newValue) -> {
            if (! slider.isValueChanging()) {
                double currentTime = player.getCurrentTime().toSeconds();
                if (Math.abs(currentTime - newValue.doubleValue()) > MIN_CHANGE) {
                    player.seek(Duration.seconds(newValue.doubleValue()));
                }
            }
        });

        player.currentTimeProperty().addListener((obs, oldTime, newTime) -> {
            if (! slider.isValueChanging()) {
                slider.setValue(newTime.toSeconds());
            }
        });

        Scene scene = new Scene(root, 540, 280);
        primaryStage.setScene(scene);
        primaryStage.show();

        player.play();
    }

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

这篇关于JavaFX - 拖动鼠标按钮后设置滑块值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆