ControlsFX 準備編

このEntryは JavaFX Advent Calendar の22日目のエントリーです。

昨日は id:hagi44 さんの 業務で JavaFX をちょっとだけ使ってみた でした。明日は id:yumix_h さんが再び登場です。

なんか、ITproの連載が終わってから、完全にJavaはオフモードになってしまっていますが、久しぶりにblog書くのではてな記法もぜんぜん覚えていないというていたらく。

まぁ、仕事ではJavaJavaFXも使っているので、Javaに触っていないというわけではないのですが...

ということで、今日はControlsFXを紹介しようと思います。

ControlsFX

ControlsFXはJonathan Gilesさんを中心にJavaFXのコントロールを提供するためのプロジェクトです。

ControlsFXのコントロールの中には、DialogのようにJavaFXの標準コントロールに採用されたものもあります。

今年のJavaOneのDuke's Choice Awardも獲得しています!

とことが、JonathanがOracleからMicrosoftに転職してしまったのです!

ということで、Duke's Choice Award受賞記念と、転職のはなむけにControlsFXを紹介していきます!!

ControlsFXが提供しているコントロールおよびその周辺機能としては、以下のようなものがあります。

  • Actions
  • Borders
  • BreadcrumbBar
  • ButtonBar
  • CheckComboBox / CheckListView / CheckTreeView
  • Decoration / Validation
  • Dialogs
  • FXSampler
  • Glyph font pack support
  • GridView
  • HiddenSidesPane
  • HyperlinkLabel
  • InfoOverlay
  • ListSelectionView
  • MasterDetailPane
  • Notifications / NotificationPane
  • PlusMinusSlider
  • PopOver
  • PropertySheet
  • RangeSlider
  • Rating
  • SegmentedButton
  • SnapshotView
  • SpreadsheetView
  • TaskProgressView
  • TextFields
  • Top Quality JavaDocs!
  • Translations

このリストはContorlsFXのサイトからコピペしてきたものなので、私もよくわかっていないものも入ってます ^ ^;;

今日は準備編として、ControlsFXを使えるところまで紹介します。

ダウンロードとサンプルの実行

ControlsFXは現状、2つのバージョンが公開されています。

  • Java SE 9用のControlsFX 9.0.0
  • Java SE 8用のControlsFX 8.40.14

当然、Java SE 9用のControlsFX 9.0.0を使っていきます。

ダウンロードは ダウンロード用のリンク から行います。

ダウンロードするファイルはcontrolsfx-9.0.0.zipです。このファイルを展開すると、ライセンスのテキストとJARファイルが3つあります。

この中のcontrolsfx-samples-9.0.0.jarファイルがサンプルです。さっそく実行してみましょう。

C:\controlsfx-9.0.0>java -jar controlsfx-samples-9.0.0.jar
Initialising FXSampler sample scanner...
        Discovering projects...
                Found project 'ControlsFX', with sample base package 'org.controlsfx.samples'
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by impl.org.controlsfx.ReflectionUtils (file:/C:/controlsfx-9.0.0/controlsfx-9.0.0.jar) to method com.sun.javafx.css.StyleManager.getInstance()
WARNING: Please consider reporting this to the maintainers of impl.org.controlsfx.ReflectionUtils
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

実行はできましたけど、なんか怒られてます。

これはJava SE 9のモジュール化の影響で、隠蔽しているクラスをリフレクションで使用しているために警告されているのです。メッセージにあるように--illegal-access=warnを実行時オプションとして付記すれば、警告はでますが、問題なく実行できます。

逆に--illegal-access=warnを付けないと、実行できたとしても、リフレクションが正常に動作しない部分があるはずです(確かめてないですけど)。

では、--illegal-access=warnを付けて、実行してみましょう。

C:\controlsfx-9.0.0>java --illegal-access=warn -jar controlsfx-samples-9.0.0.jar
Initialising FXSampler sample scanner...
        Discovering projects...
                Found project 'ControlsFX', with sample base package 'org.controlsfx.samples'
WARNING: Illegal reflective access by impl.org.controlsfx.ReflectionUtils (file:/C:/controlsfx-9.0.0/controlsfx-9.0.0.jar) to method com.sun.javafx.css.StyleManager.getInstance()
WARNING: Illegal reflective access by impl.org.controlsfx.ReflectionUtils (file:/C:/controlsfx-9.0.0/controlsfx-9.0.0.jar) to method com.sun.javafx.css.StyleManager.addUserAgentStylesheet(java.lang.String)

先ほどとはメッセージが変わっています。警告はしたけれども、実行できているということです。

実行すると、以下のようなウィンドウが表示されます。

