2017-03-05 3 views
1

私のアプリケーションでは、カスタムCSSテーマを使用してインターフェイスをスタイルすることができます。私はいくつかの事前に構築された "テーマ"を選択することができますが、これは3つのプロパティだけで非常にシンプルです。JavaFX CSSファイルを解析してマップしてプロパティと値を取得する方法は?

サンプルCSS:

.root{ 
    -fx-background: #325c81; 
    -fx-default-button: #77a3ca; 
    -fx-base: #a7c4dd; 
} 

アプリケーションは、ユーザーがこれらのプロパティのそれぞれの色を選択し、CSSファイルに戻って保存できるようにする必要が3つのColorPickerコントロールがあります。

私は実際にCSSファイルを書き込んで何の問題もないが、私は.cssファイルからの値でColorPickerコントロールの値を設定するために.cssファイルを解析する方法を見つけることができません。関連する.cssファイルが現在のSceneにロードされ、適用される

cboPresetTheme.valueProperty().addListener((observable, priorTheme, newTheme) -> { 
       Utility.applyTheme(cboPresetTheme.getScene(), newTheme); 
      }); 

2):

public static void applyTheme(Scene scene, Theme theme) { 
    scene.getStylesheets().clear(); 

    File css = new File("themes/" + theme.getFileName()); 
    File fontFile = new File("themes/Font.css"); 

    scene.getStylesheets().addAll(
      css.toURI().toString(), 
      fontFile.toURI().toString()); 
} 

基本的なプログラムの流れ

1)ユーザーはComboBoxから既成のテーマを選択し、

3)3 ColorPickerコントロールは適用StyleSheetからの値で更新:

cpBackground.setValue(Color.valueOf(cssFileBackground)); 
cpBase.setValue(Color.valueOf(cssFileBase)); 
cpDefaultButton.setValue(Color.valueOf(cssFileDefaultButton)); 

私は手順1 & 2で何の問題もありませんが、私はステップ3

を処理する方法がわからない、私は他のCSSパーサライブラリ(見てきましたありがとう、グーグル)、彼らはスタンドCSSに向いていて、FXのプロパティをサポートしていないようだ。 StackExchangeの質問edit or parse FX-CSS file programmaticallyは同じ質問をしているようですが、決してうまく答えられませんでした。

これを達成するには、CSS Parserを使用することをお勧めしますが、ドキュメントを知っていることはほとんどなく(現在の理解レベルを超えています)、どこから始めるべきかわかりません。

これを達成するために現在利用可能な標準的なAPIがないかもしれないことは理解していますが、そこには簡単なライブラリや解決策が見つからないことがあります。

答えて

3

CSS宣言のColorへの変換にはいくつかの方法があります。

スタイルAUXILIARノード

これは非常にシンプルですが、効果的である:アイデアはあなただけ同じCSSを使用したノードの背景色のスタイルを設定し、その色でColorPickerの値を設定することができることです。

このケースで考慮する必要があるのは、ノードがシーンに追加されたときにのスタイリングだけであることです。

ノードをシーンに追加する必要があります。0x0サイズのノードを追加しても問題は発生しませんが、おそらくそれがそこに存在しないようにすることで、より使いやすいシーンを使用することができます。

.root { 
    -fx-background: #325c81; 
    -fx-default-button: #77a3ca; 
    -fx-base: #a7c4dd; 
} 

.value1 { 
    -fx-background-color: -fx-background; 
} 
.value2 { 
    -fx-background-color: -fx-default-button; 
} 
.value3 { 
    -fx-background-color: -fx-base; 
} 

使用StylableProperties

同様の、よりエレガントな解決策は、here見出される:style.css

public class CSSParsingApp extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     ColorPicker cpBackground = new ColorPicker(retrieveColor("value1")); 
     ColorPicker cpBase = new ColorPicker(retrieveColor("value2")); 
     ColorPicker cpDefaultButton = new ColorPicker(retrieveColor("value3")); 

     VBox root = new VBox(10, cpBackground, cpDefaultButton, cpBase); 
     root.setAlignment(Pos.CENTER); 

     Scene scene = new Scene(root, 300, 250); 
     scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm()); 

     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    private Color retrieveColor(String value) { 
     Pane pane = new Pane(); 
     pane.getStyleClass().add(value); 

     Scene sceneAux = new Scene(pane); 
     sceneAux.getStylesheets().add(getClass().getResource("style.css").toExternalForm()); 
     pane.applyCss(); 
     return (Color) pane.getBackground().getFills().get(0).getFill(); 
    } 

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

} 

