Eclipse Android〜Gluonでアプリを作る10:アニメーションの基本(パラレル遷移)〜

イントロダクション

前回はこちらのサイトを参考にして「パス遷移」をやりました。(参考サイトの呼び方)そして今回はその続き「パラレル遷移」をやります。

パラレル遷移は単純に複数のアニメーションを組み合わせてアニメーションするというものでした。

とりあえずは実行結果から

実装内容

public void start(Stage primaryStage) throws Exception {

    Group gp = new Group();

    // チュートリアルにあるコード

    final Rectangle rect = new Rectangle(60, 60);

   rect.setArcHeight(15);
 rect.setArcWidth(15);

    rect.setFill(Color.DARKBLUE);

    rect.setTranslateX(50);
    rect.setTranslateY(75);


    FadeTransition fadeTransition = 
 new FadeTransition(Duration.millis(3000), rect);
 fadeTransition.setFromValue(1.0f);

    fadeTransition.setToValue(0.3f);

    fadeTransition.setCycleCount(2);

    fadeTransition.setAutoReverse(true);

    TranslateTransition translateTransition =
   new TranslateTransition(Duration.millis(2000), rect);

    translateTransition.setFromX(50);

    translateTransition.setToX(350);

    translateTransition.setCycleCount(2);

    translateTransition.setAutoReverse(true);

    RotateTransition rotateTransition = 
    new RotateTransition(Duration.millis(3000), rect);
    rotateTransition.setByAngle(180f);

    rotateTransition.setCycleCount(4);

    rotateTransition.setAutoReverse(true);

    ScaleTransition scaleTransition = 
  new ScaleTransition(Duration.millis(2000), rect);
 scaleTransition.setToX(2f);
    scaleTransition.setToY(2f);
    scaleTransition.setCycleCount(2);
    scaleTransition.setAutoReverse(true);
    ParallelTransition parallelTransition = new ParallelTransition();   parallelTransition.getChildren().addAll(fadeTransition,  translateTransition,     rotateTransition,   scaleTransition   );
    parallelTransition.setCycleCount(Timeline.INDEFINITE);  parallelTransition.play();
    // シーンをステージに登録
    gp.getChildren().addAll(rect);
    Scene scene = new Scene(gp, 450, 450);
    primaryStage.setScene(scene);
    primaryStage.setTitle("Animation Basic3");
    primaryStage.show();
    }

今回はチュートリアルをコピペで変数名を多少修正してお終いだったので、まぁ楽でした。今までの実装を行なっていれば「こんな感じ」というのが掴めると思います。

<ソースの内容>

final Rectangle rect = new Rectangle(60, 60);
rect.setArcHeight(15);
rect.setArcWidth(15);
rect.setFill(Color.DARKBLUE);
rect.setTranslateX(50);
rect.setTranslateY(75);

毎度おなじみ、四角形クラス(Rectangle)です。これを縦横60の大きさで作成します。そしてArcHeight, ArcWidthを設定します。(リンクはJavaDocです)

JavaDocの説明は「矩形の4隅にある弧の水平方向の直径を定義します。円弧の幅と円弧の高さの両方のプロパティが0.0より大きい場合にのみ、矩形の角が丸くなります。」とありました。四角形の先っちょが丸くなるんですね(笑)

そしてFill()は色を指定します。setTranslateは位置を指定します。

FadeTransition fadeTransition = 
  new FadeTransition(Duration.millis(3000), rect);

fadeTransition.setFromValue(1.0f);
fadeTransition.setToValue(0.3f);
fadeTransition.setCycleCount(2);
fadeTransition.setAutoReverse(true);

これは初めの方に出てきたアニメーションです。色をフェードアウト・インするアニメーションです。

TranslateTransition translateTransition =
 new TranslateTransition(Duration.millis(2000), rect);
translateTransition.setFromX(50);
translateTransition.setToX(350);
translateTransition.setCycleCount(2);
translateTransition.setAutoReverse(true);

TranslateTransitionクラスを使用した、四角形の移動アニメーションです。

X座標が「50」〜「350」の間を移動します。JavaDocの説明は「このアニメーションのサイクル数を定義します。アニメーションを無限に繰り返す場合はcycleCountをINDEFINITEに設定できます、それ以外の場合は0より大きくする必要があります。」です。

そして最後のsetAutoReverseは名前から想像できますね。※動きからも見て取れると思います。

ちょっと余談ですが、「想像できますね」という記載をしましたが、コーディングをするときのメソッド名をつけるとき、変数名をつけるとき、処理の内容が「簡単に想像できる」というのはとても大切なことです。これがわかりづらいと結局ソースの中身を追いかけることになります。

そして、「RotateTransition」「ScaleTransition」は説明を割愛します。

最後のクラスです。

ParallelTransition parallelTransition = new ParallelTransition();

parallelTransition.getChildren().addAll(
fadeTransition,
translateTransition,
rotateTransition,
scaleTransition
);

本題の「パラレル遷移」クラスです。今まで作成したアニメーションクラスを登録しています。これでアニメーションを複合して実行しています。

最後に。。。

ここまでで、とりあえずはチュートリアルを止めようと思っております。

なぜかというと「じゃんけんゲーム」で必要なアニメーションの作成ができるようになったからです。つまり今回の「パラレル遷移」をじゃんけんゲームで使用します。ちょいとした戦いになりそうですが。。。

追加でやって見た

四角をコインのように回転してみる。

追加で修正した部分は以下の「RotateTransition」の部分です。

RotateTransition rotateTransition = 
 new RotateTransition(Duration.millis(800), rect);
rotateTransition.setAxis(new Point3D(0, 10, 0));

rotateTransition.setByAngle(360f);
rotateTransition.setInterpolator(Interpolator.TANGENT(Duration.millis(100), 10000.0));

rotateTransition.setCycleCount(RotateTransition.INDEFINITE);

コンストラクタに渡している「Duration」が回転のスピードになります。値が少ないほど回転が早い。

そしてPoint3Dで回転する方向を指定します。今回は横軸(Y軸)方向に回転するのでYの値のみを設定しています。

