NetBeansでJavaFX開発をする

NetBeansJavaFXのプログラムを作る方法を解説します。

プロジェクトを作る

まずはプロジェクト作成です。「Java with Maven」カテゴリの「FXML JavaFX Maven Archtype(Gluon)」を選んで「Next」を押します。
f:id:nowokay:20200716005904p:plain

いろいろ入力する項目がでますが、とりあえずそのまま「Finish」を押します。
f:id:nowokay:20200716005929p:plain

そうするとプロジェクトの作成が始まります。初回はいろいろとダウンロードが行われるので時間がかかると思います。

NetBeansじゃなくても、次のMavenコマンドで同じプロジェクトが生成できます。

$ mvn -DarchetypeGroupId=com.raelity.jfx \
  -DarchetypeArtifactId=javafx-archetype-fxml-netbeans \
  -DarchetypeVersion=0.0.4 \
  -DarchetypeRepository=https://repo.maven.apache.org/maven2 \
  -DgroupId=kis \
  -DartifactId=mavenproject18fx \
  -Dversion=1.0-SNAPSHOT \
  -Dpackage=kis.mavenproject18fx \
  -Djavafx-version=13 \
  -Djavafx-maven-plugin-version=0.0.4 \
  -Dadd-debug-configuration=Y \
  -Darchetype.interactive=false \
  --batch-mode \
  org.apache.maven.plugins:maven-archetype-plugin:3.1.2:generate"

ファイル構成

生成されたプロジェクトは、こんな感じのファイル構成になってます。
f:id:nowokay:20200716010611p:plain

App.javaは起動ファイル。
画面がPrimaryとSecondaryが切り替わるというプログラムになっているので、それぞれのコントローラがあります。
あと、Other SourcesのほうにFXMLファイルがあって、ここで画面が定義されています。
あとはプロジェクト構成のPOMファイルがありますね。

module-info.javaはモジュール定義ファイルなのですが、慣れないうちは あとあとハマりがちなので、消しておいたほうがいいです。

実行してみる

プロジェクトを右クリックして、メニューから「Run」を選ぶと実行できます。 f:id:nowokay:20200716010632p:plain

コマンドではjavafx:runで実行できます。

$ mvn javafx:run

実行すると次のような画面が出ます。
f:id:nowokay:20200716010658p:plain

ボタンを押すと次の画面に切り替わります。
f:id:nowokay:20200716010712p:plain

SceanBuilderの導入

それではちょっと画面をいじってみましょう。
画面定義はFXMLファイルに記述されているので、このファイルを書き換えればいいのですが、やはりビジュアルエディタで操作したい。
f:id:nowokay:20200716012443p:plain

JavaFXではScene Builderというツールが用意されているので、このツールをインストールします。
ダウンロードは次のサイトで行えます。
Scene Builder - Gluon f:id:nowokay:20200716011202p:plain

NetBeansの「Tools > Option」で設定を開いて、「Java」の中の「JavaFX」タブでScene Builderをインストールした場所を設定します。
f:id:nowokay:20200716011524p:plain

これでFXMLファイルをダブルクリックするとScene Builderが開くようになるんですが、メニューが文字化けしています。
f:id:nowokay:20200716011734p:plain

ここではメニュー操作は行わないのでそのままにしていてもいいんですが、目障りでもあります。
とりいそぎ、英語設定にしておきます。
Scene Builderをインストールしたフォルダの下のAppフォルダにSceneBuilder.cfgというファイルがあるので、これを編集してJVMオプションの項目に-Duser.language=enを追加します。

[JVMOptions]
--add-opens
javafx.fxml/javafx.fxml=ALL-UNNAMED
-Duser.language=en

ただ、恐らくパーミッションがなくて保存できないので、どこか別のところで保存して上書きコピーするか、Usersに変更のパーミッションを設定します。
f:id:nowokay:20200716011925p:plain

そうすると、メニューが英語で表示されるようになりました。
f:id:nowokay:20200716011613p:plain

日本語で表示したい場合には、検索するといろいろ出てくるのでそこの手順に従うといいと思います。
SceneBuilder 11 の文字化けを直す - Qiita

やってることは同じですが、コマンドからJarファイルを操作して対処するほうが正統っぽいやりかたです。 SceneBuilder 11で日本語が文字化けする事象の修正方法 - タツノオトシゴのブログ

ボタンを置いてみる

Scene Builderが使えるようになったので、ボタンを配置してみましょう。
ControlsからButtonを選んで一番下においてみます。
f:id:nowokay:20200716012531p:plain

保存してFXMLファイルを確認するとButtonが追加されているのがわかります。
f:id:nowokay:20200716012605p:plain

実行するとボタンが表示されていますね。ただ、ここではボタンを押してもなにも起きません。
f:id:nowokay:20200716012630p:plain

