プロジェクト

全般

プロフィール

JavaFXのTips

オブジェクト参照

ウィンドウ関係のオブジェクト参照

stageの参照を取得したい

ダイアログ表示等で、stageの参照を必要とする箇所がありますが、FXMLと一緒に生成されるコントローラーではstageの参照を保持していません。

コントロールからシーンを辿ってstageを取得
    private Stage getStage() {
        return (Stage) label.getScene().getWindow();
    }

ただし、初期化中(例えば、コントローラのinitializeメソッド中)でこの処理を実行すると、まだsceneがstageに登録されていないため、NullPointerExceptionが発生します。
イベントハンドラーの中で呼び出すようにします。

または次のTipsを参照ください。

sceneの参照を取得したい

FXMLと対になるコントローラーのinitializeメソッドは、ルートノードがまだsceneにセットされる前に(FXMLLoaderでロードされる時点で)実行されます。

NodeクラスのsceneProperty を使うと、sceneがノードにセットされたタイミングを取れるので、initializeメソッドの中でscenePropertyの変化をイベントとして受け取り処理を記述することで、scene参照を利用する処理を書くことができます。

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        root.sceneProperty().addListener((observable, oldScene, newScene) -> {
            if (newScene != null) {
                // scene がセットされた
            }
        }); 
        :
  • このタイミングでsceneのgetWindow()を呼ぶと、まだsceneがStageにセットされる前なのでgetWindow()がnullを返します。initializeメソッド内で上述のコードでsceneを取得し、インスタンスフィールドに格納、Stageを使う段階でインスタンスフィールドのsceneからgetWindow()で取得します。

FXMLLoader生成後にstageをセット

Application派生クラスのstartメソッドの実装で、FXMLLoaderを使ってFXMLファイルをロードするときに、コントローラにstageをセットします。

public class MyApplication extends Application {
    public void start(Stage stage) throws Exception {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("MyView.fxml"));
        Parent root = loader.load();
        MyController controller = loader.getController();
        controller.setState(stage);
        :
    }
    :
}

Controllerには、あらかじめsetStageメソッドを定義しておきます。

public class MyController {
    :
    private Stage stage;
    public void setStage(Stage stage) {
        this.stage = stage;
    }
    :
}

スタイルシート

テーマ

JavaFXには、全体のルック・アンド・フィールを定義する、SwingでいうLook & Feelに相当するThemeがあります。

定義済みテーマの指定

JavaFX 2では、Caspianと呼ばれるテーマがデフォルトでした。JavaFX 8ではModenaと呼ばれるテーマがデフォルトです。これは次のコードのように変更できます。

public class MyApplication extends Application {
    :
    @Override
    public void start(Stage stage) throws Exception {
        setUserAgentStylesheet(STYLESHEET_CASPIAN);
        :
    }
    :
}

Applicationクラスには、次の2つの定数が定義されています(Java SE 8)。
  • STYLESHEET_CASPIAN
  • STYLESHEET_MODENA

スタイルシートの指定

画面全体に適用するスタイルシートの指定

APIで指定

APIで指定する場合、Sceneインスタンスに設定します。

Scene scene = ...
scene.getStylesheets().addAll("alfa.css", "bravo.css");

ただし、ここで指定する文字列はURLである必要があります。カレントディレクトリに置いても認識されません。次のようにエラーとなってしまいます。

8 01, 2014 10:27:26 午前 com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
警告: Resource "alfa.css" not found.

上記コード例のように指定する場合、クラスパスのルート直下に置きます。
NetBeansのantプロジェクトではsrcフォルダ直下に置くことで、ビルド時にjarファイルのルートに配置されます。

FXMLで指定

FXMLで指定する場合、FXMLルートコンテナの子要素に記述します1

<BorderPane>
  :
  <stylesheets>
    <URL value="@alfa.css"/>
    <URL value="@bravo.css"/>
  </stylesheets>
</BorderPane>

パスなしでファイル名を指定するときは、このFXMLと同じ場所に置きます。

SceneBuilderで指定する場合、ルートコンテナのプロパティからJavaFX CSSグループのStylesheetsに指定します。次にSceneBuilderの指定画面(部分抜粋)を示します。

stylesheet_scenebuilder-1.png

参考

JavaFX 2で始めるGUI開発 第9回 CSSによるスタイリング

レイアウト

画像

画像生成

シーンを画像に出力したい(画面キャプチャ)

  WritableImage snapshot = scene.snapshot(null);
  ImageIO.write(SwingFXUtils.fromFXImage(snapshot, null), "png", new File("scene.png"));

画像読み込み

ファイルから画像を読み込みたい

Imageクラスを使います。
InputStreamまたは文字列でURLを指定します。

  • カレントディレクトリにあるファイルをURLで指定する場合
    new Image("file:clockDial.png")

座標変換

拡大・縮小

ノードの左上位置を固定して拡大・縮小したい

あるノードに対して、scaleX()やscaleY()メソッドを呼び拡大または縮小すると、そのノードの中心の位置が拡大縮小の中心となります。

ここで、ノードの配置で左上隅の位置を保ったまま拡大縮小させるときは、拡大縮小の中心点(pivot)を、ノードの左上隅(通常は(0,0))に指定します。ただし、scaleXやscaleYメソッドにはpivotを指定する方法がないので、Scaleインスタンスを作って、ノードにgetTransforms().add(scale) で設定します。


3ヶ月前に更新