右側の項目を選択すれば、その機能のデモが中央に表示されます。そして、右側に説明が表示されます。

たとえば、Bordersを選択すると、こんな感じ。

こんな感じで動かしてみれば、どういうコントロールが提供されているか分かるはずです。

Scene Builderへの組み込み

コントロールを使うのであれば、Scene Builderで使えなければ!!

ということで、Scene Builderでも使えるようにしてみましょう。

Scene Builderの左側のコントロールのリストの上に歯車アイコンがあります。

そこをクリックすると、下のようなメニューが表示されます。

で、JAR/FXML Managerを選択します。すると、Library Managerダイアログが表示されます。

ローカルにあるJARファイルを追加する場合は3番目の[Add Library/FXML from file system]を選択します。すると、ファイルチューザーが表示されるので、ダウンロードしたcontrolsfx-9.0.0.jarを指定します。

すると、JARファイルに含まれているコントロールが一覧表示されます。

必要なコントロールをチェックして (というか、全部チェックすればOKですが)、[Import Components]を選択すれば、OK。

すると、コントロールの一覧に[Custom]グループが追加されて、そこに今追加したコントロールが表示されます。

Mavenなどのレポジトリからダウンロードすることもできます。その場合は一番上の[Search repositories]もしくは、次の[Manually add Library from repository]を選択します。

[Manually add Library from repository]から説明しましょう。この項目を選択すると、Add Library from Repositoryダイアログが表示されます。

上の図のようにGroup IDにはorg.controlsfx、Artifact IDにはcontrolsfxを指定します。すると、バージョンが選択できるようになるので、9.0.0を選択します。

[Search repositories]の場合、先ほどのGroup IDもしくはArtifact IDをどちらかを入力すると、それに合致するライブラリを表示するので、追加します。

これで、標準のコントロールと同じようにControlsFXのコントロールを使用することができます。

試しに、AnchorPaneにCustomTextFieldを貼ってみたのが、下の図です。

このFXMLはこんな感じになってました。

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<?import org.controlsfx.control.textfield.CustomTextField?>


<AnchorPane prefHeight="200.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <CustomTextField fx:id="textField" layoutX="74.0" layoutY="63.0" promptText="Custom TextField" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="50.0">
         <font>
            <Font size="16.0" />
         </font>
      </CustomTextField>
   </children>
</AnchorPane>

ControlsFXを使用する (非モジュールアプリケーション)

といっても、普通のライブラリと同じです。

ここでは、NetBeansのNightly Buildを使います。

それにしても、NetBeansはいつになったら、Java SE 9に対応したバージョン出してくれるんでしょうねぇ...

試しに、controlsfxdemoというプロジェクトを作成しました。

Mavenのプロジェクトではなく、普通のプロジェクトなので、ライブラリにcontrolsfx-9.0.0.jarを追加してください。

では、先ほどのFXMLをそのまま使ってみます。

メインクラスをnet.javainthebox.fx.ControlsFXDemo、FXMLをControlsFXDemoView.fxml、コントローラクラスをnet.javainthebox.fx.ControlsFXDemoControllerとしました。

プロジェクトの構成はこんな感じ。

ControlsFXDemoクラスはFXMLをロードするだけです。

package net.javainthebox.fx;

import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class ControlsFXDemo extends Application {
    
    @Override
    public void start(Stage stage) throws IOException {
        AnchorPane root = FXMLLoader.load(getClass().getResource("ControlsFXDemoView.fxml"));
        
        Scene scene = new Scene(root);
        
        stage.setTitle("ControlsFX Demo");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

FXMLは先ほどのFXMLにコントローラクラスの指定を加えてます(整形してあります)。

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<?import org.controlsfx.control.textfield.CustomTextField?>

<AnchorPane prefHeight="200.0" prefWidth="400.0" 
            xmlns="http://javafx.com/javafx/9.0.1" 
            xmlns:fx="http://javafx.com/fxml/1" 
            fx:controller="net.javainthebox.fx.ControlsFXDemoController">
   <children>
      <CustomTextField fx:id="textField" 
                       layoutX="74.0" layoutY="63.0" 
                       promptText="Custom TextField" 
                       AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="50.0">
         <font>
            <Font size="16.0" />
         </font>
      </CustomTextField>
   </children>
</AnchorPane>

ControlsFXDemoControllerクラスは、以下の通り。というか、何もやってないです。

package net.javainthebox.fx;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import org.controlsfx.control.textfield.CustomTextField;

public class ControlsFXDemoController implements Initializable {

    @FXML
    private CustomTextField textField;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    
    
}

これで実行してみましょう。

何も問題ないはず。

問題なのは、モジュールアプリケーションにした場合なのですが、それは次回。