盘基地资源论坛

 找回密码
 立即注册
搜索
热搜: 书籍 电影 音乐
查看: 14|回复: 0

Java写播放代码

[复制链接]

966

主题

153

回帖

4344

积分

中级会员

Rank: 3Rank: 3

UID
32013
金钱
3210
钻石
7
积分
4344
注册时间
2023-7-27
发表于 前天 16:57 | 显示全部楼层 |阅读模式
本帖最后由 小九九 于 2024-7-2 16:58 编辑
  1. package com.example.window;

  2. import javafx.application.Application;
  3. import javafx.application.Platform;
  4. import javafx.beans.value.ChangeListener;
  5. import javafx.beans.value.ObservableValue;
  6. import javafx.geometry.Insets;
  7. import javafx.geometry.Pos;
  8. import javafx.scene.Scene;
  9. import javafx.scene.control.Button;
  10. import javafx.scene.control.Label;
  11. import javafx.scene.control.ListView;
  12. import javafx.scene.control.Slider;
  13. import javafx.scene.layout.HBox;
  14. import javafx.scene.layout.StackPane;
  15. import javafx.scene.media.Media;
  16. import javafx.scene.media.MediaPlayer;
  17. import javafx.scene.media.MediaView;
  18. import javafx.stage.FileChooser;
  19. import javafx.stage.Stage;
  20. import java.io.File;
  21. import java.util.concurrent.Executors;
  22. import java.util.concurrent.ScheduledExecutorService;
  23. import java.util.concurrent.TimeUnit;

  24. public class VideoPlayerExample extends Application {
  25.     private Stage primaryStage;
  26.     private StackPane root;
  27.     private MediaPlayer mediaPlayer;
  28.     private ListView<String> playlist;
  29.     private boolean isPlaylistVisible = true;
  30.     private Button togglePlaylistButton;
  31.     private Button openFileButton;
  32.     private ScheduledExecutorService mouseIdleExecutor;
  33.     private boolean isMouseIdle = false;

  34.     // 提取文件名(不带扩展名)的方法
  35.     private static String extractFileNameWithoutExtension(String path) {
  36.         int lastSlashIndex = path.lastIndexOf('/');
  37.         if (lastSlashIndex == -1) {
  38.             lastSlashIndex = path.lastIndexOf('\\');
  39.         }
  40.         if (lastSlashIndex == -1) {
  41.             return path;
  42.         }
  43.         String fileName = path.substring(lastSlashIndex + 1);
  44.         int lastDotIndex = fileName.lastIndexOf('.');
  45.         if (lastDotIndex == -1) {
  46.             return fileName;
  47.         }
  48.         return fileName.substring(0, lastDotIndex);
  49.     }

  50.     @Override
  51.     public void start(Stage primaryStage) {
  52.         this.primaryStage = primaryStage;
  53.         root = new StackPane();
  54.         double borderWidth = 1.0;
  55.         root.setStyle("-fx-background-color: black; -fx-border-color: black; -fx-border-width: " + borderWidth + "px;");

  56.         // 默认视频文件
  57.         File defaultFile = new File("G:/音乐.mp4");
  58.         if (defaultFile.exists()) {
  59.             Media media = new Media(defaultFile.toURI().toString());
  60.             mediaPlayer = new MediaPlayer(media);
  61.         } else {
  62.             mediaPlayer = new MediaPlayer(new Media("https://www.example.com/default_video.mp4")); // 默认视频URL
  63.         }
  64.         mediaPlayer.setAutoPlay(true);

  65.         MediaView mediaView = new MediaView(mediaPlayer);
  66.         StackPane.setAlignment(mediaView, Pos.CENTER);
  67.         mediaView.fitWidthProperty().bind(root.widthProperty().subtract(borderWidth * 2));
  68.         mediaView.fitHeightProperty().bind(root.heightProperty().subtract(borderWidth * 2));

  69.         // 播放列表
  70.         playlist = new ListView<>();
  71.         playlist.getItems().addAll(
  72.             "",
  73.             "节目 1",
  74.             "节目 2",
  75.             "节目 3",
  76.             "节目 4",
  77.             "节目 5",
  78.             "节目 6",
  79.             "节目 7",
  80.             "节目 8",
  81.             "节目 9",
  82.             "节目 10"
  83.         );
  84.         playlist.setPrefWidth(200);
  85.         playlist.setMaxWidth(200);
  86.         playlist.setMinWidth(200);
  87.         playlist.getSelectionModel().select(1);
  88.         playlist.getStyleClass().add("playlist");

  89.         // 播放列表显示/隐藏按钮
  90.         togglePlaylistButton = new Button("\u003C");
  91.         togglePlaylistButton.getStyleClass().add("togglePlaylistButton");
  92.         togglePlaylistButton.setOnAction(event -> {
  93.             isPlaylistVisible = !isPlaylistVisible;
  94.             playlist.setVisible(isPlaylistVisible);
  95.             openFileButton.setVisible(isPlaylistVisible);
  96.             if (isPlaylistVisible) {
  97.                 togglePlaylistButton.setText("\u003C");
  98.                 togglePlaylistButton.setTranslateX(0);
  99.                 togglePlaylistButton.setVisible(true);
  100.             } else {
  101.                 togglePlaylistButton.setText("\u003E");
  102.                 togglePlaylistButton.setTranslateX(-200);
  103.                 togglePlaylistButton.setVisible(false);
  104.             }
  105.         });

  106.         HBox playlistContainer = new HBox(playlist, togglePlaylistButton);
  107.         playlistContainer.setAlignment(Pos.CENTER_LEFT);
  108.         HBox.setHgrow(playlist, javafx.scene.layout.Priority.ALWAYS);

  109.         // 监听媒体播放状态
  110.         mediaPlayer.statusProperty().addListener(new ChangeListener<MediaPlayer.Status>() {
  111.             @Override
  112.             public void changed(ObservableValue<? extends MediaPlayer.Status> observable, MediaPlayer.Status oldValue, MediaPlayer.Status newValue) {
  113.                 if (newValue == MediaPlayer.Status.PLAYING) {
  114.                     String currentMediaPath = mediaPlayer.getMedia().getSource();
  115.                     String currentMediaName = extractFileNameWithoutExtension(currentMediaPath);
  116.                     updatePlaylist(currentMediaName);
  117.                 }
  118.             }
  119.         });

  120.         StackPane.setAlignment(playlistContainer, Pos.CENTER_LEFT);
  121.         root.getChildren().addAll(mediaView, playlistContainer);

  122.         // 打开文件按钮
  123.         openFileButton = new Button("文件");
  124.         openFileButton.getStyleClass().add("openFileButton");
  125.         openFileButton.setOnAction(event -> {
  126.             FileChooser fileChooser = new FileChooser();
  127.             fileChooser.getExtensionFilters().add(
  128.                 new FileChooser.ExtensionFilter("视频文件", "*.mp4", "*.mkv", "*.avi")
  129.             );

  130.             File selectedFile = fileChooser.showOpenDialog(primaryStage);
  131.             if (selectedFile != null) {
  132.                 Media newMedia = new Media(selectedFile.toURI().toString());
  133.                 mediaPlayer.stop();
  134.                 mediaPlayer.dispose();
  135.                 mediaPlayer = new MediaPlayer(newMedia);
  136.                 mediaPlayer.setAutoPlay(true);
  137.                 mediaView.setMediaPlayer(mediaPlayer);
  138.             }
  139.         });

  140.         StackPane.setAlignment(openFileButton, Pos.TOP_LEFT);
  141.         root.getChildren().add(openFileButton);

  142.         // 进度条
  143.         Slider slider = new Slider();
  144.         slider.setMin(0);
  145.         slider.setMax(100);
  146.         slider.setValue(0);
  147.         slider.setShowTickLabels(false);
  148.         slider.setShowTickMarks(false);
  149.         slider.setMaxWidth(500);

  150.         StackPane.setAlignment(slider, Pos.BOTTOM_CENTER);
  151.         StackPane.setMargin(slider, new Insets(0, 0, 20, 0));

  152.         slider.valueProperty().addListener((observable, oldValue, newValue) -> {
  153.             double value = newValue.doubleValue();
  154.             double max = slider.getMax();
  155.             if (max != 0) { // 确保 max 不为 0,避免除以 0 的情况
  156.                 double fraction = value / max;
  157.                 if (!Double.isNaN(fraction)) { // 确保 fraction 不是 NaN
  158.                     String color = String.format("-fx-background-color: linear-gradient(to right, #00ff00 %f%%, transparent %f%%);" +
  159.                         "-fx-background-radius: 10px;", fraction * 100, fraction * 100);
  160.                     slider.setStyle(color);
  161.                 } else {
  162.                     // 处理 fraction 为 NaN 的情况,例如设置一个默认样式
  163.                     slider.setStyle("-fx-background-color: linear-gradient(to right, #00ff00 0%, transparent 0%);" +
  164.                         "-fx-background-radius: 10px;");
  165.                 }
  166.             } else {
  167.                 // 处理 max 为 0 的情况,例如设置一个默认样式
  168.                 slider.setStyle("-fx-background-color: linear-gradient(to right, #00ff00 0%, transparent 0%);" +
  169.                     "-fx-background-radius: 10px;");
  170.             }
  171.         });

  172.         slider.setStyle("-fx-background-radius: 10px;");
  173.         root.getChildren().add(slider);

  174.         // 总时间标签
  175.         Label durationLabel = new Label("00:00");
  176.         durationLabel.getStyleClass().add("durationLabel");
  177.         durationLabel.setTextFill(javafx.scene.paint.Color.RED);

  178.         StackPane.setAlignment(durationLabel, Pos.BOTTOM_CENTER);
  179.         StackPane.setMargin(durationLabel, new Insets(0, 0, 18.0, 0));
  180.         durationLabel.translateXProperty().bind(slider.widthProperty().subtract(durationLabel.getWidth() / 2 + 135));
  181.         root.getChildren().add(durationLabel);

  182.         // 当前时间标签
  183.         Label currentTimeLabel = new Label("00:00:00");
  184.         currentTimeLabel.setTextFill(javafx.scene.paint.Color.WHITE);
  185.         currentTimeLabel.getStyleClass().add("currentTimeLabel");

  186.         StackPane.setAlignment(currentTimeLabel, Pos.BOTTOM_CENTER);
  187.         StackPane.setMargin(currentTimeLabel, new Insets(0, 0, 17.5, 0));
  188.         currentTimeLabel.translateXProperty().bind(slider.widthProperty().subtract(currentTimeLabel.getWidth() / 2 + 200));
  189.         root.getChildren().add(currentTimeLabel);

  190.         // 斜杠标签
  191.         Label slashLabel = new Label("/");
  192.         slashLabel.setTextFill(javafx.scene.paint.Color.WHITE);
  193.         slashLabel.getStyleClass().add("slashLabel");

  194.         StackPane.setAlignment(slashLabel, Pos.BOTTOM_CENTER);
  195.         StackPane.setMargin(slashLabel, new Insets(0, 0, 18.0, 0));
  196.         slashLabel.translateXProperty().bind(slider.widthProperty().subtract(slashLabel.getWidth() / 2 + 167.5));
  197.         root.getChildren().add(slashLabel);

  198.         // 播放/暂停按钮
  199.         Button playButton = new Button();
  200.         playButton.getStyleClass().add("playButton");
  201.         playButton.setOnAction(event -> {
  202.             if (mediaPlayer.getStatus() == MediaPlayer.Status.PLAYING) {
  203.                 mediaPlayer.pause();
  204.                 playButton.getStyleClass().remove("playButton");
  205.                 playButton.getStyleClass().add("pauseButton");
  206.             } else {
  207.                 mediaPlayer.play();
  208.                 playButton.getStyleClass().remove("pauseButton");
  209.                 playButton.getStyleClass().add("playButton");
  210.             }
  211.         });

  212.         StackPane.setAlignment(playButton, Pos.BOTTOM_CENTER);
  213.         StackPane.setMargin(playButton, new Insets(0, 0, 45, 0));
  214.         playButton.translateXProperty().bind(slider.widthProperty().subtract(playButton.getWidth() / 2 + 500));
  215.         root.getChildren().add(playButton);

  216.         // 设置视频总时间
  217.         mediaPlayer.setOnReady(() -> {
  218.             javafx.util.Duration totalDuration = mediaPlayer.getMedia().getDuration();
  219.             int hours = (int) (totalDuration.toHours());
  220.             int minutes = (int) (totalDuration.toMinutes() % 60);
  221.             int seconds = (int) (totalDuration.toSeconds() % 60);
  222.             durationLabel.setText(String.format("%d:%02d:%02d", hours, minutes, seconds));
  223.         });

  224.         // 视频结束时重置时间
  225.         mediaPlayer.setOnEndOfMedia(() -> {
  226.             durationLabel.setText("00:00:00");
  227.         });

  228.         // 更新当前播放时间
  229.         mediaPlayer.currentTimeProperty().addListener((observable, oldValue, newValue) -> {
  230.             javafx.util.Duration currentTime = newValue;
  231.             int hours = (int) (currentTime.toHours());
  232.             int minutes = (int) (currentTime.toMinutes() % 60);
  233.             int seconds = (int) (currentTime.toSeconds() % 60);
  234.             currentTimeLabel.setText(String.format("%d:%02d:%02d", hours, minutes, seconds));
  235.         });

  236.         final double THRESHOLD = 1;
  237.         slider.valueProperty().addListener((observable, oldValue, newValue) -> {
  238.             double value = newValue.doubleValue();
  239.             double oldVal = oldValue.doubleValue();
  240.             if (Math.abs(value - oldVal) >= THRESHOLD) {
  241.                 double max = slider.getMax();
  242.                 double fraction = value / max;
  243.                 javafx.util.Duration totalDuration = mediaPlayer.getMedia().getDuration();
  244.                 javafx.util.Duration newTime = new javafx.util.Duration(totalDuration.toMillis() * fraction);
  245.                 mediaPlayer.seek(newTime);
  246.             }
  247.         });

  248.         mediaPlayer.currentTimeProperty().addListener((observable, oldValue, newValue) -> {
  249.             javafx.util.Duration currentTime = newValue;
  250.             javafx.util.Duration totalDuration = mediaPlayer.getMedia().getDuration();
  251.             double fraction = currentTime.toMillis() / totalDuration.toMillis();
  252.             slider.setValue(fraction * 100);
  253.         });

  254.         Scene scene = new Scene(root, 800, 600);
  255.         scene.getStylesheets().add(getClass().getResource("/styles.css").toExternalForm());
  256.         scene.setOnMouseClicked(event -> {
  257.             if (event.getButton() == javafx.scene.input.MouseButton.PRIMARY && event.getClickCount() == 2) {
  258.                 toggleFullScreen();
  259.             }
  260.         });
  261.         primaryStage.setScene(scene);
  262.         primaryStage.setTitle("视频播放器");
  263.         primaryStage.show();

  264.         scene.setOnMouseMoved(event -> {
  265.             resetMouseIdleTimer();
  266.             if (!isPlaylistVisible) {
  267.                 togglePlaylistButton.setVisible(true);
  268.             }
  269.         });

  270.         scene.setOnMouseExited(event -> {
  271.             if (!isPlaylistVisible) {
  272.                 togglePlaylistButton.setVisible(false);
  273.             }
  274.         });

  275.         initMouseIdleTimer();
  276.         scene.setOnMouseMoved(event -> resetMouseIdleTimer());
  277.         primaryStage.setScene(scene);
  278.         primaryStage.setTitle("视频播放器");
  279.         primaryStage.show();
  280.     }

  281.     // 初始化鼠标空闲计时器
  282.     private void initMouseIdleTimer() {
  283.         mouseIdleExecutor = Executors.newSingleThreadScheduledExecutor();
  284.         scheduleMouseIdleTask();
  285.     }

  286.     // 重置鼠标空闲计时器
  287.     private void resetMouseIdleTimer() {
  288.         if (isMouseIdle) {
  289.             Platform.runLater(() -> primaryStage.getScene().setCursor(javafx.scene.Cursor.DEFAULT));
  290.         }
  291.         isMouseIdle = false;
  292.         mouseIdleExecutor.shutdownNow();
  293.         mouseIdleExecutor = Executors.newSingleThreadScheduledExecutor();
  294.         scheduleMouseIdleTask();
  295.         if (!isPlaylistVisible) {
  296.             togglePlaylistButton.setVisible(true);
  297.         }
  298.     }

  299.     // 调度鼠标空闲任务
  300.     private void scheduleMouseIdleTask() {
  301.         mouseIdleExecutor.schedule(() -> {
  302.             isMouseIdle = true;
  303.             if (!isPlaylistVisible && togglePlaylistButton.getText().equals("\u003E")) {
  304.                 togglePlaylistButton.setVisible(false);
  305.             }
  306.             Platform.runLater(() -> primaryStage.getScene().setCursor(javafx.scene.Cursor.NONE));
  307.         }, 5000, TimeUnit.MILLISECONDS);
  308.     }

  309.     // 更新播放列表
  310.     private void updatePlaylist(String currentMediaName) {
  311.         playlist.getItems().set(1, "正在播放: " + currentMediaName);
  312.     }

  313.     // 切换全屏
  314.     private void toggleFullScreen() {
  315.         primaryStage.setFullScreen(!primaryStage.isFullScreen());
  316.     }

  317.     public static void main(String[] args) {
  318.         launch(args);
  319.     }
  320. }
