問題
JavaFXアプリケーションを作成する際に、画面のレイアウトをFXMLで記述、色やフォントなどの見栄えをCSSファイルに記述し、FXMLのルートノードにCSSファイルを指定しました。
模式的なソースファイル構成は次のようになります。
myapp +-- src +-- mypackage +-- MyApp.java +-- MyApp.fxml +-- MyApp.css
MyApp.javaの中でFXMLファイルを読み込みます。
Parent root = FXMLLoader.load(getClass().getResource("MyApp.fxml")); Scene scene = new Scene(root);
MyApp.fxml の中でCSSファイルを指定します。
<HBox stylesheets="@MyApp.css" xmlns=...>
このアプリケーションをビルドすると、CSSファイルは他のクラスファイル等と一緒にJARファイルまたはjlinkでモジュールファイルに含まれます。
このアプリケーションを実行するマシンに配布したあとに、画面の見栄えをカスタマイズしようとCSSファイルを取り出して編集、再組み込みすることは簡単ではありません。
JARファイルならzipアーカイブツールでCSSファイルを取り出し編集後再度JARファイルに戻すことは可能です(かなり面倒です)。
jlinkのモジュールファイルの場合、zipではないので取り出し編集は困難です。
そこで、ビルド時にJARファイルまたはモジュールファイルに組み込まれるデフォルトの設定を記述したCSSファイルとは別に、独立したCSSファイルをアプリケーション実行時に読み込み反映する方法を探ってみました。
sceneに別CSSファイルを設定するも反映されず
カレントディレクトリにMyCustom.cssファイルが存在すればそれをSceneのスタイルシートとして設定するコードを追加しました。
Path path = Paths.get("MyCustom.css"); if (Files.exists(path)) { scene.getStylesheets().add(path.toUri().toString()); }
しかし、これではMyCustom.cssに記述したカスタム設定が反映されませんでした。
このコードでは、SceneとそのrootノードのHBoxにそれぞれ別のスタイルシートが設定されます。
Scene ---> MyCustom.css +-- HBox ---> MyApp.css
試行錯誤と資料調査をしたところ、JavaFXのドキュメント「JavaFX CSS Reference Guide」に次の記述を見つけました。
Style sheets from a Parent instance are considered to be more specific than those styles from Scene style sheets.