スケジュール前のページJavaの初歩3

Javaの基礎1:イベント処理1

前節までは,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);
    }
 
}



内容の説明

TextFieldの作成

ラベルと同様に,テキストフィールド(入力欄)をtfという名前で作成します.

TextField tf = new TextField();

また,次のimport文も必要です.

import javafx.scene.control.TextField;

作成したテキストフィールド tf は,starとupdateTextの両方のブロックで使用されるので,その外側の領域のこの位置で作成して置かなければなりません.(変数のスコープを参照)

イベント処理の記述

コントロールを使用するプログラムを作成する場合は,キーを押したり,マウスを操作したイベントを受け取って,対応する処理をプログラムする必要があります.

これを「ラムダ式」という書き方を使うと,次のように簡単に記述できます.

tf.setOnAction(event -> updateText());

この記述の具体的な内容は,

tf.setOnAction(…)
テキストフィールド tf にイベント処理の設定 setOnAction()「何か起きた時(OnAction)にやる事を設定(set) 括弧内に具体的な動作を記述」
event -> updateText()
発生イベントと実行する命令を「->」でつなぐ(この書き方がラムダ式):
「イベント(今回はeventと名づけた)が発生 -> イベントが発生した時に実行する命令(今回はupdateText()という自分で作ったメソッドを呼び出している)」

メソッドの定義

Javaでは新しいメソッドを独自に定義して使うことが出来ます.前出のプログラムでは,イベント処理で呼び出されるメソッドupdateText()はJavaで予め用意されているメソッドではなく,プログラムの製作者が新しくメソッドを定義しています.

定義の仕方は,一般に次のように記述します.メソッド名はJavaで予め使用されていないものならば何でも使用できます.通常,小文字から始まるアルファベットを用います.

アクセス修飾子 戻り値の型 メソッド名(引数) {メソッドの内容}

アクセス修飾子は,定義したメソッドが使用できる範囲を指定します.

アクセス修飾子公開範囲
public全てのクラスから使える
private同じクラスからのみ使える
なし同じパッケージからのみ使える

戻り値の型は,メソッドが結果を返すような処理の場合,その結果の値を表すデータ型を指定します.

戻り値の型
データ型答えとして外部に渡すデータの型を指定
void答えを返す必要のない場合

引数は,メソッドに外部からデータを渡す必要がある場合に指定し,渡すデータの型宣言と変数名を指定します.

updateText()の定義

ここでは,テキストフィールドに文字列を入力して,キーボードのenterキーを押した時に発生するAction Eventによって呼び出されるメソッド「updateText()」を定義します.

処理すべき内容は,「テキストフィールドに入力した文字列を読み取って,ラベルに設定する」ことが行われるように記述します.

以上から,具体的には次のような設定で定義します.

アクセス修飾子
なし,またはprivate
戻り値
void
メソッド名
updateText (他の名前を自分で付けても良い)
引数
なし
内容
  • 1行目:文字列変数 s を作成し,テキストフィールド tf から getText()メソッドで内容を読み取って s に代入
  • 2行目:文字列 s を setText()メソッドでラベル label に設定.

文字列の扱い方

今回は,一文字ではなく文字列(文)を扱うので,基本的な文字用の変数(char)ではなく複数の文字(文字列)をまとめて扱うプログラムである「String」を使用します.

使い方は変数の宣言と代入と同様に記述できます.ここでは,名前を「s」とした文字列変数を宣言し,「getText()」で tf から読み取った文字列を代入します.

String s;
s = tf.getText();

以上をまとめると,

privare void updateText(){
	String s;
	s = tf.getText();
	label.setText(s);
}

練習問題4−1

次のどちらかのプログラムを作成して実行してみましょう.

  1. プログラムの起動時には1行目に「文章を入力してください.」と表示され.入力欄に文章を入力すると,1行目は「入力した文章は以下の通りです.」と表示され,2行目には入力した行が表示されるプログラムを作りなさい.クラス名は「Ex04_1a」とせよ.
  2. 最初に入力した行が1行目に,2回めに入力した行が2行めに表示され,3回目の入力があったら,2回目の入力が1行目に,3回目の入力が2行目に表示されるというように,それ以降の入力では常に最新の2回の入力が1行目,2行目になるプログラムを作りなさい.クラス名は「Ex04_1b」とせよ.
    ヒント:
    • 2行表示するので,Labelが2つ必要です.TextField は1つです.
    • 必要な文字列の数だけ「String」変数が必要です.
    • getText() を tf の代わりに label に対して使用すると,label の文字列を読み取ることが出来ます.

CSSによるスタイルの設定

JavaFXではHTMLでホームページにデザインを設定する時に使用するCSSという記述の仕方と同様のものを使用してプログラムに様々なデザインを設定できます.通常は,CSSの設定を記述したCSSファイルを別に用意し,プログラムに読み込むようにして使用しますが,プログラムの中に直接記述して使用することも可能です.ここではプログラムに直接記述する方法を用います.

次のようにラベルが作成されていれば、

Label label = new Label("Hello JavaFX!");

以下のようにCSSをラベルのスタイルとして設定します.ただし,start等のメソッドのブロック内に記述します.

label.setStyle("ここにCSSを記述");

CSSの記述の仕方は,設定したいプロパティーと値を以下のような書き方で設定していきます.

CSSプロパティー:値;CSSプロパティー:値;CSSプロパティー:値;…

フォントの設定

フォントに対して用意されているプロパティーと設定できる値は次の通りです.

プロパティー
-fx-font-familyserif(明朝体),sans-serif(ゴシック体),cursive,fantasy,monospace
-fx-font-size12pt etc.
-fx-font-stylenormal, italic, oblique
-fx-font-weightnormal, 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−2

練習問題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);

練習問題4−3

次のどちらかのプログラムを作ってみましょう.

  1. 視点の高さを入力して,地平線(水平線)までの距離を求めるプログラムを作ってみましょう.クラス名は「Ex04_3a」とする.
    地平線(水平線)までの距離を求める数式は自分で求めるかネットで調べるかしてください.
  2. 「身長」と「体重」の入力欄を作り,数値を入力してenterキーを押すと,BMIの値を計算した結果を表示するプログラムを作ってみましょう.クラス名は「Ex04_3b」とする.

スケジュール前のページJavaの初歩3