package simpleMediaPlayer; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.Slider; import javafx.scene.effect.ColorAdjust; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.input.InputEvent; import javafx.scene.input.MouseEvent; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; import javafx.scene.media.Media; import javafx.scene.media.MediaPlayer; import javafx.scene.media.MediaView; import javafx.stage.Stage; import javafx.util.Duration; /** * create by Intellij IDEA * Author: Al-assad * E-mail: [email protected] * Github: https://github.com/Al-assad * Date: 2017/1/20 14:22 * Description: */ public class PlayerController { @FXML Button playBT; @FXML Button stopBT; @FXML Button maxBT; @FXML Button volumeBT; @FXML Label timeLB; @FXML Slider processSD; @FXML Slider volumeSD; @FXML MediaView mediaView; @FXML VBox controlBar; @FXML BorderPane mediaPane; @FXML AnchorPane anchorPane; //控件素材图片 private String playIcon = getClass().getResource("icon/play.png").toString(); private String pauseIcon = getClass().getResource("icon/pause.png").toString(); private String stopIcon = getClass().getResource("icon/stop.png").toString(); private String volOffIcon = getClass().getResource("icon/volume_off.png").toString(); private String volOnIcon = getClass().getResource("icon/volume_On.png").toString(); private String maxIcon = getClass().getResource("icon/max.png").toString(); private MediaPlayer mediaPlayer; private Media media; private String url; //资源的url地址 private boolean popup; //窗口弹出方式 private Scene scene ; //父类窗口 private boolean atEndOfMedia = false; //记录视频是否处播放到结束 private final boolean repeat = false; //记录视频是否重复播放 private double volumeValue; //储存静音操作前的音量数据 private Duration duration ; //记录视频持续时间 private int mediaHeight; //视频资源的尺寸 private int mediaWidth; private int currentHeight; //当前整个播放器的尺寸 private int currentWidth; public void setScene(Scene scene){ this.scene = scene; } //程序初始化:设置按钮图标 public void initialize(){ //设置各控件图标 setIcon(playBT,playIcon,25); setIcon(stopBT,stopIcon,25); setIcon(volumeBT,volOnIcon,15); setIcon(maxBT,maxIcon,25); } //程序启动项,传入必要参数 public void start(String url,boolean popup,int width,int height){ this.url = url; this.popup = popup; //MediaView设置 media = new Media(url); mediaPlayer = new MediaPlayer(media); mediaView.setMediaPlayer(mediaPlayer); //设置播放器,在媒体资源加载完毕后,获取相应的数据,设置组件自适应布局 setMediaPlayer(width,height); //设置各组件动作事件 setMediaViewOnClick(); setPlayButton(); setStopButton(); setVolumeButton(); setVolumeSD(); setProcessSlider(); setMaximizeButton(); } //设置mediaPlayer(参数:整个播放器的尺寸) void setMediaPlayer(int width,int height){ mediaPlayer.setCycleCount(repeat ? MediaPlayer.INDEFINITE : 1); //视频就绪时更新 进度条 、时间标签、音量条数据,设置布局尺寸 mediaPlayer.setOnReady(new Runnable(){ @Override public void run() { duration = mediaPlayer.getMedia().getDuration(); volumeValue = mediaPlayer.getVolume(); mediaHeight = media.getHeight(); mediaWidth = media.getWidth(); //设置布局尺寸 setSize(width,height); //设置尺寸随窗口改变自适应变化(只使用于弹窗) if (scene!= null) { scene.widthProperty().addListener(new ChangeListener<Number>() { @Override public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) { setSize(newValue.intValue(),currentHeight);} }); scene.heightProperty().addListener(new ChangeListener<Number>() { @Override public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) { setSize(currentWidth,newValue.intValue()); } }); } //设置全屏时的UI变化:工具栏只有在鼠标进入MediaView时才出现 EventHandler onScreen = new EventHandler<InputEvent>(){ @Override public void handle(InputEvent event) { controlBar.setVisible(true); } }; EventHandler offScreen = new EventHandler<InputEvent>(){ @Override public void handle(InputEvent event) { controlBar.setVisible(false); } }; if(scene != null && popup){ ((Stage)scene.getWindow()).fullScreenProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { if (newValue.booleanValue()) { controlBar.setVisible(false); mediaPane.addEventHandler(MouseEvent.MOUSE_CLICKED, onScreen); controlBar.addEventHandler(MouseEvent.MOUSE_EXITED, offScreen); }else{ controlBar.setVisible(true); mediaPane.removeEventHandler(MouseEvent.MOUSE_CLICKED,onScreen); controlBar.removeEventHandler(MouseEvent.MOUSE_EXITED,offScreen); } } }); } updateValues(); } }); //mediaPlayer当前进度发生改变时候,进度条 、时间标签、音量条数据 mediaPlayer.currentTimeProperty().addListener(new ChangeListener<Duration>(){ @Override public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) { updateValues(); } }); } //设置点击MediaView时暂停或开始 private void setMediaViewOnClick(){ mediaView.setOnMouseClicked(event -> { if(media == null) return; MediaPlayer.Status status = mediaPlayer.getStatus(); if(status == MediaPlayer.Status.UNKNOWN || status == MediaPlayer.Status.HALTED ){ return; } //当资源处于暂停或停止状态时 if(status == MediaPlayer.Status.PAUSED || status == MediaPlayer.Status.READY || status == MediaPlayer.Status.STOPPED){ //当资源播放结束时,重绕资源 if(atEndOfMedia){ mediaPlayer.seek(mediaPlayer.getStartTime()); atEndOfMedia = false; } mediaPlayer.play(); setIcon(playBT,pauseIcon,25); }else{ //当资源处于播放状态时 mediaPlayer.pause(); setIcon(playBT,playIcon,25); } }); } //设置播放按钮动作 private void setPlayButton(){ playBT.setOnAction((ActionEvent e)->{ if(media == null) return; MediaPlayer.Status status = mediaPlayer.getStatus(); if(status == MediaPlayer.Status.UNKNOWN || status == MediaPlayer.Status.HALTED ){ return; } //当资源处于暂停或停止状态时 if(status == MediaPlayer.Status.PAUSED || status == MediaPlayer.Status.READY || status == MediaPlayer.Status.STOPPED){ //当资源播放结束时,重绕资源 if(atEndOfMedia){ mediaPlayer.seek(mediaPlayer.getStartTime()); atEndOfMedia = false; } mediaPlayer.play(); setIcon(playBT,pauseIcon,25); }else{ //当资源处于播放状态时 mediaPlayer.pause(); setIcon(playBT,playIcon,25); } }); } //设置停止按钮动作 private void setStopButton(){ stopBT.setOnAction((ActionEvent e )->{ if(media == null) return; mediaPlayer.stop(); setIcon(playBT,playIcon,25); } ); } //设置视频进度条动作 private void setProcessSlider(){ processSD.valueProperty().addListener(new ChangeListener<Number>(){ @Override public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) { if(processSD.isValueChanging()){ //加入Slider正在改变的判定,否则由于update线程的存在,mediaPlayer会不停地回绕 mediaPlayer.seek(duration.multiply(processSD.getValue()/100.0)); } } }); } //设置最大化按钮动作 public void setMaximizeButton(){ maxBT.setOnAction((ActionEvent e)->{ if(popup){ ((Stage)scene.getWindow()).setFullScreen(true); }else{ mediaPlayer.pause(); setIcon(playBT,pauseIcon,25); SimpleMediaPlayer player = SimpleMediaPlayer.popup(url); player.getController().getMediaPlayer().seek(this.mediaPlayer.getCurrentTime()); } }); } //设置音量按钮动作 private void setVolumeButton(){ volumeBT.setOnAction((ActionEvent e)->{ if(media == null) return; if(mediaPlayer.getVolume()>0){ volumeValue = mediaPlayer.getVolume(); volumeSD.setValue(0); setIcon(volumeBT,volOffIcon,25); }else{ mediaPlayer.setVolume(volumeValue); volumeSD.setValue(volumeValue * 100); setIcon(volumeBT,volOnIcon,15); } }); } //设置音量滑条动作 private void setVolumeSD(){ volumeSD.valueProperty().addListener(new ChangeListener<Number>(){ @Override public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) { mediaPlayer.setVolume(newValue.doubleValue()/100); } }); } //更新视频数据(进度条 、时间标签、音量条数据) protected void updateValues(){ if(processSD != null && timeLB!=null && volumeSD != null && volumeBT != null){ Platform.runLater(new Runnable(){ @Override public void run() { Duration currentTime = mediaPlayer.getCurrentTime(); timeLB.setText(formatTime(currentTime,duration)); //设置时间标签 processSD.setDisable(duration.isUnknown()); //无法读取时间是隐藏进度条 if(!processSD.isDisabled() && duration.greaterThan(Duration.ZERO) && !processSD.isValueChanging()){ processSD.setValue(currentTime.toMillis()/duration.toMillis() * 100); //设置进度条 } if(!volumeSD.isValueChanging()){ volumeSD.setValue((int)Math.round(mediaPlayer.getVolume() *100)); //设置音量条 if(mediaPlayer.getVolume() == 0){ //设置音量按钮 setIcon(volumeBT,volOffIcon,20); }else{ setIcon(volumeBT,volOnIcon,20); } } } }); } } //将Duration数据格式化,用于播放时间标签 protected String formatTime(Duration elapsed,Duration duration){ //将两个Duartion参数转化为 hh:mm:ss的形式后输出 int intElapsed = (int)Math.floor(elapsed.toSeconds()); int elapsedHours = intElapsed / (60 * 60); int elapsedMinutes = (intElapsed - elapsedHours *60 *60)/ 60; int elapsedSeconds = intElapsed - elapsedHours * 60 * 60 - elapsedMinutes * 60; if(duration.greaterThan(Duration.ZERO)){ int intDuration = (int)Math.floor(duration.toSeconds()); int durationHours = intDuration / (60 * 60); int durationMinutes = (intDuration - durationHours *60 * 60) / 60; int durationSeconds = intDuration - durationHours * 60 * 60 - durationMinutes * 60; if(durationHours > 0){ return String.format("%02d:%02d:%02d / %02d:%02d:%02d",elapsedHours,elapsedMinutes,elapsedSeconds,durationHours,durationMinutes,durationSeconds); }else{ return String.format("%02d:%02d / %02d:%02d",elapsedMinutes,elapsedSeconds,durationMinutes,durationSeconds); } }else{ if(elapsedHours > 0){ return String.format("%02d:%02d:%02d / %02d:%02d:%02d",elapsedHours,elapsedMinutes,elapsedSeconds); }else{ return String.format("%02d:%02d / %02d:%02d",elapsedMinutes,elapsedSeconds); } } } //为按钮获取图标 private void setIcon(Button button,String path,int size){ Image icon = new Image(path); ImageView imageView = new ImageView(icon); imageView.setFitWidth(size); imageView.setFitHeight((int)(size * icon.getHeight() / icon.getWidth())); button.setGraphic(imageView); //设置图标点击时发亮 ColorAdjust colorAdjust = new ColorAdjust(); button.setOnMousePressed(event -> { colorAdjust.setBrightness(0.5); button.setEffect(colorAdjust); }); button.setOnMouseReleased(event -> { colorAdjust.setBrightness(0); button.setEffect(colorAdjust); }); } public MediaPlayer getMediaPlayer(){ return this.mediaPlayer; } //设置关闭窗口时的动作,手动释放资源,回收内存 public void destroy(){ if(mediaPlayer.getStatus() == MediaPlayer.Status.PLAYING){ mediaPlayer.stop(); } mediaPlayer.dispose(); //释放meidaPlayer的Media资源 media = null; mediaPlayer = null; System.gc(); //通知JVM垃圾回收器 } //设置播放器尺寸 public void setSize(int width,int height){ currentWidth = width; currentHeight = height; setUISuitable(); } //UI控件自适应大小 private void setUISuitable(){ anchorPane.setPrefSize(currentWidth,currentHeight); anchorPane.setBottomAnchor(controlBar, 0.0); //设置控制条位置 anchorPane.setTopAnchor(mediaPane,((double)currentHeight - (double)currentWidth *(double)mediaHeight / (double)mediaWidth - 50)/2); //设置视频面板位置 mediaView.setFitWidth(currentWidth); //设置MediaView尺寸 mediaView.setFitHeight((double)currentWidth*(double)mediaHeight / (double)mediaHeight); controlBar.setPrefWidth(currentWidth); //设置工具条宽度 } public boolean getPopup(){ return this.popup; } }