読者です 読者をやめる 読者になる 読者になる

JavaFXをやってみる(2)

前回はこちら →

前回の知識は

結構大事だと思う!

クラスの生成方法の違いを思い出す

Javaの場合(Main.java)

class Test {
  int count;
  String name;
  Test(int count, String name) {
    this.count = count;
    this.name = name;
  }
  public void dispCount() {
    System.out.println("かうんと:"+count);
  }
  public void dispName() {
    System.out.println("なまえ:"+name);
  }
}
public class Main {
  public static void main(String[] args) {
    Test test = new Test(10,"ひふみん");
    test.dispCount();  // かうんと:10  と表示される
    test.dispName();  // なまえ:ひふみん と表示される
  }
}

JavaFXの場合(名前はなんでもいいので拡張子をfxにする)

class Test {
  var count : Integer;
  var name : String;
  public function dispCount() : Void{
    println("かうんと:{count}");
  }
  public function dispName() : Void{
    println("なまえ:{name}");
  }
}
function run(args: String[]) {
  var test = Test{
    count : 10
    name : "ひふみん"
  }
  test.dispCount();  // かうんと:10  と表示される
  test.dispName();  // なまえ:ひふみん  と表示される
}

new Test() じゃなくて Test{ } を使う
前回のがちょっと頭に入っているだけで今回のは理解していけると思います
自分はそうだった!

GUIを使ってみたい!

Javaの場合はSwingを使うとできるんでしたね!
メインのフレームはjavax.swing.JFrameを使ってました

ウィンドウを表示させる

こういうのが表示されるのを作る
f:id:voidy21:20100102024900p:image

Main.java

import javax.swing.JFrame;

class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("GUIてすと");
        frame.setSize(200, 100);
        frame.setVisible(true);
    }
}

JavaFXの場合はjavafx.stage.Stageを使う
Main.fx

import javafx.stage.Stage;

Stage {
    title : "GUIてすと"
    width : 200
    height : 100
}
JavaFXの場合Stage{}するだけで表示できちゃうのはなぜだろう

Stageを呼び出すとJavaでいうJFrame#setVisible(true)とJFrame#setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)が
自動的に呼ばれているからじゃないかと思う(詳しくはわからないけど)

サイズをなんとかしたい

上のやつだとタイトルバーもサイズに含まれていてちょっと扱いづらいのでなんとかする
f:id:voidy21:20100102035558p:imagef:id:voidy21:20100102035557p:image

左図のようになっているのを右図のようにしたい
javafx.scene.Sceneを使ってサイズを調節する
SceneはJavaでいうjavax.swing.JPanel的なやつです
SceneはJPanelではなくて、JRootPaneに相当します
自動的に上に乗っているコンポーネントに応じてサイズが変わるみたい(Javaでいうjava.awt.Window#pack())

import javafx.stage.Stage;
import javafx.scene.Scene;

Stage {
    title : "GUIてすと"
    scene : Scene {
        width: 200
        height: 100
        content: [  ]
    }
}

contentにある[ ] は配列です(空の配列なので何も表示されない)
実は期待値は配列なのですが、別に配列じゃなくても受け取ってくれます(要素1の配列だと解釈してくれる)
ここに何か表示したいコンポーネントを追加すると表示されます

何か文字を表示する(GUIHelloWorld)

f:id:voidy21:20100102042312p:image

javafx.scene.cotrol.Label は Javaでいうと javax.swing.JLabelに相当します
これを先ほどのSceneのcontentに追加します

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.text.Font;

Stage {
    title : "GUIてすと"
    scene : Scene {
        width: 200
        height: 100
        content: Label {
            text : "Hello,World!!"
            font : Font{
                size : 24;
            }
        }       
    }
}

これじゃ初見だと分かりづらいので、書き方をちょっと先行宣言的に書いてみます

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.text.Font;

var textFont : Font = Font { size : 24 };
var label : Label = Label { text : "Hello,World!!!" , font : textFont }

Stage {
    title : "GUIてすと"
    scene : Scene {
         width: 200
         height: 100
         content: label
    }
}

大分見通しが良くなった気がしますね!
ちょっとコード量的に考えて今回はここまでにします

次回予告

今回のコードだけだとJavaFXの何がGUIを書きやすくしているかあまり伝わらないと思いますが、
入れ子構造でどんどん書いていけるっぽいことはわかったんじゃないかなぁと思います
JavaFXにはbind演算子というのがあるんですが、実はこれがJavaのめんどくさいイベントの処理(特に再描画処理)を圧倒的に楽にします!
次はこれについて書けたらいいなと思います!