そして参考サイトはこちら(Java Code Examples)

でわでわ。。。


関連ページ一覧

  1. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫:Label〜
  2. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫2:Label〜
  3. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫3:Button〜
  4. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫4:RadioButton〜
  5. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫5:ToggleButton〜
  6. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫6:CheckBox〜
  7. Eclipse Android〜Gluonでアプリを作る6: アニメーションを作る準備〜
  8. Eclipse Android〜Gluonでアプリを作る7: 木琴アプリの解析〜
  9. Eclipse Android〜Gluonでアプリを作る8:アニメーションの基本(遷移)〜
  10. Eclipse Android〜Gluonでアプリを作る9:アニメーションの基本(パス遷移)〜
  11. Eclipse Android〜Gluonでアプリを作る10:アニメーションの基本(パラレル遷移)〜


Eclipse Android〜Gluonでアプリを作る9:アニメーションの基本(パス遷移)〜

イントロダクション

前回はこちらのサイトを参考にして「フェード遷移」をやりました。(参考サイトの呼び方)そして今回はその続き「パス遷移」をやります。

「パス遷移」とはPath(線)を引いて、そのパスの端から端まで移動するというものです。参考サイトより画像を引用します。

ちなみにこのPath(クラス)を利用すると文字列をオシャレにデコレーションできます。

こちらのサイトから失敬しました。

そんなわけで、今日は「パス遷移」をやります。

<ソースコード>

@Override
public void start(Stage primaryStage) throws Exception {
    Group gp = new Group();
    // チュートリアルにあるコード
    final Rectangle rect = new Rectangle(60, 60);
    rect.setArcHeight(50);
    rect.setArcWidth(50);
    rect.setFill(Color.ORANGE);
    Path path = new Path();
    path.getElements().add(new MoveTo(30,30));
    path.getElements().add(new CubicCurveTo(380, 0, 380, 120, 200, 120));
    path.getElements().add(new CubicCurveTo(0, 120, 0, 240, 380, 240));
    PathTransition pathTransition = new PathTransition();
    pathTransition.setDuration(Duration.millis(10000));
    pathTransition.setPath(path);
    pathTransition.setNode(rect);
    pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
    pathTransition.setCycleCount(Timeline.INDEFINITE);
    pathTransition.setAutoReverse(true);
    pathTransition.play();
    // シーンをステージに登録
    gp.getChildren().addAll(rect, path);
    Scene scene = new Scene(gp, 450, 450);
    primaryStage.setScene(scene);
    primaryStage.setTitle("Animation Basic2");
    primaryStage.show();
}
  1. 四角形を描き(60 x 60のオレンジ色でちょいと角を丸くする)
  2. アニメーションするための線(Path)を描き
  3. アニメーションする時間を設定(setDuration())
  4. PathTransitionに線(Path)と四角形を登録する※「ORTHOGONAL_TO_TANGENT」の意味はよくわかりませんでした。

  5. そしてINDEFINITE「stop()メソッドを呼び出すまで無限に繰り返すアニメーションを指定」
  6. オートリバース(自動繰り返し)をTrueで設定(自動で繰り返し動く)

とこんな感じで実装してありました。

でわでわ。。。



Eclipse Android〜Gluonでアプリを作る8:アニメーションの基本(遷移)〜

イントロダクション

今回からアニメーションの学習に入ります。参考にするサイトはこちらです。

https://docs.oracle.com/javase/jp/8/javafx/visual-effects-tutorial/basics.htm

今までのJavaFXをやってきたなら、楽勝だと思います。ちょっとわかりづらいのが、Durationクラスと、FadeTransitionクラスだと思います。リンク先のJavaDocにもあるように、Durationで時間(間隔)を指定してFadeTransitionでフェードさせています。「百聞は一見に〜」ということで。。。こんな感じです。

<ソース>

@Override
public void start(Stage primaryStage) throws Exception {
    Group gp = new Group();
    // チュートリアルにあるコード
    final Rectangle rect1 = new Rectangle(10, 10, 100, 100);
    rect1.setArcHeight(20);
    rect1.setArcWidth(20);
    rect1.setFill(Color.RED);
    FadeTransition ft = new FadeTransition(Duration.millis(3000), rect1);
    ft.setFromValue(1.0);
    ft.setToValue(0.1);
    ft.setCycleCount(Timeline.INDEFINITE);
    ft.setAutoReverse(true);
    ft.play();

    // シーンをステージに登録
    gp.getChildren().addAll(rect1);
    Scene scene = new Scene(gp, 450, 450);
    primaryStage.setScene(scene);
    primaryStage.setTitle("Animation Basic1");
    primaryStage.show();
}

特に調べる必要はないと思ったので今回はここまでにします。

でわでわ。。。

関連ページ

  1. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫:Label〜
  2. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫2:Label〜
  3. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫3:Button〜
  4. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫4:RadioButton〜
  5. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫5:ToggleButton〜
  6. JavaFX チュートリアル〜今度こそ、初めてでも大丈夫6:CheckBox〜
  7. Eclipse Android〜Gluonでアプリを作る6: アニメーションを作る準備〜
  8. Eclipse Android〜Gluonでアプリを作る7: 木琴アプリの解析〜



Eclipse Android〜Gluonでアプリを作る7: 木琴アプリの解析〜

イントロダクション

前回は、チュートリアルの入り口、概要について記載しいました。アニメーションなのに3D描画から始めているのでちょっとずれている感じがします。

なのでタイトルを変更しました、木琴アプリの解析をやります。元のソース、音データはこちらからダウンロードできます。

そして、ソースを読んで見た内容にコメントをつけました。※Gitにアップしたソースです。

そして、ソースを読んでいてわからない部分もありました。その部分のコードを一度コメントアウトして実行して見ます。ちなみに参考サイトはこちらです。

https://docs.oracle.com/javase/jp/8/javafx/visual-effects-tutorial/transformation-types.htm

rectangleGroup(Group)を追加しないパターン

251行目、

setCamOffsetを設定しない(シーンサイズ半分、分の位置をずらさない)

338行目をコメントアウト:

