JavaFX 簡単 NetBeans6.5 で My Application を作成 その10

4 3 月, 2009 (07:14) | OpenSource, Java

前回は、音楽を再生する簡単なアプリケーションの作成方法について、投稿いたしました。さて今回で、この JavaFX 関連トピックも、10投稿目を数えることとなったので、そろそろ今までご紹介させていただいたコンポーネントを組み合わせたマッシュアップでも作成してみることにしました。

とは言っても40代に突入した親父な頭では、なかなかクリエイティブな発想が乏しくなって来てしまっていて、「さて何作ろ「(゚~゚o) ? 」と悩み悩んだ結果、 BGM 付きの写真のスライドショーでも作ろうと思い立ち、早速トライしました。(若い人なら、もっとものすごいものが出てくるんでしょうね、如何せん親父な頭では、これが限界の為、なにとぞご容赦を・・・σ(^_^;)アセ)

と言う訳で、今回使用するコンポーネントは、以下のとおり :
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.animation.Timeline;
import javafx.animation.KeyFrame;
import javafx.animation.Interpolator;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
で、スライドショーを作るに当たって、ただ写真を切り替えるだけでは面白みに書けるので、写真がクロスフェードして次々に映し出されるようなものをと考え、 Scene の同一座標上に、2つの ImegeView を重ねて、交互に描画する作りにしました。

