javaFX系列:史上最简单的javaFX视频播放器实现 | 您所在的位置:网站首页 › javafx播放音乐 › javaFX系列:史上最简单的javaFX视频播放器实现 |
前言 本章接着之前的根据组件学习javaFX的系列教程,本章为javaFX视频播放器的简单实现。 javaFX结构组件 场景图(Scenen graph) 图形系统(Graphics System) Glass窗体工具包(Glass window toolkit) 多媒体和图形(media and images) web组件(web component) css样式 UI控件(UI controls) 布局(layout) 视觉特效(visual effects)参考 本章有且只参考了oracle javaFX官方文档: https://docs.oracle.com/javase/8/javafx/media-tutorial/overview.htm#JFXMD101 功能实现 完整的视频播放功能 开始播放 停止播放 暂停播放 音量调整 播放进度调整实现代码 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392/** * javaFX视频播放器测试 * 支持的视频格式列表: FLV container with MP3 and VP6 MP3 audio MPEG-4 container with either AAC, H.264, or both HTTP, FILE protocol support Progressive download Seeking Buffer progress Playback functions (Play, Pause, Stop, Volume, Mute, Balance, Equalizer) * @author eguid * */ public class JavaFxVideoPlayer extends Application{ public Scene scene;//场景 public MediaCtrl mc;//播放器控件 int sceneWidth,sceneHeight; public String src;//播放地址 public JavaFxVideoPlayer() { Console.log("创建"+this.getClass().getSimpleName()+"对象,顺序:2,当前线程: "+Thread.currentThread().getName()); } private void load(String src) { Console.log("初始化播放器,播放器播放地址:"+src); this.mc = new MediaCtrl(createMediaPlayer(src)); this.scene=new Scene(mc,sceneWidth,sceneHeight); } @Override public void init() throws Exception { src=getParam("src"); String width=getParam("width"); String height=getParam("height"); sceneWidth=Integer.valueOf(width); sceneHeight=Integer.valueOf(height); load(src); //与对象创建,start,stop方法不属于同一个线程 Console.log("执行了init初始化"+this.getClass().getSimpleName()+",顺序:3,当前线程: "+Thread.currentThread().getName()); // init方法是由javaFX-launcher线程执行的,也就是说,init中的初始化的数据,在start中使用可能会发生空指针 super.init(); } @Override public void stop() throws Exception { // TODO Auto-generated method stub Console.log("执行stop销毁"+this.getClass().getSimpleName()+"对象,顺序:5,当前线程: "+Thread.currentThread().getName()); super.stop(); } @Override public void start(Stage primaryStage) throws Exception { Console.log("初始化场景大小:"+sceneWidth+"x"+sceneHeight); //mc.videoWidth==null?sceneWidth:mc.videoWidth,mc.videoHeight==null?sceneHeight:mc.videoHeight Console.log(this.getClass().getSimpleName()+"开始显示窗口,顺序:4,当前线程:"+Thread.currentThread().getName()); primaryStage.setTitle("eguid最简单的javaFX播放器demo"); primaryStage.setScene(scene); primaryStage.setAlwaysOnTop(true);//窗口永远在最上层 primaryStage.requestFocus();//窗口获取焦点 primaryStage.setFullScreen(false);//全屏 // primaryStage.setOpacity(50);//透明度 primaryStage.setResizable(false);//窗口是否可调整大小 primaryStage.sizeToScene();//窗口大小适应场景大小 primaryStage.show();//显示,必须设置scene场景后才能调用 } /** * 添加显示组件 */ private void addView(Node node) { ((Group)scene.getRoot()).getChildren().add(node); } /** * 创建播放器窗口 * @param mediaPlayer * @return */ private MediaView createSimpleMediaPlayerView(MediaPlayer mediaPlayer) { MediaView view =new MediaView(mediaPlayer); view.setCache(false);//是否缓存 return view; } /** * 创建播放器 * @param src * @return */ private MediaPlayer createMediaPlayer(String src) { Media media=new Media(src);//创建媒体 //创建媒体播放器 MediaPlayer player=new MediaPlayer(media); //设置自动播放 // player.setAutoPlay(false);//默认是否自动播放 return player; } /** * 获取输出参数 * @param key * @return */ private String getParam(String key) { Map params=getParameters().getNamed(); return params.get(key); } static class MediaCtrl extends BorderPane{ public MediaPlayer mp;//播放器 public MediaView mv;//播放器显示组件 public HBox mb;//播放器控制面板 public Slider ts;//进度条 public Label pt;//播放时间显示 public Slider vs;//音量控制条 public Button playButton;//播放按钮 public Button stopButton;//停止按钮 public final boolean repeat = false;//循环播放 public boolean stopRequested = false; public boolean atEndOfMedia = false;//媒体播放是否结束 public Duration duration;//持续时长 public Integer videoWidth,videoHeight;//视频画面实际大小 public MediaCtrl(final MediaPlayer mp) { this.mp=mp; setStyle("-fx-background-color:#bfc2c7"); mv=new MediaView(mp); Pane mvPane = new Pane(); mvPane.getChildren().add(mv); mvPane.setStyle("-fx-background-color: black;"); setCenter(mvPane); BorderPane.setAlignment(mv, Pos.CENTER); //播放器控制面板 mb = new HBox(); mb.setAlignment(Pos.CENTER);//设置对齐方式:中间对齐 mb.setPadding(new Insets(5, 10, 5, 10));//设置内边距 BorderPane.setAlignment(mb, Pos.CENTER);//设置对其方式:中间对齐 //停止按钮 stopButton = new Button(""); mb.getChildren().add(stopButton); setBottom(mb); Label spacer = new Label(" "); mb.getChildren().add(spacer); //播放|暂停按钮 playButton = new Button("?"); mb.getChildren().add(playButton); setBottom(mb); Label spacer2 = new Label(" "); mb.getChildren().add(spacer2); //显示播放进度label Label timeLabel = new Label("播放进度: "); mb.getChildren().add(timeLabel); // 时间进度条 ts = new Slider(); HBox.setHgrow(ts,Priority.ALWAYS); ts.setMinWidth(50); ts.setMaxWidth(Double.MAX_VALUE); mb.getChildren().add(ts); pt = new Label(); pt.setPrefWidth(130); pt.setMinWidth(50); mb.getChildren().add(pt); // 显示音量Label Label volumeLabel = new Label("音量: "); mb.getChildren().add(volumeLabel); // 音量条 vs = new Slider(); vs.setPrefWidth(70); vs.setMaxWidth(Region.USE_PREF_SIZE); vs.setMinWidth(30); mb.getChildren().add(vs); initListeners(); } private void initListeners(){ stopButton.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { Console.log("停止播放"); mp.stop(); stopRequested = true;//播放结束 playButton.setText("?"); } }); //监听播放状态 playButton.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { Status status = mp.getStatus(); Console.log("当前播放状态:"+status); if (status == Status.UNKNOWN || status == Status.HALTED){ // don't do anything in these states return; } if (status == Status.PAUSED || status == Status.READY || status == Status.STOPPED){ // rewind the movie if we're sitting at the end if(stopRequested) { //已停止播放,不允许再播放 return; } Console.log("播放"); if (atEndOfMedia) { Console.log("播放结束,调整播放进度条"); mp.seek(mp.getStartTime()); atEndOfMedia = false; } mp.play(); } else { Console.log("暂停"); mp.pause(); } } }); //监听播放时间 mp.currentTimeProperty().addListener(new InvalidationListener() { @Override public void invalidated(Observable observable) { // TODO Auto-generated method stub updateValues(); } }); //监听设置播放操作 mp.setOnPlaying(new Runnable() { public void run() { if (stopRequested) { mp.pause(); stopRequested = false; } else { playButton.setText("||"); Media media=mp.getMedia(); videoWidth=media.getWidth(); videoHeight=media.getHeight(); Console.log("视频画面大小:"+videoWidth+"x"+videoHeight); double width=getScene().getWidth(); double height=getScene().getHeight(); Console.log("实际窗口大小:"+width+"x"+height); double scaleX=width/videoWidth+1,scaleY=(height-60)/videoHeight+1; Console.log("调整视频缩放,以适应窗口实际尺寸,缩放等级:"+scaleX+"x"+scaleY); mv.setScaleX(scaleX); mv.setScaleY(scaleY); mv.setSmooth(true); mv.setTranslateX(width/videoWidth/2); mv.setTranslateY(height/videoHeight/2); } } }); //监听暂停操作 mp.setOnPaused(new Runnable() { public void run() { System.out.println("onPaused"); playButton.setText("?"); } }); //监听视频开始加载状态 mp.setOnReady(new Runnable() { public void run() { Media media=mp.getMedia(); duration = media.getDuration(); updateValues(); } }); mp.setCycleCount(repeat ? MediaPlayer.INDEFINITE : 1); mp.setOnEndOfMedia(new Runnable() { public void run() { Console.log("播放结束"); if (!repeat) { playButton.setText("?"); stopRequested = true; atEndOfMedia = true; } } }); //监听时间进度条 ts.valueProperty().addListener(new InvalidationListener() { public void invalidated(Observable ov) { if (ts.isValueChanging()) { // multiply duration by percentage calculated by slider position mp.seek(duration.multiply(ts.getValue() / 100.0)); } } }); //监听音量设置 vs.valueProperty().addListener(new InvalidationListener() { public void invalidated(Observable ov) { if (vs.isValueChanging()) { mp.setVolume(vs.getValue() / 100.0); } } }); } /** * 更新时间 */ protected void updateValues() { if (pt != null && ts != null && vs != null) { Platform.runLater(new Runnable() { public void run() { Duration currentTime = mp.getCurrentTime(); pt.setText(formatTime(currentTime, duration)); ts.setDisable(duration.isUnknown()); if (!ts.isDisabled() && duration.greaterThan(Duration.ZERO)&& !ts.isValueChanging()) { ts.setValue(currentTime.divide(duration).toMillis()* 100.0); } if (!vs.isValueChanging()) { vs.setValue((int)Math.round(mp.getVolume() * 100)); } } }); } } private static String formatTime(Duration elapsed, Duration duration) { int intElapsed = (int)Math.floor(elapsed.toSeconds()); int elapsedHours = intElapsed / (60 * 60); if (elapsedHours > 0) { intElapsed -= elapsedHours * 60 * 60; } int elapsedMinutes = intElapsed / 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); if (durationHours > 0) { intDuration -= durationHours * 60 * 60; } int durationMinutes = intDuration / 60; int durationSeconds = intDuration - durationHours * 60 * 60 - durationMinutes * 60; if (durationHours > 0) { //Compile and Run the EmbeddedMedia //Controlling Media Playback 3-7 return String.format("%d:%02d:%02d/%d:%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("%d:%02d:%02d", elapsedHours, elapsedMinutes, elapsedSeconds); } else { return String.format("%02d:%02d",elapsedMinutes, elapsedSeconds); } } } } } 运行代码 1234567public static void main(String[] args) { Console.log("进入main方法,顺序:1,当前线程:"+Thread.currentThread().getName()); //https://media.w3.org/2010/05/sintel/trailer.mp4 //http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4 Application.launch(JavaFxVideoPlayer.class,new String[]{"--width=1280","--height=720","--src=http://localhost:81/big_buck_bunny.mp4"}); Console.log("结束main方法,顺序:6,当前线程:"+Thread.currentThread().getName()); }效果演示 |
CopyRight 2018-2019 实验室设备网 版权所有 |