340行目をコメントアウト:

341行目をコメントアウト:

342行目をコメントアウト:

そして255行目以降の「scene.setOn〜」はボタン押下などのアクション処理の実装になります。なので今は置いておきます。

とりあえずは、理解の整理

  1. Groupクラスを継承した「Cam」クラスをフィールド変数の「camOffset」「cam」で使用している。
  2. ステージ(Stageクラス)にカメラ(PerspectiveCameraクラス)を設定
  3. Groupクラスを継承した「Cube」クラスを木琴のバー、土台として使用(内訳としてはRectangleクラスを「面」として使用)
  4. 木琴は「cam(Group)」に追加
  5. 「cam」は「camOffset」に追加、「camOffset」をステージに追加

そして、「A」「F」のボタンを押下すると木琴の位置が変わります。そして「スペース」で全画面表示になります。注目ポイントは305行目〜328行目。

アニメーションに関連深そうなのはボタン押下時に木琴を移動する部分が怪しいです。

インナークラスのコードを記載します。

<Camクラス>

class Cam extends Group {
    Translate t  = new Translate();
    Translate p  = new Translate();
    Translate ip = new Translate();
    Rotate rx = new Rotate();
    { rx.setAxis(Rotate.X_AXIS); }
    Rotate ry = new Rotate();
    { ry.setAxis(Rotate.Y_AXIS); }
    Rotate rz = new Rotate();
    { rz.setAxis(Rotate.Z_AXIS); }
    Scale s = new Scale();
    public Cam() { super(); getTransforms().addAll(t, p, rx, rz, ry, s, ip); }
}

<Cubeクラス>

public class Cube extends Group {
    final Rotate rx = new Rotate(0, Rotate.X_AXIS);
    final Rotate ry = new Rotate(0, Rotate.Y_AXIS);
    final Rotate rz = new Rotate(0, Rotate.Z_AXIS);
    public Cube(double size, Color color, double shade) {
        getTransforms().addAll(rz, ry, rx);

//          back face
        Rectangle backFace = new Rectangle(size,size);
        backFace.setFill(color.deriveColor(0.0, 1.0, (1 - 0.5*shade), 1.0));
        backFace.setTranslateX(-0.5*size);
        backFace.setTranslateY(-0.5*size);
        backFace.setTranslateZ(-0.5*size);

        // bottom face
        Rectangle bottomFace = new Rectangle(size,size);
        bottomFace.setFill(color.deriveColor(0.0, 1.0, (1 - 0.4*shade), 1.0));
        bottomFace.setTranslateX(-0.5*size);
        bottomFace.setTranslateY(0);
        bottomFace.setRotationAxis(Rotate.X_AXIS);
        bottomFace.setRotate(90);

//          right face
        Rectangle rightFace = new Rectangle(size,size);
        rightFace.setFill(color.deriveColor(0.0, 1.0, (1 - 0.3*shade), 1.0));
        rightFace.setTranslateX(-1*size);
        rightFace.setTranslateY(-0.5*size);
        rightFace.setRotationAxis(Rotate.Y_AXIS);
        rightFace.setRotate(90);

//            leftFace
        Rectangle leftFace = new Rectangle(size,size);
        leftFace.setFill(color.deriveColor(0.0, 1.0, (1 - 0.2*shade), 1.0));
        leftFace.setTranslateX(0);
        leftFace.setTranslateY(-0.5*size);
        leftFace.setRotationAxis(Rotate.Y_AXIS);
        leftFace.setRotate(90);

//            topFace
        Rectangle topFace = new Rectangle(size,size);
        topFace.setFill(color.deriveColor(0.0, 1.0, (1 - 0.1*shade), 1.0));
        topFace.setTranslateX(-0.5*size);
        topFace.setTranslateY(-1*size);
        topFace.setRotationAxis(Rotate.X_AXIS);
        topFace.setRotate(90);

//          frontFace
        Rectangle frontFace = new Rectangle(size,size);
        frontFace.setFill(color);
        frontFace.setTranslateX(-0.5*size);
        frontFace.setTranslateY(-0.5*size);
        frontFace.setTranslateZ(-0.5*size);

        getChildren().addAll(backFace, bottomFace, rightFace, leftFace, topFace,frontFace);

    }
}

これで大分処理の概要が見えてきたと思います。(自分は見えてきました。)

【補足】

  1. Rectangleは四角を表現するクラスです。
  2. Rotateは回転を表現するクラスです。
  3. Boundsは境界を示すために使用されるクラスです。
  4. AudioClipは音データを扱うためのクラスです。

そして、最後にチュートリアルにある「スケーリングの処理」を302行目に追加します。チュートリアルの「例2-3 スケーリング」にあるコードを追加します。

最終的なコードはこちらです。

次回はついにアニメーションにてが届く



Eclipse Android〜Gluonでアプリを作る6: アニメーションを作る準備〜

イントロダクション

前回までは、とりあえず動くところまで作りました。概要は以下の通りです。

  1. ゲームのタイトル表示
  2. ゲームの開始画面表示
  3. 「じゃんけん」の開始ボタン押下後の処理

「3」の部分で開始ボタンを押下後にイメージを表示して終了している状態で前回の作業を終わりました。

ここからは、プログラムでのアニメーション作成方法に注目します。

アニメーション作成の前に

参考にするサイトはこちらです。Oracleのチュートリアルになります。

  1. 変換の概要:transformations.zipリンクよりサンプルコードをダウンロードできます。
  2. このzipファイルをダウンロード、展開して(Eclipse上では)下のようにファイルを配置します。
    展開後のファイル →
    Eclipseに配置 → 
  3. とりあえず、プログラムを実行してみます。

おー素晴らしい!やはり操作して音が出ると違います。

本題

このコードを解析して中身を理解します。以前3次元表現(描画)に挑戦したけどうまくいかなかったので、自分自身ここで問題を解決したいと思っています。

1 変換の概要

サンプル・ソースコード(Gitにアップロードしています)をダウンロードできます。そして「以下の変換について記載してますよ」ということが書いてありました。

  1. 平行移動
  2. 回転
  3. スケーリング
  4. 変形