StylablePropertiesを使用して、カスタムの-named-colorプロパティでスタイルを設定できるノードを作成し、このhelperノードをメインシーンに追加します。

基本的には、あなたのCSSファイルを変更する必要がないので、上記のアイデアと同じで、おそらくもっとクリーンです。 CssToColorHelperを使用して

、あなたのコードは次のようになります。

.root { 
    -fx-background: #325c81; 
    -fx-default-button: #77a3ca; 
    -fx-base: #a7c4dd; 
} 

使用のJavaFXあなたが探している場合CSSParser

style.cssあなたのCSSファイルが

public class CSSParsingApp extends Application { 

    private CssToColorHelper helper = new CssToColorHelper(); 

    @Override 
    public void start(Stage primaryStage) { 
     ColorPicker cpBackground = new ColorPicker(); 
     ColorPicker cpBase = new ColorPicker(); 
     ColorPicker cpDefaultButton = new ColorPicker(); 

     VBox root = new VBox(10, cpBackground, cpDefaultButton, cpBase, helper); 
     root.setAlignment(Pos.CENTER); 

     Scene scene = new Scene(root, 300, 250); 
     scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm()); 

     cpBackground.setValue(getNamedColor("-fx-background")); 
     cpDefaultButton.setValue(getNamedColor("-fx-default-button")); 
     cpBase.setValue(getNamedColor("-fx-base")); 

     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    private Color getNamedColor(String name) { 
     helper.setStyle("-named-color: " + name + ";"); 
     helper.applyCss(); 

     return helper.getNamedColor();  
    } 
    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     launch(args); 
    } 
} 

ですCSSParser、JavaFXに含まれているものを使ってみてくださいあなたのアプリに送るのですか?

com.sun.javafx.css.parser.CSSParserの下にあります。答えがプライベートAPIを使用したくない場合は、JavaFX 9の公開APIになることをお勧めします。

これで、CSSファイルを解析して、解析された値を簡単に取得できます。

public class CSSParsingApp extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     ColorPicker cpBackground = new ColorPicker(); 
     ColorPicker cpBase = new ColorPicker(); 
     ColorPicker cpDefaultButton = new ColorPicker(); 

     VBox root = new VBox(10, cpBackground, cpDefaultButton, cpBase); 
     root.setAlignment(Pos.CENTER); 

     Scene scene = new Scene(root, 300, 250); 
     scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm()); 

     cpBackground.setValue(parseColor("-fx-background")); 
     cpDefaultButton.setValue(parseColor("-fx-default-button")); 
     cpBase.setValue(parseColor("-fx-base")); 

     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    private Color parseColor(String property) { 
     CSSParser parser = new CSSParser(); 
     try { 
      Stylesheet css = parser.parse(getClass().getResource("style.css").toURI().toURL()); 
      final Rule rootRule = css.getRules().get(0); // .root 
      return (Color) rootRule.getDeclarations().stream() 
       .filter(d -> d.getProperty().equals(property)) 
       .findFirst() 
       .map(d -> ColorConverter.getInstance().convert(d.getParsedValue(), null)) 
       .get(); 
     } catch (URISyntaxException | IOException ex) { } 
     return Color.WHITE; 
    } 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     launch(args); 
    } 
} 

style.cssあなたのCSSファイルです:

.root { 
    -fx-background: #325c81; 
    -fx-default-button: #77a3ca; 
    -fx-base: #a7c4dd; 
} 
+0

使用ビルトインCSSParserは有望に見える、ありがとうございました!しかし、私は 'NullPointerException'を ' Stylesheet css = parser.parse(Utility.class.getResource(cssFile).toURI()。toURL()); '私の 'cssFile'は問題の' .css'ファイルに文字列として渡されています。 – Zephyr

+0

'Utility'クラスと同じパスの下に有効な' cssFile'があることを確認してください。また、catchの中に 'ex.printStackTrace()'を置くことで、その例外の理由を知ることができます。 –

+0

私はそれが 'Utility.class'がnullであること(Stringがうまくチェックアウトする)と関係があると仮定しています。私はパーザを 'Static'メソッドに入れているので、' getClass() 'を使うことはできません。 – Zephyr

関連する問題