OSGiバンドル内のJavaFXスタイルシート
質問
私は私のバンドルのルートに "styles.css"を置き、そしてコードでそれをリンクする方法を見つけようとしています。問題は@ .getStylesheets()があるということです。追加(_)はURLではなく文字列を取ります。そのため、私が知っているすべてのアプローチはここで失敗しています:
撮影1:
scene.getStylesheets().add("styles.css");
.
→
Nov 15, 2013 2:04:47 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
WARNING: Resource "styles.css" not found.
.
テイク2:
scene.getStylesheets().add(this.getClass().getResource("styles.css").toExternalForm());
.
→
NullPointerException
.
テイク3:
scene.getStylesheets().add(this.getClass().getClassLoader().getResource("styles.css").toExternalForm());
.
→
Nov 15, 2013 2:27:31 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
INFO: Could not load stylesheet: bundle://5.0:1/styles.css
.
撮影4:
scene.getStylesheets().add(myBundle.getEntry("styles.css").toExternalForm());
.
→
Nov 15, 2013 1:31:35 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
INFO: Could not load stylesheet: bundle://5.0:0/styles.css
.
felix-4.2.1 、 java-8(ビルド1.8.0-EA-B115)、 JavaFX-8(8.0。0-EA-B115)。
解決
最近、この質問の元のポスターと同じエラー/トラブルで実行され、CSS / FXMLを変更したり、TEMPファイルに抽出したりすることなく、それを解決できませんでした。私はここでそれをここに投稿しています。オンラインで良い答えが見つかりませんでした:
私の場合のセットアップは次のとおりです。
バンドル0:
- CSSファイルへの相対パス参照を含むeffiew.fxml
- 画像への相対パス参照があるsomestyle.css
- someimage.png
- resourceLoader.java(CSSおよびFXMLファイルからURLオブジェクトを返す)
バンドル1:
- Bundle0からFXMLローダーを使用してFXMLをロードするための基本的なJavaFXファイル。
問題:
FXMLローダにClassLoaderを設定しても、すべてのCSSとCSS参照画像はFXMLによって無視されたように見えました。 CSSの絶対ファイルパスとCSSで参照されているイメージを使用した場合にのみ機能しました。これは私が欲しいものではありません。
解決策:
このセットアップをOSGiで作業することを禁止するJavaFXには、2つのバグ/デザイン問題があります。
- fxml からのCSSのロード
- CSSからの画像を参照する
最初の問題を解決するには、System Property Binary.cssをfalseに設定して、JavaFXでバイナリCSSファイルを無効にする必要があります。 JavaFXがSmartであることを試み、CSSを言ってもBSSファイルを見つけようとすると、JavaFXにはバグがあります。 OSGiリソースのURLに「バンドル://」がスキーマがないと予想されていないため、フリップします。解決策:
- -dbinary.css= false
2番目の問題を解決するには、CSSイメージが配置されているバンドルのクラスローダにスレッドコンテキストクラスローダを設定し、スレッドコンテキストクラスローダを復元する必要があります。トリックは、CSSがJavaFXによって解釈されるたびにこれを行うことです。これは必ずしも期待しているときには必ずしもそうではありません...
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
try {
final ClassLoader resourcesClassLoader = Resourceloader.class.getClassLoader();
//needed for css
Thread.currentThread().setContextClassLoader(resourcesClassLoader);
this.primaryStage.show();
} finally {
Thread.currentThread().setContextClassLoader(tccl);
}
.
残念ながらこれは私が思い付くことができる最善の解決策です。あらゆる企業アプリケーションが何らかの形でそれらの機能を使用しているとしても、クラスローダーまたは依存挿入念の中にはJavaFXが念頭に置いて行われませんでした。 :(
//編集 CSSから画像にアクセスするためにスレッドコンテキストクラスローダーを設定する必要がないように見えます!
他のヒント
これが機能しない理由はここで説明されています。 JavaFX JIRA RT-14177 。 Ressourceの "Externalform"を使用できないので、入力ストリームを直接読み取ることでTEMPファイルにコピーしました。
InputStream inputStream = MainApp.class.getResourceAsStream("/styles/styles.css");
File tempStyleSheetDest = File.createTempFile("javafx_stylesheet", "");
tempStyleSheetDest.deleteOnExit();
Files.copy(inputStream, tempStyleSheetDest.toPath(), StandardCopyOption.REPLACE_EXISTING);
scene.getStylesheets().add(tempStyleSheetDest.toURI().toString());
.
- CSSファイルを含むバンドルにアクセスできるクラスのClassLoaderを使用していることを確認してください
- 相対パスを使用している場合は、CSSがそのクラス 'パッケージ を基準にしていることを確認してください。
これは、 drombler fx ( drombler fxは、OSGiとMavenに基づくJavaFX用のモジュラーリッチクライアントプラットフォームです。(POM-First)):
ここ:StylesheetsクラスはCSSファイルと同じバンドルにあります。
getClass()getClassLoader()。getResource()toExternalForm()?