そして、次のトピックへ進む前にサンプルコードの内容を(大雑把に)理解します。

【前提】

  1. JavaFXを起動する部分(Applicationクラスの継承とMainメソッドの実装)は割愛します。よくわからない場合はここのページを読み返してみてください(それでもわからない場合は実行してみてください)
  2. サンプルソースは、ダウンンロードするソースが1ファイルで良いようにまとめてあります。1クラス1ファイルになっていないので注意が必要です。
    (注)クラスの中に作成するクラス(インナークラス)に「Camクラス」「Cubeクラス」を実装しています。

ソース解析

実際のソースは、結構長いのでこちらを参照してください。(サンプルソースのリンクも同じ場所を参照しています)

まずはクラス構成から見ていきます。

1. インナークラス

大元のクラスは「Xylophone」クラスです、そしてこのクラスにインナークラスが下のようなクラスが2つあります。

  1. Camクラス 
  2. Cubeクラス 

「class」の左側に「public」がついているものと、ついていないものがありますが、これはフィールド変数と同様に

「class Cam」はパッケージ内でのみ使用、参照が可能なアクセス修飾子(何もない)状態を示します。

「public class Cube」はクラスの外部からも、全ての場所から参照することができます。(Xylophone.Cubeのような形で参照する)

しかし、インナークラスは「1クラス1ファイル」の作り方からは逸脱するのであまり使用しません。使用するのは以下のような場合のみです。

対象のクラスからのみ使用される(CubeがXylophneクラスからのみ使用される)

  1. start()メソッドを見る

JavaFXアプリケーションの場合は必ず「Application」クラスを継承したクラスを実装します。そしてこのクラスには「start()」メソッドを実装する(実装することを強制している)ので必ず実装します。

つまり、必ず動くメソッドということです。見ていきます。

フィールド変数に「Cam」クラスが2つあります。

このクラスは、位置と回転を制御するための仕組みがついています。

class Cam extends Group {
    Translate t  = new Translate();
    Translate p  = new Translate();
    Translate ip = new Translate();
    Rotate rx = new Rotate();
    { rx.setAxis(Rotate.X_AXIS); }
    Rotate ry = new Rotate();
    { ry.setAxis(Rotate.Y_AXIS); }
    Rotate rz = new Rotate();
    { rz.setAxis(Rotate.Z_AXIS); }
    Scale s = new Scale();
    public Cam() { super(); getTransforms().addAll(t, p, rx, rz, ry, s, ip); }
}

「Transrate」クラスは位置を管理するため、「Rotate」クラスは回転を管理するためのクラスです。

そして、赤い字で記載した部分に関してフィールド変数と同様に処理を実装するためのスコープ("{", "}")です。これを外すとエラーになります。

本来はメソッドを作成する方が良いのでしょうが、これ以外に処理がないのでここに作成したようです。

そして、ポイントは「Group」クラスを継承しているというところです。

つまり「Group」クラスを拡張しているので細かい処理は全て親クラス(Group)に実装してあるものを使用します。必要に応じてメソッドをオーバーライド、追加の実装を行います。

とりあえずは、キリが良いので今回はここまでにします。

でわでわ。。。



JavaFX チュートリアル〜今度こそ、初めてでも大丈夫6:CheckBox〜

イントロダクション

以前記載した記事で「初めてでも大丈夫」などと記載していましたが、ちょっと「危ういな」と思いチュートリアルをやってみようとなりました。

今回はチェックボックスの表示をやります。

チュートリアル

ここのページを、戦国Xサラの要領でガンガン斬り伏せながらやっていきます。

<チュートリアル>

基本のコード

/**
 * OracleのJavaFXチュートリアル。
 * ToggleButton表示します。
 * JavaDocです。このクラスは「@see」に記載しているサイトの
 * チュートリアルをやります。このクラスではLabelクラスの使用法を実行します。
 * 
 * @author takunoji
 * @see https://docs.oracle.com/javase/jp/8/javafx/user-interface-tutorial/checkbox.htm#CHDFEJCD
 * 2019/03/14
 */
public class Lv5_CheckBox extends Application {

	/**
	 * このメソッドは、Applicationクラス(JavaFXのフレームワーク部品)
	 * のメソッドをオーバーライドする。
	 * {@link Application#launch(String...)}から呼び出される。
	 */
	@Override
	public void start(Stage primaryStage) throws Exception {
		// チュートリアルの乗っていない部分
		Group group = new Group();
		VBox virtical = new VBox();
		HBox horizonal = new HBox();

		/* チュートリアルにあるコード */
		//A checkbox without a caption
		CheckBox cb1 = new CheckBox();
		//A checkbox with a string caption
		CheckBox cb2 = new CheckBox("Second");

		cb1.setText("First");
		cb1.setSelected(true);

		// Groupにチェックボックスを追加する
		group.getChildren().addAll(cb1, cb2);
		// チュートリアルでは省略されている
		virtical.getChildren().addAll(cb1, cb2);
		// チェックボックスの表示領域
		horizonal.getChildren().add(virtical);
		// イメージの表示領域
		Label iconSpace = new Label("Icon Space");
		iconSpace.setBackground(new Background(new BackgroundFill(Color.BLACK, new CornerRadii(5), Insets.EMPTY)));
		horizonal.getChildren().add(iconSpace);
		group.getChildren().add(horizonal);

		// 毎度おなじみのコード(この部分はだいたい同じになる)
		Scene scene = new Scene(group, 300, 300);
		primaryStage.setScene(scene);
		primaryStage.setTitle("チュートリアル6");
		primaryStage.show();
	}

	/**
	 * メインメソッド。
	 * Apllicationクラスのlaunchメソッドを呼び出す。
	 * 
	 * @param args プログラム引数
	 */
	public static void main(String[] args) {
		launch(args);
	}
}

<実行結果>

この基本のコードを基準にします。