まずは描画するイメージ部分、その5のトピックにて、 Image のエレメント、 "url" には、 bind を使用できないこと、お伝えしました。そうした理由から、画像を切り替えるには、 Image ごと入れ替える必要があります。そのため、あらかじめ Image オブジェクトを複数格納した、配列変数を用意します。 code snipet は以下のとおり :
var imageList = [
  Image {
    url: "{__DIR__}head.jpg"
  },
  Image {
    url: "My flickr photo url1"
  },
          ・
          ・
          ・
  Image {
    url: "{__DIR__}fin.jpg"
  }
次に、 Timeline の KeyFrame 内で、 Image オブジェクトを入れ替える為の変数と、この Image を描画する為の、 ImageView の透過度を格納する為の変数を2つ用意します。
var image1: Image = imageList[0];
var image2: Image = imageList[1];

var opacity1: Number = 1.0;
var opacity2: Number = 0.0;
次に、マウスクリックイベントをハンドリングする為のフラグをひとつ設けます。
var isStarted: Boolean = false;そして、 BGM を奏でる為の MediaPlayer のインスタンスを格納する変数を設けます。コードについては、前回のトピでご紹介しておりますので、ここでは省略します。

ここまでできたら、いよいよ写真のクロスフェード部分の実装に入って行きます。写真のスクリーンインとスクリーンアウトは、 Timeline の中で、 KeyFrame に opacity を可変させるコードを実装します。まずは、 Timeline の出だしのコードから :
var timeline: Timeline = Timeline {
  repeatCount: 1
  keyFrames: [
    KeyFrame {
      time: 0s
      values: [
        opacity1 => 1.0 tween Interpolator.LINEAR,
        opacity2 => 0.0 tween Interpolator.LINEAR,
        image1 => imageList[0] tween Interpolator.LINEAR,
        image2 => imageList[1] tween Interpolator.LINEAR
      ]
      action: function() {
        musicPlayer.volume = 1.0;
        musicPlayer.play();
      }
    },
    KeyFrame {
      time: 3s
      values: [
        opacity1 => 0.0 tween Interpolator.LINEAR,
        opacity2 => 0.0 tween Interpolator.LINEAR,
        image1 => imageList[0] tween Interpolator.LINEAR,
        image2 => imageList[1] tween Interpolator.LINEAR
      ]
    },
    KeyFrame {
      time: 6s
      values: [
        opacity1 => 0.0 tween Interpolator.LINEAR,
        opacity2 => 1.0 tween Interpolator.LINEAR,
        image1 => imageList[0] tween Interpolator.LINEAR,
        image2 => imageList[1] tween Interpolator.LINEAR
      ]
    },
今回 RepeatCount には、 1 を指定しました。先頭の KeyFrame では、最初に描画する画像と、次にスクリーンインする、一枚目の写真を指定しています。そして、開始アクションにて、 MediaPlayer の volume に最大値を設定し、 play() を実行させる様にしています。2つ目の KeyFrame では、先頭に出て来た画像が、3秒後にスクリーンアウトするよう、 opacity に 0.0 を指定し、6秒後に、1枚目の画像がスクリーンインするように実装しています。ここから先は、各写真を4秒間描画した後、2秒間で次に描画する写真とクロスフェードする様実装して行きます。実装したコードは以下のとおり :
    KeyFrame {
      time: 10s
      values: [
        opacity1 => 0.0 tween Interpolator.LINEAR,
        opacity2 => 1.0 tween Interpolator.LINEAR,
        image1 => imageList[2] tween Interpolator.LINEAR,
        image2 => imageList[1] tween Interpolator.LINEAR
      ]
    },
    KeyFrame {
      time: 12s
      values: [
        opacity1 => 1.0 tween Interpolator.LINEAR,
        opacity2 => 0.0 tween Interpolator.LINEAR,
        image1 => imageList[2] tween Interpolator.LINEAR,
        image2 => imageList[1] tween Interpolator.LINEAR
      ]
    },
上記処理を、画像の枚数分繰り返します。そして締めくくりには、オープニングの時と同じ様に、最後の写真が3秒間でスクリーンアウトしされた後、更に3秒間で、最終画像をスクリーンインさせ、続けて最終画像をスクリーンアウトさせると共に、 BGM もフェードアウトする様に、ちょっと格好付けて実装してみました。(笑)実装コードは以下のとおり :
    KeyFrame {
      time: 148s
      values: [
        opacity1 => 1.0 tween Interpolator.LINEAR,
        opacity2 => 0.0 tween Interpolator.LINEAR,
        image1 => imageList[24] tween Interpolator.LINEAR,
        image2 => imageList[25] tween Interpolator.LINEAR
      ]
    },
    KeyFrame {
      time: 151s
      values: [
        opacity1 => 0.0 tween Interpolator.LINEAR,
        opacity2 => 0.0 tween Interpolator.LINEAR,
        image1 => imageList[24] tween Interpolator.LINEAR,
        image2 => imageList[25] tween Interpolator.LINEAR
      ]
    },
    KeyFrame {
      time: 154s
      values: [
        opacity2 => 1.0 tween Interpolator.LINEAR,
        image2 => imageList[25] tween Interpolator.LINEAR,
        musicPlayer.volume => 1.0
      ]
    },
    KeyFrame {
      time: 157s
      values: [
        opacity2 => 0.0 tween Interpolator.LINEAR,
        image2 => imageList[25] tween Interpolator.LINEAR,
      ]
    },
    KeyFrame {
      time: 160s
      values: [
        musicPlayer.volume => 0.0,
      ]
      action: function() {
        musicPlayer.stop();
        isStarted = false;
      }
    }
一番最後の 154 秒後にイベントを発生させる KeyFrame のところで、 MediaPlayer の volume に、再び最大値を指定しています。何故これが必要かと言うと、 Timeline 関連のトピを投稿した時にも、ご説明させていただきましたが、「 n 秒から nn 秒の間に、値をどれだけ変化させるか」、と言う指定が、 KeyFrame の values に指定された内容で、このアプリケーションでは、処理の最終プロセスで、 BGM の volume を 0 にする、と言う要件を実装しているため、最初に指定した KeyFrame の values で、 volume を最大値に設定し、 160 秒後の KeyFrame に到達するまでに、音が減衰していってしまい、不自然な動きなってしまわないようにするためです。そしていろいろ動かして試してみた結果、画像のスクリーンアウトより、ややディレイ気味に、 BGM がフェードアウトした方が、ちょっと良い感じだなと思ったので、敢えてフェードアウトのタイミングを送らせてみました。まぁこれは好みの問題と心得ますが・・・σ(^_^;)アセ

ここまで出来上がれば、9割方実装は完了です。後は Stage, Scene, content を順次実装して、必要なコードを実装すれば、完成となります。 Stage の実装コードは以下のとおり :
Stage {
  title: "Sun Tech Days 2008 Tokyo"
  scene: Scene {
    width: 500
    height: 375
    content: [
      ImageView {
        image: bind image1
        opacity: bind opacity1
        onMouseClicked: function( e: MouseEvent ):Void {
          if(isStarted) {
            musicPlayer.stop();
            timeline.pause();
            isStarted = false;
          } else {
            timeline.playFromStart();
            isStarted = true;
          }
        }
      },
      ImageView {
        image: bind image2
        opacity: bind opacity2
      }
    ]
  }
}
Scene のサイズは、 flickr の midium サイズに合わせて 500 × 375 にしてあります。そして再三書いて参りましたが、2つの ImageView を交互にスクリーンイン/アウトするように実装するため、 content [] には、2つの ImageView を実装しています。各 ImageView では、 KeyFrame のイベントに合わせて画像を入れ替えられる様に image: を bind しているのと、 KeyFrame で指定しているスクリーンアウトする為の opacity を bind しています。そして1つ目の ImageView に、マウスクリックイベントを実装し、画像パネルがクリックされたら、再生、一時停止、先頭からの再スタートを出来る様に実装しています。前述した、マウスクリックイベントをハンドリングする為のフラグ isStarted は、これら処理をする為に、ここで使われることになります。これでマッシュアップは全て完了です。

実行結果については以下のスクリーンキャストのとおりです。




※こちらのアプリケーションについても、前回同様、音楽コンテンツを含んでいるため、 Web への公開は、控えさせていただいています。誠に申し訳ありませんが、ご理解ください。

さて如何でしたでしょうか? もうちょっとひねれば、もっと良いものは出来る物と思われます。皆さんも、どこかにご旅行した時の思い出などを、こうした形で残すって言うの、なかなか良いのではないかと思います。オリジナリティあふれるスライドアルバム、是非皆さんも、トライして見てください (*`д´)b goo♪

Write a comment





*
画像に書かれた文字を入力してください

スパム対策用画像
ログインすると画像認証なしで投稿できます

ホットワード JavaFX 簡単 作成 前回
割引クーポンまとめ情報 - クー割