【Java】SwingとJavaFXの連携で動画再生

2018年2月22日

本稿は、JavaのSwingアプリケーション内でJavaFXと連携し、動画再生する方法を紹介します。

動画再生はゲームには必須ではありませんが、より高度なオープニングやエンディングを流したい場合は必要になってきます。

JavaFXはJava7の2から使えるようですがいろいろと準備などがいるらしいので、より簡単に使えるJava8以降を使用しましょう。

swingアプリ内でFXによる動画再生

JavaFXにはJComponentクラスを継承したJFXPanelというクラスがあります。

今回はそのクラスを継承し、動画再生パネルとしてクラス化します。

わざわざクラス化するのは動画再生が必要になれば、他の画面と同じようにパネルの差し替えのみで簡単に画面遷移させることができるようになるからです。

mp4(h264コーデック)は再生できますが、mpgやwmv、avi等は再生できませんでした。

テスト用に自作ゲームの動画を作成したのでこれを流すことにします。

テスト用の動画が欲しい方は右クリックしてダウンロードしてもらってもいいですし、ファイルを用意したくない方でオンラインの方ならMediaオブジェクトのインスタンス化を

new Media( "http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv" );

と指定することでoracleの用意してくれている動画をそのまま再生できます。

それではサンプルソースをご覧ください

import java.awt.Dimension;
import java.io.File;

import javax.swing.JFrame;

import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;

public class Test {
	public static void main(String[] args) throws Exception{
		TestWindow wnd = new TestWindow();

		//ムービー再生パネル
		//引数にはファイルのパスを指定してください。
		MoviePanel mp = new MoviePanel("sample.mp4");

		//JavaFX動画インスタンスとプレイヤーを取得
		Media meida = mp.getMedia();
		MediaPlayer player = mp.getPlayer();

		//読み込み待ち
		for(int i = 0;player.getStatus() != MediaPlayer.Status.READY;i++) {
			try {
				Thread.sleep(500);
			} catch (Exception e) {
			}
			if ( i > 20 ) throw new Exception("動画の読み込みに時間がかかりすぎたため中断しました。");
		}

		//読み込み完了後なら動画サイズを取得できる
		int videoW = meida.getWidth();
		int videoH = meida.getHeight();

		//MoviePanelのサイズを動画に合わせてJFrameに追加
		mp.setPreferredSize(new Dimension(videoW,videoH));
		wnd.add(mp);

		//JFrame側のパネルサイズを動画に合わせる
		wnd.getContentPane().setPreferredSize(new Dimension(videoW,videoH));

		//JFrameサイズをパネル全体が見えるサイズに自動調整
		wnd.pack();

		//中心に表示
		wnd.setLocationRelativeTo(null);

		wnd.setVisible(true);

		//動画の再生
		player.play();
	}
}
//テスト用Windowクラス
class TestWindow extends JFrame{
	TestWindow(){
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setResizable(false);
	}
}

//動画再生パネルクラス
class MoviePanel extends JFXPanel{
	Media media;
	MediaPlayer player;
	MoviePanel(String filePath){

		//JavaFXルートパネル
		StackPane root = new StackPane();

		// 動画ファイルのパスを取得
		File f = new File( filePath );

		// 動画再生クラスをインスタンス化
		media = new Media( f.toURI().toString() );
		player = new MediaPlayer(media);
		MediaView mediaView = new MediaView(player);
		root.getChildren().add(mediaView);

		//JavaFXScene
		Scene scene = new Scene( root );

		//JFXPanelにSceneをセット
		setScene(scene);
	}

	public Media getMedia() {
		return media;
	}

	public MediaPlayer getPlayer() {
		return player;
	}
}
実行結果

ざっとプログラムの流れを説明します。

重要なのはMoviePanelクラスの処理であり、まずMediaクラスで動画ファイルを読み込みます。

次に、読み込んでできたオブジェクトをMediaPlayerに渡し、PlayerをMediaViewに渡します。

MediaViewをJavaFXのパネルに追加して、swing連携用のJFXPanelに追加します。

これで後は、JFXPanelをJFrameに追加して、MediaPlayerのplayメソッドを呼び出せば再生されます。

ここまでが、重要な処理で、あとはmainにごじゃごじゃ処理を書いていますが、動画のサイズに合わせてウィンドウを表示する処理をしています。

読み込み待ちの処理は、コールバック指定できるメソッドがあったのですが、読み込みが早く済んでしまった場合に呼び出されなかったため、手動ですることにしました。

動画停止させる場合はMediaPlayerのstopメソッドを使うと良いです。ゲームで利用するならplayとstopだけ知っておけば問題ないでしょう。

MediaPlayerには音量設定や再生位置の指定をする機能もありますので興味があればドキュメントを読んでみてください。

ちなみに動画だけでなく、wavやmp3等も簡単に再生できるみたいなので非常に使いやすい。

JavaFXも勉強しようかなぁ・・・


参考サイト
http://krr.blog.shinobi.jp/javafx/javafx%E3%81%A7%E5%8B%95%E7%94%BB%E5%86%8D%E7%94%9F

JavaJavaFX

Posted by nompor