このコードは単純にチェックボックスと、イメージを表示するための背景ラベルを表示します。処理を説明すると以下のようになります。

  1. Groupを使用して最終的に表示するコンテナを作成します。
  2. VBoxで縦、HBoxで横のレイアウト用コンテナを作成。
  3. CheckBoxを2つ作成し、FirstとSecondと名前をつけます。
  4. Firstのチェックボックスに選択済みフラグをTrueに設定します。

そして作成したコンポーネント(画面の部品)をGroup(コンテナ)へ追加して表示しています。

 

そして最終的にできたコードです。

/**
 * このメソッドは、Applicationクラス(JavaFXのフレームワーク部品)
 * のメソッドをオーバーライドする。
 * {@link Application#launch(String...)}から呼び出される。
 */
@Override
public void start(Stage primaryStage) throws Exception {
	// チュートリアルの乗っていない部分
	Group group = new Group();
	VBox virtical = new VBox();
	HBox horizonal = new HBox();

	/* チュートリアルにあるコード */
	//A checkbox without a caption
	CheckBox cb1 = new CheckBox();
	//A checkbox with a string caption
	CheckBox cb2 = new CheckBox("Second");

	cb1.setText("First");
	cb1.setSelected(true);

	// CheckBoxの動きの設定
	final String[] names = new String[]{"ore", "min", "twit"};
	final Image[] images = new Image[names.length];
	final ImageView[] icons = new ImageView[names.length];
	final CheckBox[] cbs = new CheckBox[names.length];

	// イメージ用のグループ
	Group gp = new Group();
	for (int i = 0; i < names.length; i++) {
	    final Image image = images[i] =
	        new Image("/" + names[i] + ".png");
	    final ImageView icon = icons[i] = new ImageView();
	    gp.getChildren().add(icon);
	    final CheckBox cb = cbs[i] = new CheckBox(names[i]);
	    cb.selectedProperty().addListener(
	        (ObservableValue<? extends Boolean> ov,
	            Boolean old_val, Boolean new_val) -> {
	                icon.setImage(new_val ? image : null);
	    });
	    virtical.getChildren().add(cb);
	}
	// Groupを追加する
//		group.getChildren().addAll(cb1, cb2);
	// チュートリアルでは省略されている
	virtical.getChildren().addAll(cb1, cb2);
	// チェックボックスの表示領域
	horizonal.getChildren().add(virtical);
	// イメージの表示領域
	Label iconSpace = new Label("Icon Space");
	iconSpace.setBackground(new Background(new BackgroundFill(Color.BLACK, new CornerRadii(5), Insets.EMPTY)));
	horizonal.getChildren().add(gp);
	group.getChildren().add(horizonal);

	// 毎度おなじみのコード(この部分はだいたい同じになる)
	Scene scene = new Scene(group, 300, 300);
	primaryStage.setScene(scene);
	primaryStage.setTitle("チュートリアル6");
	primaryStage.show();
}

チュートリアルに乗っている部分をコピーしています。

実行結果は以下のようになります。

イベント処理を追加するときは「〜Property」を使用するようですね(笑)



JavaFX チュートリアル〜今度こそ、初めてでも大丈夫5:ToggleButton〜

イントロダクション

以前記載した記事で「初めてでも大丈夫」などと記載していましたが、ちょっと「危ういな」と思いチュートリアルをやってみようとなりました。

今回はラジオボタンの表示をやります。

チュートリアル

ここのページを、戦国Xサラの要領でガンガン斬り伏せながらやっていきます。

<チュートリアル>

基本のコード(ちょっとダメなコード)

public class Lv4_ToggleButton extends Application {

	/**
	 * このメソッドは、Applicationクラス(JavaFXのフレームワーク部品)
	 * のメソッドをオーバーライドする。
	 * {@link Application#launch(String...)}から呼び出される。
	 */
	@Override
	public void start(Stage primaryStage) throws Exception {
		// チュートリアルの乗っていない部分
		Group group = new Group();

		// トグルグループ
		ToggleGroup toggleGroup = new ToggleGroup();

		ToggleButton tb1 = new ToggleButton("Minor");
		tb1.setToggleGroup(toggleGroup);

		ToggleButton tb2 = new ToggleButton("Major");
		tb2.setToggleGroup(toggleGroup);

//		Image image = new Image(getClass().getResourceAsStream("icon.png"));
		ToggleButton tb3 = new ToggleButton ("Critical");
		tb3.setToggleGroup(toggleGroup);

//		// 横のレイアウト
//		HBox lineLayout = new HBox();
//		lineLayout.getChildren().addAll(tb1, tb2, tb3);
		
		// Groupを追加する
		group.getChildren().addAll(tb1, tb2, tb3);
		// チュートリアルでは省略されている
		Scene scene = new Scene(group, 300, 300);
		primaryStage.setScene(scene);
		primaryStage.setTitle("チュートリアル4");
		primaryStage.show();
	}

	/**
	 * メインメソッド。
	 * Apllicationクラスのlaunchメソッドを呼び出す。
	 * 
	 * @param args プログラム引数
	 */
	public static void main(String[] args) {
		launch(args);
	}
}

前回と同様に、打面な原因は表示結果にあります。

トグルボタンが重なっています。。。なので、下の様に「横のレイアウト」を追加します。

// 横のレイアウト
HBox lineLayout = new HBox();
lineLayout.getChildren().addAll(tb1, tb2, tb3);

// Groupを追加する
group.getChildren().addAll(lineLayout);

こんな感じで表示されます。「横のレイアウト」の存在意義が少し見えてきたかと思いますがいかがでしょうか?

そして、下の部分に色をつけた四角(Rect)を設定し、簡単なアクション(イベント処理)を追加します。

@Override
public void start(Stage primaryStage) throws Exception {
	// チュートリアルの乗っていない部分
	Group group = new Group();

	// トグルグループ
	ToggleGroup toggleGroup = new ToggleGroup();

	ToggleButton tb1 = new ToggleButton("Minor");
	tb1.setToggleGroup(toggleGroup);

	ToggleButton tb2 = new ToggleButton("Major");
	tb2.setToggleGroup(toggleGroup);

	ToggleButton tb3 = new ToggleButton ("Critical");
	tb3.setToggleGroup(toggleGroup);

	// ユーザーデータを追加
	tb1.setUserData(Color.LIGHTGREEN);
	tb2.setUserData(Color.LIGHTBLUE);
	tb3.setUserData(Color.SALMON);
	// 四角の領域
	Rectangle rect = new Rectangle();
	rect.setHeight(50);
	rect.setFill(Color.WHITE);
	rect.setStroke(Color.DARKGRAY);
	rect.setStrokeWidth(2);
	rect.setArcHeight(10);
	rect.setArcWidth(10);
	// 横のレイアウト
	HBox lineLayout = new HBox();
	lineLayout.getChildren().addAll(tb1, tb2, tb3);
	// 縦のレイアウト
	VBox vbox = new VBox();
	vbox.getChildren().add(lineLayout);
	vbox.getChildren().add(rect);

	// トグルボタンのイベント処理
	toggleGroup.selectedToggleProperty().addListener(
			(ObservableValue<? extends Toggle> ov, Toggle oldToggle, Toggle newToggle) -> {
				System.out.println(lineLayout.getWidth());
				rect.setWidth(lineLayout.getWidth());
				if (newToggle == null) {
					System.out.println("null: ");
					rect.setFill(Color.WHITE);
				} else {
					System.out.println("!= null: ");
					rect.setFill((Color) toggleGroup.getSelectedToggle().getUserData());
				}
	});
	// Groupを追加する
	group.getChildren().addAll(vbox);
	// チュートリアルでは省略されている
	Scene scene = new Scene(group, 300, 300);
	// ここでサイズを指定する
	vbox.setPrefWidth(scene.getWidth());
	rect.setWidth(scene.getWidth());
	rect.setHeight(scene.getHeight());
	primaryStage.setScene(scene);
	primaryStage.setTitle("チュートリアル4");
	primaryStage.show();
}

画面の上部にある「トグルボタン」が3つあります、

// トグルグループ
ToggleGroup toggleGroup = new ToggleGroup();

ToggleButton tb1 = new ToggleButton("Minor");
tb1.setToggleGroup(toggleGroup);

ToggleButton tb2 = new ToggleButton("Major");
tb2.setToggleGroup(toggleGroup);

ToggleButton tb3 = new ToggleButton ("Critical");
tb3.setToggleGroup(toggleGroup);

このボタンに「UserDdata」を設定して置き、

// ユーザーデータを追加
tb1.setUserData(Color.LIGHTGREEN);
tb2.setUserData(Color.LIGHTBLUE);
tb3.setUserData(Color.SALMON);

初期表示の四角(Rect)を表示します。(色は白なので表示結果がよく分かりません。。。すんません。。。)

// 四角の領域
Rectangle rect = new Rectangle();
rect.setHeight(50);
rect.setFill(Color.WHITE);
rect.setStroke(Color.DARKGRAY);
rect.setStrokeWidth(2);
rect.setArcHeight(10);
rect.setArcWidth(10);

トグルボタンが押下されたときに「UserData」を取得して何色の四角「Rect」に値設定しています。

// トグルボタンのイベント処理
toggleGroup.selectedToggleProperty().addListener(
		(ObservableValue<? extends Toggle> ov, Toggle oldToggle, Toggle newToggle) -> {
			System.out.println(lineLayout.getWidth());
			rect.setWidth(lineLayout.getWidth());
			if (newToggle == null) {
				System.out.println("null: ");
				rect.setFill(Color.WHITE);
			} else {
				System.out.println("!= null: ");
				rect.setFill((Color) toggleGroup.getSelectedToggle().getUserData());
			}
});

ちょっと長いので分解して内容を記載します。トグルグループに選択時のイベントを追加します。〜Propertyで設定できる様です。