复制代码
  1. .playlist {
  2.     -fx-background-color: rgba(0, 0, 0, 0.5); /* 设置背景颜色为半透明黑色 */
  3.     -fx-text-fill: white;  /* 设置文本颜色为白色 */
  4.     -fx-control-inner-background: rgba(0, 0, 0, 0.5);  /* 设置内部背景颜色为半透明黑色 */
  5.     -fx-selection-bar: rgba(255, 255, 255, 0.3);  /* 设置选择栏的颜色为半透明白色 */
  6.     -fx-selection-bar-text: white;   /* 设置选择栏文本颜色为白色 */
  7. }

  8. .playlist .list-cell {
  9.     -fx-font-size: 14px; /* 初始字体大小 */
  10. }  

  11. .openFileButton {
  12.     -fx-background-color: transparent;  /* 设置背景颜色为透明 */
  13.     -fx-text-fill: white;   /* 设置文本颜色为白色 */
  14.     -fx-font-size: 14px;  /* 设置字体大小为 14 像素 */
  15.     -fx-font-weight: bold;   /* 设置字体加粗 */
  16. }

  17. .togglePlaylistButton {
  18.     -fx-background-color: transparent;  /* 设置背景颜色为透明 */
  19.     -fx-text-fill: white;   /* 设置文本颜色为白色 */
  20.     -fx-font-size: 20px;  /* 设置字体大小为 20 像素 */
  21.     -fx-font-weight: bold;   /* 设置字体加粗 */
  22.     -fx-border-color: white;  /* 设置边框颜色为白色 */
  23.     -fx-border-width: 2px;  /* 设置边框宽度为 2 像素 */
  24.     -fx-border-radius: 50%;  /* 设置边框圆角为 50% 以实现圆形 */
  25.     -fx-background-radius: 50%;  /* 设置背景圆角为 50% 以实现圆形 */
  26.     -fx-padding: 5px;  /* 设置内边距为 5 像素 */
  27. }

  28. .durationLabel {
  29.     -fx-text-fill: white;   /* 设置文本颜色为白色 */
  30.     -fx-font-size: 14px;    /* 设置字体大小为 14 像素 */
  31.     -fx-font-weight: bold;  /* 设置字体加粗 */
  32. }

  33. .currentTimeLabel {
  34.     -fx-text-fill: white;   /* 设置文本颜色为白色 */
  35.     -fx-font-size: 14px;    /* 设置字体大小为 14 像素 */
  36.     -fx-font-weight: bold;  /* 设置字体加粗 */
  37. }

  38. .slashLabel {
  39.     -fx-text-fill: white;   /* 设置文本颜色为白色 */
  40.     -fx-font-size: 14px;    /* 设置字体大小为 14 像素 */
  41.     -fx-font-weight: bold;  /* 设置字体加粗 */
  42. }

  43. .playButton {
  44.     -fx-background-color: transparent;  /* 设置背景颜色为透明 */
  45.     -fx-text-fill: white;   /* 设置文本颜色为白色 */
  46.     -fx-font-size: 16px;  /* 设置字体大小为 16 像素 */
  47.     -fx-font-weight: bold;   /* 设置字体加粗 */
  48.     -fx-border-color: white;  /* 设置边框颜色为白色 */
  49.     -fx-border-width: 2px;  /* 设置边框宽度为 2 像素 */
  50.     -fx-padding: 3px;  /* 设置内边距为 3 像素 */
  51.     -fx-min-width: 25px;  /* 设置最小宽度为 25 像素 */
  52.     -fx-max-width: 25px;  /* 设置最大宽度为 25 像素 */
  53.     -fx-shape: "M 50,25 L 75,50 L 50,75 z";  /* 设置形状为向右三角形 */
  54. }

  55. .pauseButton {
  56.     -fx-background-color: transparent;  /* 设置背景颜色为透明 */
  57.     -fx-text-fill: white;   /* 设置文本颜色为白色 */
  58.     -fx-font-size: 16px;  /* 设置字体大小为 16 像素 */
  59.     -fx-font-weight: bold;   /* 设置字体加粗 */
  60.     -fx-border-color: white;  /* 设置边框颜色为白色 */
  61.     -fx-border-width: 2px;  /* 设置边框宽度为 2 像素 */
  62.     -fx-padding: 3px;  /* 设置内边距为 3 像素 */
  63.     -fx-min-width: 25px;  /* 设置最小宽度为 25 像素 */
  64.     -fx-max-width: 25px;  /* 设置最大宽度为 25 像素 */
  65.     -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";  /* 设置形状为两条竖线 */
  66. }
复制代码


盘基地论坛免责声明
1、本站资源来自互联网用户收集发布,仅供用于学习和交流。
2、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。
3、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决。
4、联系邮箱:[email protected]
5、官方网址:www.panjdzy.com
6、备用网址:www.panjd.top




上一篇:软件贴
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|盘基地资源论坛

GMT+8, 2024-7-4 19:13 , Processed in 0.078593 second(s), 23 queries .

Powered by Discuz!

本站资源来自互联网用户收集发布,仅供用于学习和交流。

如有侵权之处,请联系站长并出示版权证明以便删除,敬请谅解!

联系邮箱:[email protected]

快速回复 返回顶部 返回列表