ということで、ボタンを押したときの処理として次のようなメソッドをPrimariController.javaに追加します。

    @FXML
    private void buttonAction() {
        System.out.println("Hello");
    }

そうすると、Scene BuilderでOn Actionに設定できるようになります。
f:id:nowokay:20200716012836p:plain

FXMLはこんな感じになります。
f:id:nowokay:20200716012921p:plain

実行すると、ボタンを押したときにHelloとコンソールに表示されるようになりました。
f:id:nowokay:20200716012949p:plain

コンポーネントの操作

最後に、コンポーネントから値を読み取ったり値を設定したり、コンポーネントの操作を行ってみます。

TextFieldとTextAreaを置いてみます。
f:id:nowokay:20200716024503p:plain

TextFieldとButtonを横に並べたいのだけど、全体がVBOXになっているので、ここにHBOXをいれて横にコンポーネントが並べれるようにしています。
f:id:nowokay:20200716024549p:plain

TextFieldとTextAreaを扱うフィールドを追加して、@FXMLアノテーションを付けておきます。

    @FXML
    private TextField textField;
    
    @FXML
    private TextArea textArea;

importなどはこんな感じになります。ctrl+shift+i で補完できます。 f:id:nowokay:20200716024754p:plain

そうするとScene Builderのほうでfx:idに設定できるようになります。対応するものを設定します。
f:id:nowokay:20200716025031p:plain

ボタンを押したときの処理を書き換えます。

    @FXML
    private void buttonAction() {
        textArea.appendText(textField.getText() + "\n");
    }

実行すると、テキストフィールドになにか入力してボタンを押すとテキストエリアに表示されるようになりました。
f:id:nowokay:20200716025917p:plain

ということで、あとはいろいろコントロールを追加したり処理を追加したりしてアプリケーションを作っていくことになりますね。

JavaFXのWebViewでSeleniumみたいなWebテストやってみたら面白かったんだけど

JavaFX2.0のWebViewで、Javaからブラウザが操作できるようになって、これをSeleniumが組み込んだらおもしろいことになるだろうなと思ってたのですが、よくよく考えると、SeleniumナシでWebサイトのUIテストが簡単に書けることに気づきました。


ということで、まずはテスト対象のサイトをつくってみます。
最初の画面(first.html)。テキストフィールドがあって、OKボタンを押すと「ほんと?」という確認ダイアログがでて、「OK」を押すと次の画面に行きます。

<!DOCTYPE html>
<html>
    <head>
        <title>テスト画面</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <h1>テスト画面</h1>
        <form id="myform" action="next.jsp" method="post"
              onsubmit="return confirm('ほんと?')">
            <input type="text" name="param" id="param">
            <input type="submit" value="OK">
        </form>
    </body>
</html>


で、その遷移先の画面(next.jsp)。入力された文字を表示します。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("utf-8"); %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>結果よ</title>
    </head>
    <body>
        <h1>結果よ</h1>
        <div id="result">${param['param']}でした</div>
    </body>
</html>


さて、これをテストするプログラムを書いてみます。ソースは最後に貼っておきます。
実行すると、first.htmlが表示されて、自動的にテキストフィールドに文字が入力されます。


で、画面が遷移します。


このとき、遷移先URL、タイトル、メッセージ文字列を確認します。

フォーム取得:成功
遷移:成功
タイトル:成功
結果:成功


Seleniumっぽいことができました!


Seleniumってブラウザ表示させるので、起動が重かったり結構時間がかかるのですけど、かなり軽くWebテストができます。
あと、プログラム工夫すれば、通らなかったテストケースを画面キャプチャして確認できるようにしたり、便利な感じにできます。
画面を2つ表示して別々のユーザーでログインさせて、互いの操作が反映するか確認するっていうテストはSeleniumではできなかったのですが、それもできそう。
しかもこれ、WebViewで画面に表示する必要はなくて、WebEngineだけ準備すればいいです。Seleniumのテストは画面が表示されて、結構うっとおしかったので、定期自動テストでもだいじょうぶ。


ただ、本来は確認ダイアログが出るはずなのだけど、それは出ませんでした。
WebEngineにsetConfirmHandlerとかそれっぽいメソッドがあるのですけど、呼び出されてくれません。
あと、なぜか何回かに1度JavaScriptのパースエラーが出たり、処理終了後に例外メッセージが出てたり、いまの段階では動作が安定しているとはいえません。まあ、ベータなので本番リリースまでに直ってくれればいいのですけど。


というわけでソースです。
いつもどおり、コンパイルや実行にはJavaFX2.0ベータのjfxrt.jarをクラスパスに含めます。64bit Windowsでも32bit JDKで動かす必要があります。

続きを読む