toggleGroup.selectedToggleProperty().addListener(

そして、イベントの処理内容を記載します。

(ObservableValue<? extends Toggle> ov, Toggle oldToggle, Toggle newToggle) -> { ... }

引数が3つあります。「ObservableValue<? extends Toggle>」と「Toggle1」「Toggle2」です、これを受けて(引数にして)以下のイベント処理を実装しています。

System.out.println(lineLayout.getWidth());
rect.setWidth(lineLayout.getWidth());
if (newToggle == null) {
	System.out.println("null: ");
	rect.setFill(Color.WHITE);
} else {
	System.out.println("!= null: ");
	rect.setFill((Color) toggleGroup.getSelectedToggle().getUserData());
}

新しいトグルが「Null」の場合は四角(Rect)の色を白、それ以外は「UserData」で指定した色を表示。

上記の様に実装しています。

JavaFX チュートリアル〜今度こそ、初めてでも大丈夫4:RadioButton〜

イントロダクション

以前記載した記事で「初めてでも大丈夫」などと記載していましたが、ちょっと「危ういな」と思いチュートリアルをやってみようとなりました。

今回はラジオボタンの表示をやります。

チュートリアル

ここのページを、戦国Xサラの要領でガンガン斬り伏せながらやっていきます。

<チュートリアル>

基本のコード(ちょっとダメなコード)

public class Lv3_RadioButton extends Application {

	/**
	 * このメソッドは、Applicationクラス(JavaFXのフレームワーク部品)
	 * のメソッドをオーバーライドする。
	 * {@link Application#launch(String...)}から呼び出される。
	 */
	@Override
	public void start(Stage primaryStage) throws Exception {
		// チュートリアルには省略されている部分
		Group group = new Group();
		// この部分がチュートリアルに記載されている。
		//A radio button with an empty string for its label
		RadioButton rb1 = new RadioButton();
		//Setting a text label
		rb1.setText("Home");
		//A radio button with the specified label
		RadioButton rb2 = new RadioButton("Calendar");

		// 上のコンポーネント(Labelとか、イメージとか)
		group.getChildren().addAll(rb1, rb2);
		// チュートリアルでは省略されている
		Scene scene = new Scene(group, 300, 300);
		primaryStage.setScene(scene);
		primaryStage.setTitle("チュートリアル1");
		primaryStage.show();
	}

	/**
	 * メインメソッド。
	 * Apllicationクラスのlaunchメソッドを呼び出す。
	 * 
	 * @param args プログラム引数
	 */
	public static void main(String[] args) {
		launch(args);
	}
}

今回は、ちょっとダメなコードを基本にしていきます。なんでダメなのかは実行結果を見れば一目瞭然。。。

コンポーネントが重なってしまい、意味がわかりません。

ここで、start()メソッドの初めの部分で「Group group = new Group();」というコードがありますが、この部品をGroupからVBoxへ変更します。

Groupはレイアウトクラスですが、VBoxの親の親。。。とちょっと遠い親戚な関係です。下のJavaDocをみてください。

こんな感じでクラスの系譜がちょっと違うのです。コンポーネントを配置するコンテナクラスという意味で「レイアウトクラス」という文言を使いましたが、とりあえずは「VBoxも Groupもコンポーネントを保持するんだな」と理解してくれればOK!

そして、以下の様にVBoxをGroupの代わりに使用してみると。。。

こんな感じで表示されます。

そしてコードはこんな感じになりました。これもイマイチ。。。Gitからダウンロード

public void start(Stage primaryStage) throws Exception {
	// チュートリアルには省略されている部分
	VBox group = new VBox(20b);
	// この部分がチュートリアルに記載されている。

	//A radio button with an empty string for its label
	RadioButton rb1 = new RadioButton();
	//Setting a text label
	rb1.setText("Home");
	rb1.setSelected(true);
	group.getChildren().add(rb1);

	//A radio button with the specified label
	RadioButton rb2 = new RadioButton("Calendar");
	rb2.setToggleGroup(togle);
	group.getChildren().add(rb2);

	RadioButton rb = new RadioButton("Agree");
	group.getChildren().add(rb);

	
	// 上のコンポーネント(Labelとか、イメージとか)
	group.getChildren().addAll(rb1, rb2, rb);
	// チュートリアルでは省略されている
	Scene scene = new Scene(group, 300, 300);
	primaryStage.setScene(scene);
	primaryStage.setTitle("チュートリアル3");
	primaryStage.show();
}

これで、3つあるラジオボタンの1つを選択するとそれのみを選択する様になります。選択することができます。表示結果は下の様になります、

これでは味気ないので次の様な機能を実装しようと思います。

  1. 初期表示時には「家の画像」を表示する
  2. ラジオボタンで選択すると選択した画像を表示する

それぞれ、Home, Calender, Agreeで以下の様な画像です。

Home
Calender
Agree

ちょっとややこしくなってしまいました。。。

<ソースコード>

@Override
public void start(Stage primaryStage) throws Exception {
	// チュートリアルには省略されているものから変更
	// 横のレイアウト
	HBox lineLayout = new HBox();
	// 縦のレイアウト
	VBox group = new VBox(20d);
	// 横のレイアウトに追加
	lineLayout.getChildren().add(group);

	/* トグル・グループの追加
	 * トグルが設定されているラジオボタンは
	 * 1つのグループとして扱われる
	 */
	final ToggleGroup togle = new ToggleGroup();
	//A radio button with an empty string for its label
	RadioButton rb1 = new RadioButton();
	//Setting a text label
	rb1.setText("Home");
	rb1.setToggleGroup(togle);
	rb1.setSelected(true);
	// イベント用UserData
	rb1.setUserData("home");
	// 縦のレイアウトに追加
	group.getChildren().add(rb1);
	//A radio button with the specified label
	RadioButton rb2 = new RadioButton("Calendar");
	rb2.setToggleGroup(togle);
	// イベント用UserData
	rb2.setUserData("calendar");
	// 縦のレイアウトに追加
	group.getChildren().add(rb2);

	RadioButton rb = new RadioButton("Agree");
	// イベント用UserData
	rb.setUserData("contacts");
	// サイズを合わせる
	rb.setToggleGroup(togle);
	// 縦のレイアウトに追加
	group.getChildren().add(rb);
	
	// 横のレイアウトに追加
	ImageView imageView = new ImageView();
	lineLayout.getChildren().add(imageView);
	final Map<String, Image> imageMap = createImageMap(imageView);

	// イベント処理
	togle.selectedToggleProperty().addListener(
			(ObservableValue<? extends Toggle> ov, Toggle old_toggle, Toggle new_toggle) ->{
				if (togle.getSelectedToggle() != null) {
					String userData = togle.getSelectedToggle().getUserData().toString();
					imageView.setImage(imageMap.get(userData));
				}
			});
	// 上のコンポーネント(Labelとか、イメージとか)
	// チュートリアルでは省略されている
	Scene scene = new Scene(lineLayout, 1000, 300);
	primaryStage.setScene(scene);
	primaryStage.setTitle("チュートリアル3");
	primaryStage.show();
}

実行結果

上から順番に、

// 横のレイアウト
HBox lineLayout = new HBox();
// 縦のレイアウト
VBox group = new VBox(20d);
// 横のレイアウトに追加
lineLayout.getChildren().add(group);
  1. 横と縦のレイアウトを用意する。
  2. 縦のレイアウトは20d(double型の20)分の間隔をあけてやる。
  3. 横のレイアウトに縦のレウアウトを追加

イメージは下の様な感じです。

でわでわ。。。


JavaFX チュートリアル〜今度こそ、初めてでも大丈夫3:Button〜

イントロダクション

以前記載した記事で「初めてでも大丈夫」などと記載していましたが、ちょっと「危ういな」と思いチュートリアルをやってみようとなりました。

今回は、ボタンの表示をやります。

チュートリアル

ここのページを、戦国Xサラの要領でガンガン斬り伏せながらやっていきます。

<チュートリアル>

基本のコード

public class Lv2_Button extends Application {

	/**
	 * このメソッドは、Applicationクラス(JavaFXのフレームワーク部品)
	 * のメソッドをオーバーライドする。
	 * {@link Application#launch(String...)}から呼び出される。
	 */
	@Override
	public void start(Stage primaryStage) throws Exception {
		// チュートリアルには省略されている部分
		Group group = new Group();
		// この部分がチュートリアルに記載されている。

		// Fontを使用する方法
		Label label1 = new Label();
		label1.setFont(new Font("Aeial", 30));
		label1.setText("Text1");
		label1.setTranslateX(60);
		label1.setTranslateY(60);

		// 回転させる
		label1.setRotate(-45.0);

		// ボタンを追加する
		Button btn = new Button();
		
		// 上のコンポーネント(Labelとか、イメージとか)
		group.getChildren().addAll(label1, btn);
		// チュートリアルでは省略されている
		Scene scene = new Scene(group, 300, 300);
		primaryStage.setScene(scene);
		primaryStage.setTitle("チュートリアル1");
		primaryStage.show();
	}

	/**
	 * メインメソッド。
	 * Apllicationクラスのlaunchメソッドを呼び出す。
	 * 
	 * @param args プログラム引数
	 */
	public static void main(String[] args) {
		launch(args);
	}
}

このコードの実行結果

ちょっとわかりずらいけど、左端にボタンがあります。ボタンかどうかも怪しい感じです。ボタンだとわかるようにします。下の様にコードを修正します。

// ボタンを追加する
Button btn = new Button("ボタン");

ボタンが表示されました。しかし位置が悪い。。。

ソースを以下の様に追加修正します。

// ボタンを追加する
Button btn = new Button("ボタン");
btn.setLayoutX(100.0);
btn.setLayoutY(120.0);

やっぱりなんか微妙だけどまぁよし!ボタンを作成した(new Button())の行の下にあるコードは、Labelクラスでも使用したメソッドと同じ名前です。「setLayout?()」?の部分に「X」「Y」が入りそれぞれの位置を指定します。

アイコンの追加

さらにコードを修正します。

// イメージファイルの読み込み
Image img = new Image(
    this.getClass().getResourceAsStream("check.png"));
btn.setGraphic(new ImageView(img));

コードが長くなってしまった場合は、上の様にインデントをつけて(コードの開始位置をずらして)次の行にコードを書きます。そして、Imageクラスのインスタンス化(new Image())の部分はこのクラスのあるディレクトリ(フォルダ)と同じ場所にあるcheck.pngファイルを読み込んでいます。起動しているのは「Lv2_Button」クラスです。

そして、ボタンにイメージを追加しています。btn.setGraphic(new ImageView(img));これはImageViewクラスはNodeクラスを継承している(親子関係があるけど、Imageクラスにはないのでbtn.setGraphic(Node);の形位に遭わないためこの様に処理をしています。詳しくはJavaDocを参照されたし。。。

追伸:ButtonクラスはNodeクラスを継承しているので「setGraphic()」はNodeクラスのメソッドですがButtonクラスでも使用できます。この部分はおいおい理解していきましょう。

そして実行結果、よくみるとアイコンに余計な部分も入っています。元になるcheck.pngファイルをちゃんと加工していないのでこの様になります。

アクションの割り当て

アクション→ボタンを押下した時の処理を実装します。追加するコードは以下の様になります。

// アクションの追加
btn.setOnAction(event -> {
	label1.setRotate(label1.getRotate() + 15.0);
});

チュートリアルにはスタイルの指定もありましたが、ちょいと飛ばしてしまおうと思います。。。

でわでわ。。。



JavaFX チュートリアル〜今度こそ、初めてでも大丈夫2:Label〜

イントロダクション

以前記載した記事で「初めてでも大丈夫」などと記載していましたが、ちょっと「危ういな」と思いチュートリアルをやってみようとなりました。

初心者向けというのもあり、以下の手順で進めやすいように作ったつもりです。

  1. 基本のコードを写経する
  2. 動かす
  3. 〜を修正して〜する
  4. 起動確認
  5. ソースの意味を理解
  • こんな感じで進めると分かりやすいと思います。
  • 前回はラベルを表示しました。そして今回もラベルを表示します。ただし

    回転したり大きくしたりします

    チュートリアル

    ここのページを、戦国Xサラの要領でガンガン斬り伏せながらやっていきます。

    <Oracleのチュートリアル>

    基本のコード

    public class Lv1_Label2 extends Application {

	/**
	 * このメソッドは、Applicationクラス(JavaFXのフレームワーク部品)
	 * のメソッドをオーバーライドする。
	 * {@link Application#launch(String...)}から呼び出される。
	 */
	@Override
	public void start(Stage primaryStage) throws Exception {
		// チュートリアルには省略されている部分
		Group group = new Group();
		// この部分がチュートリアルに記載されている。

		// Fontを使用する方法
		Label label1 = new Label();
		label1.setFont(new Font("Aeial", 30));
		label1.setText("Text1");

		group.getChildren().add(label1);
		// チュートリアルでは省略されている
		Scene scene = new Scene(group, 300, 300);
		primaryStage.setScene(scene);
		primaryStage.setTitle("チュートリアル1");
		primaryStage.show();
	}

	/**
	 * メインメソッド。
	 * Apllicationクラスのlaunchメソッドを呼び出す。
	 * 
	 * @param args プログラム引数
	 */
	public static void main(String[] args) {
		launch(args);
	}
}

    これだけで起動すると下のように表示されます。

    そして上のコードに3行追加します。

    // 位置を指定する
label1.setTranslateX(60);
label1.setTranslateY(60);
// 回転させる
label1.setRotate(45.0);

    すると下のように表示されます。

    setTranslateX(表示するX座標)とsetTranslateY(表示するY座標)を指定することでテキストの表示する位置を変更します。

    表示する画面の左上の端が(0, 0)になります。なのでテキストの中心位置が(60, 60) かつ、角度が45度下に下がった状態で画面上に表示されています。

    試しに「45」を「-45」に変更してみます。

    上のようになりました。そのほかにもいじってみると表示結果が変わります。

    大きくする

    基本のコードに下の行を追加します。

    label1.setScaleX(1.5);
label1.setScaleY(1.5);

    実行結果はこんな感じです。

    ラベルが見切れてしまいました。なので下のコードでテキストの位置をずらします。

    label1.setLayoutX(20.0); // Xを20右に移動
label1.setLayoutY(30.0); // Yを30下に下げる


    とりあえず今回は、ここで終わりにします。

    でわでわ。。。