简体   繁体   English

JavaFx Slider 拇指监听器

[英]JavaFx Slider thumb listener

I am trying to create a media player using java fx slider.我正在尝试使用 java fx 滑块创建媒体播放器。 I would like to incorporate the play button with the slider thumb.我想将播放按钮与滑块拇指合并。 So when user click on the slider's thumb it will activate the media player to play and the slider will move accordingly when its played.因此,当用户单击滑块的拇指时,它将激活媒体播放器进行播放,并且滑块在播放时会相应地移动。 From the documentation the listeners is for the slider and not the slider's thumb.从文档中,侦听器是针对滑块的,而不是针对滑块的拇指。 Any suggestion or ideas how the listener can be implemented?任何建议或想法如何实施监听器?

I don't think the Slider control was implemented for that purpose, it might be possible but would require a lot of hacking, Why do you have to limit yourself like that ?我不认为 Slider 控件是为此目的而实现的,它可能是可能的,但需要大量的黑客攻击,为什么你必须这样限制自己?

I suggest implementing a simple custom control and styling it like to look a slider, or even better you can add an icon inside the thumb, to indicate the state (Playing / Paused), you can basically do whatever you want with it.我建议实现一个简单的自定义控件并将它的样式设置为看起来像一个滑块,或者更好的是您可以在拇指内添加一个图标,以指示状态(播放/暂停),您基本上可以用它做任何您想做的事情。

I have written the following example which uses a StackPane as a parent, then uses StackPanes for children (the full-width bar and the progress bar, also the thumb) :我编写了以下示例,该示例使用 StackPane 作为父级,然后将 StackPanes 用于子级(全角栏和进度条,还有拇指):

I named the class MediaSlider and it extends StackPane我将类命名为 MediaSlider,它扩展了 StackPane

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

public class MediaSlider extends StackPane {
    private String main = "#6200ee";
    private String sec = "#c6aee6";

    private DoubleProperty value;

    private StackPane thumb;

    private ImageView icon;
    private Image playImage, pauseImage;

    public MediaSlider() {
        setAlignment(Pos.CENTER_LEFT);
        setMaxHeight(50);

        value = new SimpleDoubleProperty(0);

        StackPane bar = createRect(sec);
        bar.maxWidthProperty().bind(widthProperty());

        StackPane fill = createRect(main);
        fill.maxWidthProperty()
                .bind(widthProperty().subtract(heightProperty()).multiply(value).add(heightProperty().divide(2)));

        thumb = new StackPane();
        thumb.setMaxWidth(Region.USE_PREF_SIZE);
        thumb.setMinWidth(Region.USE_PREF_SIZE);
        thumb.prefWidthProperty().bind(heightProperty());
        thumb.setCursor(Cursor.HAND);

        Circle circle = new Circle();
        circle.radiusProperty().bind(heightProperty().divide(2));
        circle.setFill(Color.web(main));

        playImage = new Image(getClass().getResourceAsStream("/play.png"));
        pauseImage = new Image(getClass().getResourceAsStream("/pause.png"));

        icon = new ImageView(playImage);
        icon.fitWidthProperty().bind(thumb.widthProperty().divide(2));
        icon.fitHeightProperty().bind(thumb.heightProperty().divide(2));
        
        thumb.getChildren().addAll(circle, icon);
        thumb.setEffect(new DropShadow(10, Color.gray(.0, .4)));
        thumb.translateXProperty().bind(widthProperty().subtract(thumb.widthProperty()).multiply(value));

        getChildren().addAll(bar, fill, thumb);

    }

    public void setOnThumbClicked(EventHandler<MouseEvent> handler) {
        thumb.setOnMouseClicked(handler);
    }

    public void pause() {
        icon.setImage(playImage);
    }

    public void play() {
        icon.setImage(pauseImage);
    }

    public void setValue(double value) {
        this.value.set(value);
    }

    public double getValue() {
        return value.get();
    }

    public DoubleProperty valueProperty() {
        return value;
    }

    private StackPane createRect(String color) {
        StackPane res = new StackPane();
        res.maxHeightProperty().bind(heightProperty().divide(5));
        res.setStyle("-fx-background-color: " + color + ";-fx-background-radius: 5;");
        return res;
    }
}

Then used it in the app in the following way然后通过以下方式在应用程序中使用它

import java.io.IOException;
import java.net.URISyntaxException;

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.stage.Stage;
import javafx.util.Duration;

public class App extends Application {

    @Override
    public void start(Stage stage) throws IOException, URISyntaxException {
        StackPane root = new StackPane();
        root.setPadding(new Insets(20));
        root.setStyle("-fx-background-color: #e5e5e5");

        //load media
        MediaPlayer player = new MediaPlayer(new Media(getClass().getResource("/song.mp3").toURI().toString()));
        
        //instantiate your custom slider class
        MediaSlider s = new MediaSlider();

        //bind slider position to media position
        s.valueProperty().bind(Bindings.createDoubleBinding(() -> {
            double val = player.getCurrentTime().toSeconds() / player.getTotalDuration().toSeconds();
            return Double.isNaN(val) ? .0 : val;
        }, player.currentTimeProperty()));

        //handle click events
        s.setOnThumbClicked(event -> {
            if (player.getStatus().equals(Status.PLAYING)) {
                s.pause();
                player.pause();
                player.seek(player.getCurrentTime());
            } else {
                s.play();
                player.play();
            }
        });

        //replay on end of media
        player.setOnEndOfMedia(() -> player.seek(Duration.ZERO));

        root.getChildren().add(s);

        Scene scene = new Scene(root, 600, 300);
        stage.setScene(scene);
        stage.show();
    }

}

Here is how it looks :这是它的外观:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM