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

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

问题描述

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

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 - 拖动鼠标按钮后设置Slider值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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