javafxでGUI
VsCodeでMavenを使ってjavafxでGUIを作ってみる
- Scene Builderをインストールする
- javafxをMavenで作る ひな形作成
- 1画面の計算プログラムを作ってみる
- 画面どうしでデータ渡しをしてみる
いままでCUIのjavaばかりでしたので、Servletを使わずにGUIプログラムを作ってみましょう
Scene Builderをインストールする
まずは、Scene Builderをインストールしましょう。このツールを入れると画面の作成をVBのようにVisualにすることができるようになります
まずは、Scene Builderをダウンロードします
https://gluonhq.com/products/scene-builder/
このサイトからwindows版をダウンロードします
それほど大きくはありません。
ダウンロードしたらダブルクリックしてインストールしてください
インストールが終わると、ユーザーの配下にインストールされます。この場所はあとで使います
scene builderをインスタールしたら、VsCodeに拡張機能で「Scene builder extension for Visual Studio Code」をインストールします。
さて、ここでこのインストールしたscenebuilderとVsCodeを接続していきます。Vscodeを起動してCTRL+SHIFT+Pでコマンドパネルを表示して
Configure Scene Builder path と入力して、表示されたその項目をクリックすると
どこにscene builder.exeがあるか聞いてくるので、さきほど見たユーザーの配下のscenebuilderをクリックします。これでvscodeから直接scene builderが起動できるようになります。
javafxをmavenで作る
さて、vscodeでmavenを利用してjavafxを作っていきます。CTRL+SHIFT+Pを押して create java projectを選びます
あとは、mavenの回でやったようにプロジェクト名等を入れていきます
今回はjavafxのサンプルを作りますので、javafxを選択します
group idを入れます。これがpackage名になりますので、自分のドメイン名(架空でかまわない)を逆順にした名前を英数小文字で入力してください。これがパッケージになりますので、フォルダーの階層になります。
続いて、プロジェクト名を英数小文字で入力します。これはフォルダー名とは別です。今回は画像とはことなりますが「scenesample」として作ってみましょう
その後に、そのフォルダーの先頭をどこに作るのか聞いてきますので、自分がmaven等で作成しているworkspaceにフォルダーを作成、あるいは選択してください。これは大文字が入っても大丈夫です。今回は「SceneSample」として作りましょう
作成したらそのフォルダーを選択します
するとmavenが働いてフォルダー作成の確認を求めてきますので、ここでこの当たりをマウスでクリックしておいてからエンターキーを押します
つづいてYの文字が出てきたらそこに小文字でyとenterを入力します
そのあと、今作った場所をウィンドウを開くか聞かれたらopenを押します。すると今作ったフォルダーが新たに開かれます。openを押さないでその画面で続けたい場合は×で終了して、enterキーを入力すればその場で作成を続けることも可能です。
新たなウィンドウではフォルダーが展開されていませんので、開かないとわかりません
srcを開くと、フォルダーが指示通りに作成されているのがわかります。
srcに3つのjavaソースが出来ているのがわかります。App.javaがmainでここからprimaryController.javaが呼び出されます。そこでボタンを押すことによってsecondaryController.javaが起動されて画面が切り替わるようになっています。つまりこのjavafxの作成の流れで2つの画面をもったサンプルが作成されることがわかります
中身を見てみましょう
まずjavafxのウィンドウの構造を説明します
一番外側の枠にあたるのが「stage」です。この中の台紙の部分が「scene」になります。この上にパネルとして「pane」があり、そう上に部品が乗るという感じになります。
javaではmainが最初に起動されますのでlaunch()が起動されます。これによってApplicationクラスが動きjavafxが起動されます。startメソッドがその起動時にコールされるもので、ここで初期化を行います。
起動時の枠としてstageが渡されるので、そこにprimary.fxmlで宣言された画面構造が台紙として宣言され、その台紙をstageにsetして、表示showします。
続いて第1画面の説明です。画面ファイルはサンプルとして2つ用意されています。
resourcesの配下のパッケージ配下に2つのfxmlファイルがあります。
javafxで画面がshowされると、その中の「fx:controller=」で宣言されたパッケージがコントロールを受け持つことになります。
でもこれでは画像がどう出るのかわかりません。そこでscenebuilderの登場です。見たいfxmlファイル上で右クリックして「open in scene builder」をクリックします
これが表示された画面です。といっても宣言されているのはペインPaneにあたる部分から下の階層です。stageやsceneはプログラムで書きます。
中身を見ていきましょう。ボタンをクリックします。右側のcodeの中身を展開すると
「fx.id」にprimaryButtonとあります。これがjavafxで宣言したボタンの名前です。プログラム中で使用できます。また「onAction」にswicthToSecondaryとありますが、これがボタンをクリックしたときにリンクされるメソッドの名前で、これをプログラム中に記述します。
ということで、この画面のプログラムを見てみましょう
画面が呼び出されても、このプログラムはなにも動きません。ただボタンが押されるとそこに宣言してあった「switchToSecondary」メソッドが起動されて、プログラムが動きます。書かれているのは、同じstageを使って、secondary.fxmlをsceneに貼って動けという指示です。secondary.fxmlの中身を見てみましょう
最初の画面とほぼ同じで、secondarycontrollerをコントローラーとすること、ボタンが押されたら switchtoprimaryが呼ばれることが書いてあります。
同様にscenebuilderで見てみましょう
同様で、ボタンを押すとprimaryに戻るようになっています。また左の階層をみるとPaneの一種のVBOXという部品を縦に並べる性質のあるPaneの中に中央揃えでlabelとbuttonが入っているので、縦に部品が並んでいるのがわかります。HBOXでは横に並びます
では、このままプログラムをコンパイル実行してみましょう
mainの上にrunがありますので、ここをクリック
ボタンを押すたびにscaneの中身が書き変わります
計算プログラムを作ってみる
まずは、前回のjavafxのサンプルを作り、そのあと不要なsecondarycontroller.javaとsecond.fxmlを消します。
計算プログラムの画面を作ります
画面を作るコツは、縦に並べるVBOXと横に並べるHBOXを組み合わせて作ることです。今回はVBOXの中にHBOXを入れています。scenebuilderで作るときは左のコンテナーの中のHBOXをドラッグして左下の階層のVBOXの上にドラッグすることです。下にドラッグするとその下に入ってしまいますが、上にドロップするとその配下に入ります。間違っても何回でも移動できるのでやってみましょう。
作ったのは入力が2つ、出力が1つ、ボタンが2つの画面です。縦にVBOXが並び、その中にHBOXを入れて、その中にTextFieldやButtonが並んでいます。
calcボタンをクリックすると「calc」メソッドにつながります。
ではプログラムを作っていきましょう。まずはApp.javaから
App.javaはほとんど変わっていません。setTitleが増えただけです。
primarycontroller.javaは入力の部分、計算の部分、出力の部分、終了の部分が増えています。
@FXMLを宣言して記述した部分がjavafx用のコーディングです。入力のTextFieldやButtonを宣言します。fx:idで宣言した名前で宣言すれば画面とつながります。
またデータの取得、出力が setText,getTextで行うことができます。文字としてやり取りするので数値にコンバートしてから計算を行います。
終了で少し変なことをしています。closeButtonから逆に元のstageを求めて、stageをcloseすることでjavafxを終了しています。画面を隠したりするのにもこの方法が扱えます。
calcボタンにcalcメソッドをリンクしています。
コンパイルして実行してみましょう。
TextFieldに数値を入れてcalcボタンを押すと結果が出力されます。計算が出来ないときは画面にはでないでエラーがコマンドに出力されます。calcモジュールやcloseモジュールを書いておけば動きます。exitボタンで終了します。
画面でデータ渡しをしてみる
単純に画面が切り替わるのであればひな形でやっているように、Web同様切り替えることができます。
ただ、VBなどでやっている方法は、どれかメインになる画面を決めておいて、そこから子画面を呼び出して処理が終わったら元のメインに帰るという方法です。こうしておけばメインでの終了がプログラムの終了になります。ばらばらに作ってしまうと終了のタイミングがわからなくなります。
今回はメインとしたprimaryを作り、loginが済んでいないのならばsecondaryに飛んでloginさせてからメインに戻り、login後thirdに飛び処理をしてからprimaryに戻るのをやってみます。図にすると以下のようになります。
まずはjavafxのひな形を作ります。primary.fxmlを作ります
まずは、ボタンを3つに改造します。それぞれ名前をつけて飛び先を宣言して下さい
続いてlogin画面をsecondaryとして作ります
ID,passwordを入力します。idはTextField、passwordはpasswordField、loginボタンとcancelボタンを入れます
続いて、3番目の画面です。idをユーザー名として表示するだけです。戻るボタンでメインに戻ります
メインに戻ったらexitで終了します。
つづいて、プログラムを説明します。App.javaはひな形のままですので省略します。
つづいて、primaryController.javaです。これをメインの画面としてloginを呼び出したり、子画面を呼び出したりしてみます。
処理の説明をします。起動された時、特になにも行っていません。ボタンが3つ表示されていますが、この状態ではログインが済んでいないので、this.idには空文字が入っているだけです。この状態では「hello」ボタンを押しても、先に進むことはできません。
「login」ボタンが押されて、いったんlogin画面に移動します。そのために「switchTloLogin」メソッドが動きます。ここで次の画面のsecondary.fxmlを読み込んで、そのコントローラであるsecondaryControllerのインスタンスを作ります。このインスタンスを利用してsetPassメソッドを使ってpasswordの正解を送り込んで置きます。
そして、次のコードは無理やりなのですが、自分のインスタンスをsecondaryControllerに送ります。これをしないとsecondaryからprimaryのデータを返すことができなくなります。苦肉の策です。secondaryでprimaryの画面を作れば良いような気がしますが、そこで作ったprimaryとthisのインスタンスは別アドレスの別物です。なのでいまここのアドレスを渡しておく必要がありました。(良い方法を教えてください)
そしてここで作ったsecondaryは処理が移った後のsecondaryと同じものなのでデータはわたります。そしてprimaryからsecondary画面を呼び出して、終わるまでここで待ちます。
処理的にはここからsecondaryに移りますが、説明はログインが終わったとして続けます。ログインが成功するとsecondaryからidに入力された文字列がthis.idに渡ってきています。
すると先程まで「hello」で先にいけなかった部分がロックが外れて「switchToThird」ができるようになります。ThirdControllerのインスタンスを作ったら、そのインスタンスを使ってsetIdTextを行い画面に文字を表示します。ThirdControllerのthis.idは設定はしていますが、表示するタイミングがないのでsetTextを使って表示までやっておきます。こちらもThirdが終わるまでここで待ちます。
つづいて、secondaryControllerです。
ここで行うのはidとpasswordに入力です。まず入力してもらってから「login」ボタンを押すと loginCheckメソッドが動きます。ここではあらかじめprimaryから送られているpasswordと入力された文字を比較して正しくなければ何もしません。正しければprimaryControllerのインスタンスを使って入力されたidを返します。
そして、switchToPrimaryを使ってこの画面を閉じます。
ログインに成功しなければあきらめて「cancel」を押してprimaryに戻ります。
つづいて、primaryに戻ってからの「hello」が押されてThird画面に移動します。
primaryで説明したように、Thirdにidを送って表示までしておきます。なので画面が出たときにすでにidが表示されています。これでidが確認できたので、「return to main」ボタンで画面を閉じます。すると呼び出したprimaryの画面が残っています。
primaryは、仕事が終わったので「exit」ボタンで画面を閉じて処理を終わります。
あとはコンパイルして実行です
「login」を押してlogin画面を表示します。primary画面は消えることなく残っています。
ここでidとpasswordを入れます。idはそのままユーザー名となり、パスワードは今回はabcで固定です。「login」ボタンを押します
ログインが成功すればprimaryに戻ります。間違えればなにもおきません。あきらめて「cancel」した場合ユーザー名は登録されません。
mainで「hello」ボタンを押すと今入力したidがユーザー名として表示されます。
「return to main」ボタンでmainに戻ります。そして「exit」で終了です