Zep*_*hyr 4 css java parsing javafx
我的应用程序允许用户使用自定义 CSS 主题来设计界面样式。我有几个预构建的“主题”可供选择,它们非常简单,只有 3 个属性。
示例 CSS:
.root{
-fx-background: #325c81;
-fx-default-button: #77a3ca;
-fx-base: #a7c4dd;
}
Run Code Online (Sandbox Code Playgroud)
该应用程序有 3 个ColorPicker控件,需要允许用户为每个属性选择颜色并将其保存回 CSS 文件。
我实际编写 CSS 文件没有问题,但我找不到解析.css文件的方法,以便使用文件中的值设置ColorPicker控件的值.css。
基本程序流程
1) 用户从ComboBox以下选项中选择一个预制主题:
cboPresetTheme.valueProperty().addListener((observable, priorTheme, newTheme) -> {
Utility.applyTheme(cboPresetTheme.getScene(), newTheme);
});
Run Code Online (Sandbox Code Playgroud)
2) 关联.css文件被加载并应用到当前Scene:
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());
}
Run Code Online (Sandbox Code Playgroud)
3) 使用ColorPicker来自应用的值更新3 个控件StyleSheet:
cpBackground.setValue(Color.valueOf(cssFileBackground));
cpBase.setValue(Color.valueOf(cssFileBase));
cpDefaultButton.setValue(Color.valueOf(cssFileDefaultButton));
Run Code Online (Sandbox Code Playgroud)
虽然我对步骤 1 和 2 没有问题,但我不知道如何处理步骤 3。
我查看了其他 CSS Parser 库(谢谢,谷歌),但它们似乎更适合支持 CSS 并且不支持 FX 属性。StackExchange 问题以编程方式编辑或解析 FX-CSS 文件似乎在问同样的问题,但从未成功回答过。
一个答案建议使用CSS Parser来完成此操作,但由于对文档知之甚少(以及超出我当前理解水平的内容),我不知道从哪里开始。
我知道目前可能没有可用的标准 API 来实现这一点,但我希望可能有一个我找不到的简单库或解决方案。
有几种方法可以处理 CSS 声明到颜色的转换。
设置辅助节点的样式
这很简单,但很有效:这个想法是,您可以使用相同的 css 设置节点的背景颜色,然后使用该颜色设置 colorPicker 值。
在这种情况下,您唯一需要考虑的是节点仅在被添加到场景时才会被设置样式。
所以你必须将节点添加到场景中。添加一个大小为 0x0 的节点不会造成任何问题,但也许您不希望它在那里,因此您可以使用辅助场景。
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);
}
}
Run Code Online (Sandbox Code Playgroud)
在哪里style.css:
.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;
}
Run Code Online (Sandbox Code Playgroud)
使用 StylableProperties
一个类似的、更优雅的解决方案可以在这里找到。它用于StylableProperties创建一个节点,您可以使用自定义-named-color属性对其进行样式设置,然后将此helper节点添加到主场景中。
基本上它与上面的想法相同,也许更干净,因为您不需要修改您的 css 文件。
使用CssToColorHelper,您的代码将是这样的:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
style.css你的css文件在哪里:
.root {
-fx-background: #325c81;
-fx-default-button: #77a3ca;
-fx-base: #a7c4dd;
}
Run Code Online (Sandbox Code Playgroud)
使用 JavaFX CSSParser
如果您正在寻找 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);
}
}
Run Code Online (Sandbox Code Playgroud)
style.css你的css文件在哪里:
.root {
-fx-background: #325c81;
-fx-default-button: #77a3ca;
-fx-base: #a7c4dd;
}
Run Code Online (Sandbox Code Playgroud)