|
本帖最后由 小九九 于 2024-7-2 16:58 编辑
- package com.example.window;
- import javafx.application.Application;
- import javafx.application.Platform;
- import javafx.beans.value.ChangeListener;
- import javafx.beans.value.ObservableValue;
- import javafx.geometry.Insets;
- import javafx.geometry.Pos;
- import javafx.scene.Scene;
- import javafx.scene.control.Button;
- import javafx.scene.control.Label;
- import javafx.scene.control.ListView;
- import javafx.scene.control.Slider;
- import javafx.scene.layout.HBox;
- import javafx.scene.layout.StackPane;
- import javafx.scene.media.Media;
- import javafx.scene.media.MediaPlayer;
- import javafx.scene.media.MediaView;
- import javafx.stage.FileChooser;
- import javafx.stage.Stage;
- import java.io.File;
- import java.util.concurrent.Executors;
- import java.util.concurrent.ScheduledExecutorService;
- import java.util.concurrent.TimeUnit;
- public class VideoPlayerExample extends Application {
- private Stage primaryStage;
- private StackPane root;
- private MediaPlayer mediaPlayer;
- private ListView<String> playlist;
- private boolean isPlaylistVisible = true;
- private Button togglePlaylistButton;
- private Button openFileButton;
- private ScheduledExecutorService mouseIdleExecutor;
- private boolean isMouseIdle = false;
- // 提取文件名(不带扩展名)的方法
- private static String extractFileNameWithoutExtension(String path) {
- int lastSlashIndex = path.lastIndexOf('/');
- if (lastSlashIndex == -1) {
- lastSlashIndex = path.lastIndexOf('\\');
- }
- if (lastSlashIndex == -1) {
- return path;
- }
- String fileName = path.substring(lastSlashIndex + 1);
- int lastDotIndex = fileName.lastIndexOf('.');
- if (lastDotIndex == -1) {
- return fileName;
- }
- return fileName.substring(0, lastDotIndex);
- }
- @Override
- public void start(Stage primaryStage) {
- this.primaryStage = primaryStage;
- root = new StackPane();
- double borderWidth = 1.0;
- root.setStyle("-fx-background-color: black; -fx-border-color: black; -fx-border-width: " + borderWidth + "px;");
- // 默认视频文件
- File defaultFile = new File("G:/音乐.mp4");
- if (defaultFile.exists()) {
- Media media = new Media(defaultFile.toURI().toString());
- mediaPlayer = new MediaPlayer(media);
- } else {
- mediaPlayer = new MediaPlayer(new Media("https://www.example.com/default_video.mp4")); // 默认视频URL
- }
- mediaPlayer.setAutoPlay(true);
- MediaView mediaView = new MediaView(mediaPlayer);
- StackPane.setAlignment(mediaView, Pos.CENTER);
- mediaView.fitWidthProperty().bind(root.widthProperty().subtract(borderWidth * 2));
- mediaView.fitHeightProperty().bind(root.heightProperty().subtract(borderWidth * 2));
- // 播放列表
- playlist = new ListView<>();
- playlist.getItems().addAll(
- "",
- "节目 1",
- "节目 2",
- "节目 3",
- "节目 4",
- "节目 5",
- "节目 6",
- "节目 7",
- "节目 8",
- "节目 9",
- "节目 10"
- );
- playlist.setPrefWidth(200);
- playlist.setMaxWidth(200);
- playlist.setMinWidth(200);
- playlist.getSelectionModel().select(1);
- playlist.getStyleClass().add("playlist");
- // 播放列表显示/隐藏按钮
- togglePlaylistButton = new Button("\u003C");
- togglePlaylistButton.getStyleClass().add("togglePlaylistButton");
- togglePlaylistButton.setOnAction(event -> {
- isPlaylistVisible = !isPlaylistVisible;
- playlist.setVisible(isPlaylistVisible);
- openFileButton.setVisible(isPlaylistVisible);
- if (isPlaylistVisible) {
- togglePlaylistButton.setText("\u003C");
- togglePlaylistButton.setTranslateX(0);
- togglePlaylistButton.setVisible(true);
- } else {
- togglePlaylistButton.setText("\u003E");
- togglePlaylistButton.setTranslateX(-200);
- togglePlaylistButton.setVisible(false);
- }
- });
- HBox playlistContainer = new HBox(playlist, togglePlaylistButton);
- playlistContainer.setAlignment(Pos.CENTER_LEFT);
- HBox.setHgrow(playlist, javafx.scene.layout.Priority.ALWAYS);
- // 监听媒体播放状态
- mediaPlayer.statusProperty().addListener(new ChangeListener<MediaPlayer.Status>() {
- @Override
- public void changed(ObservableValue<? extends MediaPlayer.Status> observable, MediaPlayer.Status oldValue, MediaPlayer.Status newValue) {
- if (newValue == MediaPlayer.Status.PLAYING) {
- String currentMediaPath = mediaPlayer.getMedia().getSource();
- String currentMediaName = extractFileNameWithoutExtension(currentMediaPath);
- updatePlaylist(currentMediaName);
- }
- }
- });
- StackPane.setAlignment(playlistContainer, Pos.CENTER_LEFT);
- root.getChildren().addAll(mediaView, playlistContainer);
- // 打开文件按钮
- openFileButton = new Button("文件");
- openFileButton.getStyleClass().add("openFileButton");
- openFileButton.setOnAction(event -> {
- FileChooser fileChooser = new FileChooser();
- fileChooser.getExtensionFilters().add(
- new FileChooser.ExtensionFilter("视频文件", "*.mp4", "*.mkv", "*.avi")
- );
- File selectedFile = fileChooser.showOpenDialog(primaryStage);
- if (selectedFile != null) {
- Media newMedia = new Media(selectedFile.toURI().toString());
- mediaPlayer.stop();
- mediaPlayer.dispose();
- mediaPlayer = new MediaPlayer(newMedia);
- mediaPlayer.setAutoPlay(true);
- mediaView.setMediaPlayer(mediaPlayer);
- }
- });
- StackPane.setAlignment(openFileButton, Pos.TOP_LEFT);
- root.getChildren().add(openFileButton);
- // 进度条
- Slider slider = new Slider();
- slider.setMin(0);
- slider.setMax(100);
- slider.setValue(0);
- slider.setShowTickLabels(false);
- slider.setShowTickMarks(false);
- slider.setMaxWidth(500);
- StackPane.setAlignment(slider, Pos.BOTTOM_CENTER);
- StackPane.setMargin(slider, new Insets(0, 0, 20, 0));
- slider.valueProperty().addListener((observable, oldValue, newValue) -> {
- double value = newValue.doubleValue();
- double max = slider.getMax();
- if (max != 0) { // 确保 max 不为 0,避免除以 0 的情况
- double fraction = value / max;
- if (!Double.isNaN(fraction)) { // 确保 fraction 不是 NaN
- String color = String.format("-fx-background-color: linear-gradient(to right, #00ff00 %f%%, transparent %f%%);" +
- "-fx-background-radius: 10px;", fraction * 100, fraction * 100);
- slider.setStyle(color);
- } else {
- // 处理 fraction 为 NaN 的情况,例如设置一个默认样式
- slider.setStyle("-fx-background-color: linear-gradient(to right, #00ff00 0%, transparent 0%);" +
- "-fx-background-radius: 10px;");
- }
- } else {
- // 处理 max 为 0 的情况,例如设置一个默认样式
- slider.setStyle("-fx-background-color: linear-gradient(to right, #00ff00 0%, transparent 0%);" +
- "-fx-background-radius: 10px;");
- }
- });
- slider.setStyle("-fx-background-radius: 10px;");
- root.getChildren().add(slider);
- // 总时间标签
- Label durationLabel = new Label("00:00");
- durationLabel.getStyleClass().add("durationLabel");
- durationLabel.setTextFill(javafx.scene.paint.Color.RED);
- StackPane.setAlignment(durationLabel, Pos.BOTTOM_CENTER);
- StackPane.setMargin(durationLabel, new Insets(0, 0, 18.0, 0));
- durationLabel.translateXProperty().bind(slider.widthProperty().subtract(durationLabel.getWidth() / 2 + 135));
- root.getChildren().add(durationLabel);
- // 当前时间标签
- Label currentTimeLabel = new Label("00:00:00");
- currentTimeLabel.setTextFill(javafx.scene.paint.Color.WHITE);
- currentTimeLabel.getStyleClass().add("currentTimeLabel");
- StackPane.setAlignment(currentTimeLabel, Pos.BOTTOM_CENTER);
- StackPane.setMargin(currentTimeLabel, new Insets(0, 0, 17.5, 0));
- currentTimeLabel.translateXProperty().bind(slider.widthProperty().subtract(currentTimeLabel.getWidth() / 2 + 200));
- root.getChildren().add(currentTimeLabel);
- // 斜杠标签
- Label slashLabel = new Label("/");
- slashLabel.setTextFill(javafx.scene.paint.Color.WHITE);
- slashLabel.getStyleClass().add("slashLabel");
- StackPane.setAlignment(slashLabel, Pos.BOTTOM_CENTER);
- StackPane.setMargin(slashLabel, new Insets(0, 0, 18.0, 0));
- slashLabel.translateXProperty().bind(slider.widthProperty().subtract(slashLabel.getWidth() / 2 + 167.5));
- root.getChildren().add(slashLabel);
- // 播放/暂停按钮
- Button playButton = new Button();
- playButton.getStyleClass().add("playButton");
- playButton.setOnAction(event -> {
- if (mediaPlayer.getStatus() == MediaPlayer.Status.PLAYING) {
- mediaPlayer.pause();
- playButton.getStyleClass().remove("playButton");
- playButton.getStyleClass().add("pauseButton");
- } else {
- mediaPlayer.play();
- playButton.getStyleClass().remove("pauseButton");
- playButton.getStyleClass().add("playButton");
- }
- });
- StackPane.setAlignment(playButton, Pos.BOTTOM_CENTER);
- StackPane.setMargin(playButton, new Insets(0, 0, 45, 0));
- playButton.translateXProperty().bind(slider.widthProperty().subtract(playButton.getWidth() / 2 + 500));
- root.getChildren().add(playButton);
- // 设置视频总时间
- mediaPlayer.setOnReady(() -> {
- javafx.util.Duration totalDuration = mediaPlayer.getMedia().getDuration();
- int hours = (int) (totalDuration.toHours());
- int minutes = (int) (totalDuration.toMinutes() % 60);
- int seconds = (int) (totalDuration.toSeconds() % 60);
- durationLabel.setText(String.format("%d:%02d:%02d", hours, minutes, seconds));
- });
- // 视频结束时重置时间
- mediaPlayer.setOnEndOfMedia(() -> {
- durationLabel.setText("00:00:00");
- });
- // 更新当前播放时间
- mediaPlayer.currentTimeProperty().addListener((observable, oldValue, newValue) -> {
- javafx.util.Duration currentTime = newValue;
- int hours = (int) (currentTime.toHours());
- int minutes = (int) (currentTime.toMinutes() % 60);
- int seconds = (int) (currentTime.toSeconds() % 60);
- currentTimeLabel.setText(String.format("%d:%02d:%02d", hours, minutes, seconds));
- });
- final double THRESHOLD = 1;
- slider.valueProperty().addListener((observable, oldValue, newValue) -> {
- double value = newValue.doubleValue();
- double oldVal = oldValue.doubleValue();
- if (Math.abs(value - oldVal) >= THRESHOLD) {
- double max = slider.getMax();
- double fraction = value / max;
- javafx.util.Duration totalDuration = mediaPlayer.getMedia().getDuration();
- javafx.util.Duration newTime = new javafx.util.Duration(totalDuration.toMillis() * fraction);
- mediaPlayer.seek(newTime);
- }
- });
- mediaPlayer.currentTimeProperty().addListener((observable, oldValue, newValue) -> {
- javafx.util.Duration currentTime = newValue;
- javafx.util.Duration totalDuration = mediaPlayer.getMedia().getDuration();
- double fraction = currentTime.toMillis() / totalDuration.toMillis();
- slider.setValue(fraction * 100);
- });
- Scene scene = new Scene(root, 800, 600);
- scene.getStylesheets().add(getClass().getResource("/styles.css").toExternalForm());
- scene.setOnMouseClicked(event -> {
- if (event.getButton() == javafx.scene.input.MouseButton.PRIMARY && event.getClickCount() == 2) {
- toggleFullScreen();
- }
- });
- primaryStage.setScene(scene);
- primaryStage.setTitle("视频播放器");
- primaryStage.show();
- scene.setOnMouseMoved(event -> {
- resetMouseIdleTimer();
- if (!isPlaylistVisible) {
- togglePlaylistButton.setVisible(true);
- }
- });
- scene.setOnMouseExited(event -> {
- if (!isPlaylistVisible) {
- togglePlaylistButton.setVisible(false);
- }
- });
- initMouseIdleTimer();
- scene.setOnMouseMoved(event -> resetMouseIdleTimer());
- primaryStage.setScene(scene);
- primaryStage.setTitle("视频播放器");
- primaryStage.show();
- }
- // 初始化鼠标空闲计时器
- private void initMouseIdleTimer() {
- mouseIdleExecutor = Executors.newSingleThreadScheduledExecutor();
- scheduleMouseIdleTask();
- }
- // 重置鼠标空闲计时器
- private void resetMouseIdleTimer() {
- if (isMouseIdle) {
- Platform.runLater(() -> primaryStage.getScene().setCursor(javafx.scene.Cursor.DEFAULT));
- }
- isMouseIdle = false;
- mouseIdleExecutor.shutdownNow();
- mouseIdleExecutor = Executors.newSingleThreadScheduledExecutor();
- scheduleMouseIdleTask();
- if (!isPlaylistVisible) {
- togglePlaylistButton.setVisible(true);
- }
- }
- // 调度鼠标空闲任务
- private void scheduleMouseIdleTask() {
- mouseIdleExecutor.schedule(() -> {
- isMouseIdle = true;
- if (!isPlaylistVisible && togglePlaylistButton.getText().equals("\u003E")) {
- togglePlaylistButton.setVisible(false);
- }
- Platform.runLater(() -> primaryStage.getScene().setCursor(javafx.scene.Cursor.NONE));
- }, 5000, TimeUnit.MILLISECONDS);
- }
- // 更新播放列表
- private void updatePlaylist(String currentMediaName) {
- playlist.getItems().set(1, "正在播放: " + currentMediaName);
- }
- // 切换全屏
- private void toggleFullScreen() {
- primaryStage.setFullScreen(!primaryStage.isFullScreen());
- }
- public static void main(String[] args) {
- launch(args);
- }
- }
复制代码- .playlist {
- -fx-background-color: rgba(0, 0, 0, 0.5); /* 设置背景颜色为半透明黑色 */
- -fx-text-fill: white; /* 设置文本颜色为白色 */
- -fx-control-inner-background: rgba(0, 0, 0, 0.5); /* 设置内部背景颜色为半透明黑色 */
- -fx-selection-bar: rgba(255, 255, 255, 0.3); /* 设置选择栏的颜色为半透明白色 */
- -fx-selection-bar-text: white; /* 设置选择栏文本颜色为白色 */
- }
- .playlist .list-cell {
- -fx-font-size: 14px; /* 初始字体大小 */
- }
- .openFileButton {
- -fx-background-color: transparent; /* 设置背景颜色为透明 */
- -fx-text-fill: white; /* 设置文本颜色为白色 */
- -fx-font-size: 14px; /* 设置字体大小为 14 像素 */
- -fx-font-weight: bold; /* 设置字体加粗 */
- }
- .togglePlaylistButton {
- -fx-background-color: transparent; /* 设置背景颜色为透明 */
- -fx-text-fill: white; /* 设置文本颜色为白色 */
- -fx-font-size: 20px; /* 设置字体大小为 20 像素 */
- -fx-font-weight: bold; /* 设置字体加粗 */
- -fx-border-color: white; /* 设置边框颜色为白色 */
- -fx-border-width: 2px; /* 设置边框宽度为 2 像素 */
- -fx-border-radius: 50%; /* 设置边框圆角为 50% 以实现圆形 */
- -fx-background-radius: 50%; /* 设置背景圆角为 50% 以实现圆形 */
- -fx-padding: 5px; /* 设置内边距为 5 像素 */
- }
- .durationLabel {
- -fx-text-fill: white; /* 设置文本颜色为白色 */
- -fx-font-size: 14px; /* 设置字体大小为 14 像素 */
- -fx-font-weight: bold; /* 设置字体加粗 */
- }
- .currentTimeLabel {
- -fx-text-fill: white; /* 设置文本颜色为白色 */
- -fx-font-size: 14px; /* 设置字体大小为 14 像素 */
- -fx-font-weight: bold; /* 设置字体加粗 */
- }
- .slashLabel {
- -fx-text-fill: white; /* 设置文本颜色为白色 */
- -fx-font-size: 14px; /* 设置字体大小为 14 像素 */
- -fx-font-weight: bold; /* 设置字体加粗 */
- }
- .playButton {
- -fx-background-color: transparent; /* 设置背景颜色为透明 */
- -fx-text-fill: white; /* 设置文本颜色为白色 */
- -fx-font-size: 16px; /* 设置字体大小为 16 像素 */
- -fx-font-weight: bold; /* 设置字体加粗 */
- -fx-border-color: white; /* 设置边框颜色为白色 */
- -fx-border-width: 2px; /* 设置边框宽度为 2 像素 */
- -fx-padding: 3px; /* 设置内边距为 3 像素 */
- -fx-min-width: 25px; /* 设置最小宽度为 25 像素 */
- -fx-max-width: 25px; /* 设置最大宽度为 25 像素 */
- -fx-shape: "M 50,25 L 75,50 L 50,75 z"; /* 设置形状为向右三角形 */
- }
- .pauseButton {
- -fx-background-color: transparent; /* 设置背景颜色为透明 */
- -fx-text-fill: white; /* 设置文本颜色为白色 */
- -fx-font-size: 16px; /* 设置字体大小为 16 像素 */
- -fx-font-weight: bold; /* 设置字体加粗 */
- -fx-border-color: white; /* 设置边框颜色为白色 */
- -fx-border-width: 2px; /* 设置边框宽度为 2 像素 */
- -fx-padding: 3px; /* 设置内边距为 3 像素 */
- -fx-min-width: 25px; /* 设置最小宽度为 25 像素 */
- -fx-max-width: 25px; /* 设置最大宽度为 25 像素 */
- -fx-shape: "M 40,25 L 50,25 L 50,75 L 40,75 z M 60,25 L 70,25 L 70,75 L 60,75 z"; /* 设置形状为两条竖线 */
- }
复制代码
|
盘基地论坛免责声明
1、本站资源来自互联网用户收集发布,仅供用于学习和交流。
2、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。
3、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决。
4、联系邮箱:admin@panjdzy.com
5、官方网址:www.panjdzy.com
6、备用网址:www.panjd.top
上一篇:软件贴下一篇:有没有大佬懂烟丝调香
|