前節までは,Scene Graphを構成するNodeとして,データを表示するだけのGUI部品を使用しましたが,NodeにはControlと呼ばれるマウスやキーボードからの操作を受け取るGUI部品があります.
ここでは,窓に入力欄を設置して,プログラムに外部からデータを入力できるようにしてみます.
画面からプログラムにデータを入力するためには,「Text Filed(テキストフィールド)」というコントロールを使用して,「イベント処理」をする必要があります.
「イベント処理」と言うのは,画面上で行った操作をプログラムに受け渡し,それに対して適切な処理が実行されるようにプログラムすることです.
イベント処理の流れは,それぞれのコントロールの状態が変化(データを入力してEnterを押したり,ボタンをクリックしたり,マウスをクリックしたりなど)すると「イベント」というものが発生し,それぞれのイベントの種類に応じて,作業する内容をプログラムします.
最近のJavaでは「ラムダ式」という書き方を使用することで,このイベント処理を簡単に記述できます.
それでは,具体的な例として,画面に「テキストフィールド」を表示し,キーボードから文字を入力し,エンターキーを押すと入力した文字が窓に表示されるプログラムを作ってみましょう.
「Javaの初歩1」で作成した文字を表示するプログラムを「イベント処理」を使用するように書き換えれば,次のようになります.赤色の部分がイベント処理に必要な部分で,詳しい説明は下にあります.
import javafx.application.Application; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.layout.VBox; import javafx.scene.control.Label; import javafx.scene.control.TextField; public class InputEvent extends Application{ public static void main(String[] args) { launch(args); } //TextFieldの作成 TextField tf = new TextField(); Label label = new Label("文章を入力して下さい."); @Override public void start(Stage stage) throws Exception { stage.setTitle("Application InputEvent"); VBox root = new VBox(); root.setAlignment(Pos.CENTER); root.setPadding(new Insets(10,10,10,10)); root.setSpacing(15.0); root.getChildren().addAll(label, tf); //イベント処理のラムダ式による記述 tf.setOnAction(event -> updateText()); Scene scene = new Scene(root,320,240); stage.setScene(scene); stage.show(); } //メソッド「updateText」 private void updateText() { String s; s = tf.getText(); label.setText(s); } }
ラベルと同様に,テキストフィールド(入力欄)をtfという名前で作成します.
TextField tf = new TextField();
また,次のimport文も必要です.
import javafx.scene.control.TextField;
作成したテキストフィールド tf は,starとupdateTextの両方のブロックで使用されるので,その外側の領域のこの位置で作成して置かなければなりません.(変数のスコープを参照)
コントロールを使用するプログラムを作成する場合は,キーを押したり,マウスを操作したイベントを受け取って,対応する処理をプログラムする必要があります.
これを「ラムダ式」という書き方を使うと,次のように簡単に記述できます.
tf.setOnAction(event -> updateText());
この記述の具体的な内容は,
Javaでは新しいメソッドを独自に定義して使うことが出来ます.前出のプログラムでは,イベント処理で呼び出されるメソッドupdateText()はJavaで予め用意されているメソッドではなく,プログラムの製作者が新しくメソッドを定義しています.
定義の仕方は,一般に次のように記述します.メソッド名はJavaで予め使用されていないものならば何でも使用できます.通常,小文字から始まるアルファベットを用います.
アクセス修飾子 戻り値の型 メソッド名(引数) {メソッドの内容}
アクセス修飾子は,定義したメソッドが使用できる範囲を指定します.
アクセス修飾子 | 公開範囲 |
---|---|
public | 全てのクラスから使える |
private | 同じクラスからのみ使える |
なし | 同じパッケージからのみ使える |
戻り値の型は,メソッドが結果を返すような処理の場合,その結果の値を表すデータ型を指定します.
戻り値の型 | |
---|---|
データ型 | 答えとして外部に渡すデータの型を指定 |
void | 答えを返す必要のない場合 |
引数は,メソッドに外部からデータを渡す必要がある場合に指定し,渡すデータの型宣言と変数名を指定します.
ここでは,テキストフィールドに文字列を入力して,キーボードのenterキーを押した時に発生するAction Eventによって呼び出されるメソッド「updateText()」を定義します.
処理すべき内容は,「テキストフィールドに入力した文字列を読み取って,ラベルに設定する」ことが行われるように記述します.
以上から,具体的には次のような設定で定義します.
今回は,一文字ではなく文字列(文)を扱うので,基本的な文字用の変数(char)ではなく複数の文字(文字列)をまとめて扱うプログラムである「String」を使用します.
使い方は変数の宣言と代入と同様に記述できます.ここでは,名前を「s」とした文字列変数を宣言し,「getText()」で tf から読み取った文字列を代入します.
String s; s = tf.getText();
以上をまとめると,
privare void updateText(){ String s; s = tf.getText(); label.setText(s); }
次のどちらかのプログラムを作成して実行してみましょう.
JavaFXではHTMLでホームページにデザインを設定する時に使用するCSSという記述の仕方と同様のものを使用してプログラムに様々なデザインを設定できます.通常は,CSSの設定を記述したCSSファイルを別に用意し,プログラムに読み込むようにして使用しますが,プログラムの中に直接記述して使用することも可能です.ここではプログラムに直接記述する方法を用います.
次のようにラベルが作成されていれば、
Label label = new Label("Hello JavaFX!");
以下のようにCSSをラベルのスタイルとして設定します.ただし,start等のメソッドのブロック内に記述します.
label.setStyle("ここにCSSを記述");
CSSの記述の仕方は,設定したいプロパティーと値を以下のような書き方で設定していきます.
CSSプロパティー:値;CSSプロパティー:値;CSSプロパティー:値;…
フォントに対して用意されているプロパティーと設定できる値は次の通りです.
プロパティー | 値 |
---|---|
-fx-font-family | serif(明朝体),sans-serif(ゴシック体),cursive,fantasy,monospace |
-fx-font-size | 12pt etc. |
-fx-font-style | normal, italic, oblique |
-fx-font-weight | normal, bold, bolder, lighter, 100 〜 900 |
ラベルをlabelとして作成したとして,フォントの設定の具体な例としては以下のようにします.
label.setStyle("-fx-font-family:serif;-fx-font-size:20pt;-fx-font-style:italic;-fx-font-weight:bold; ");
この場合,大きさ20ポイントの明朝体の太字の斜体で表示されます.
CSSを使えば,文字の色や背景色を変更することも可能です.上記のフォントの設定と同様に,setStyleに次のような設定を付け加えます.
文字色の設定:-fx-text-fill:#000000; 背景色の設定:-fx-background-color:#ffffff;
#000000(黒),#ffffff(白)の部分が色の指定で,左から2桁ごとに赤,緑,青の光の3原色の強さを16進法(0〜9,a 〜 f)で指定します.
練習問題4−1を「Ex04_2」という別名で保存し,それにフォントや色の設定をしてみましょう.クラス名の変更を忘れずに.
異なるレイアウトを持ったコンテナを組合せて用いることで,様々なレイアウトを設定できます.
例えば,今まで使用してきたVBoxは垂直方向にノードをレイアウトするものでしたが,この各ノードにHBoxという水平方向にノードをレイアウトするコンテナを設定すれば,垂直,水平の両方向にノードをレイアウトしたScene Graphを作れます.
水平方向に「身長」のラベル,「入力欄」のテキストフィールド,その後に「単位(cm)」のラベルが表示され, 入力欄に数値を入力してenterキーを押すと,その下の部分に「身長 =(数値)cm」のように表示するプログラムを作ってみます.
import javafx.application.Application; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.layout.VBox; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.layout.HBox; public class LayoutMix extends Application{ public static void main(String[] args) { launch(args); } //TextFieldの作成 TextField tfs = new TextField(); Label kekkalabel = new Label(); @Override public void start(Stage stage) throws Exception { stage.setTitle("Application LayoutMix"); VBox root = new VBox(); root.setAlignment(Pos.CENTER_LEFT); root.setPadding(new Insets(10,10,10,10)); root.setSpacing(15.0); //HBox1の作成 HBox spane = new HBox(); //HBox1のレイアウト設定 spane.setAlignment(Pos.CENTER); spane.setPadding(new Insets(10,10,10,10)); spane.setSpacing(5.0); //HBox2の作成 HBox kpane = new HBox(); //HBox2のレイアウト設定 kpane.setAlignment(Pos.CENTER); kpane.setPadding(new Insets(10,10,10,10)); kpane.setSpacing(5.0) //Labelの作成 Label slabel = new Label("身長:"); Label cmlabel1 = new Label("cm"); Label cmlabel2 = new Label("cm"); //HBoxへの組み込み spane.getChildren().addAll(slabel,tfs,cmlabel1); //slabel,tf,cmlabel1を横に並べる kpane.getChildren().addAll(kekkalabel,cmlabel2); //kekkalabel,cmlabel2を横に並べる //VBoxへの組み込み:Hbox1(spane),Hbox2(kpane)を縦に並べる root.getChildren().addAll(spane,kpane); //イベント処理 tfs.setOnAction(event -> updateText()); Scene scene = new Scene(root,320,240); stage.setScene(scene); stage.show(); } //updateTextの定義 private void updateText(){ String s = tfs.getText(); double x = Double.parseDouble(s); kekkalabel.setText("身長 = "+x); } }
入力欄に数値を入力した場合でも,getText()で受け取るのは入力された文字列で数値ではありません.従って,プログラム内で入力された値を使用して計算するためには文字列を数値に変換しなければ出来ません.
文字列を倍精度実数に変換するには,「Double.parseDouble(文字列)」という命令を使用します.(整数にする場合は「Integer.parseInt()」)
プログラム例の場合updateTextの定義の所で,入力された文字列をgetText()で受け取り,文字列変数 s に代入し,その後,Double.parseDouble(s)で倍精度実数に変換して倍精度実数で宣言した変数 x に代入しています.
String s = tfs.getText();
double x = Double.parseDouble(s);
次のどちらかのプログラムを作ってみましょう.