如何解析/映射JavaFX CSS文件以检索其属性和值? [英] How to parse/map JavaFX CSS file to retrieve its properties and values?
问题描述
我的应用程序允许用户使用自定义CSS主题来设置界面样式.我有几个非常简单的预置主题"可供选择,只有3个属性.
示例CSS:
.root{
-fx-background: #325c81;
-fx-default-button: #77a3ca;
-fx-base: #a7c4dd;
}
该应用程序具有3个ColorPicker
控件,这些控件需要允许用户为每个属性选择一种颜色并将其保存回CSS文件.
我实际上写CSS文件没有问题,但是我找不到解析.css
文件的方法,以便用.css
文件中的值设置ColorPicker
控件的值. /p>
基本程序流程
1)用户从ComboBox
中选择一个预制主题:
cboPresetTheme.valueProperty().addListener((observable, priorTheme, newTheme) -> {
Utility.applyTheme(cboPresetTheme.getScene(), newTheme);
});
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());
}
3)用应用的StyleSheet
中的值更新3个ColorPicker
控件:
cpBackground.setValue(Color.valueOf(cssFileBackground));
cpBase.setValue(Color.valueOf(cssFileBase));
cpDefaultButton.setValue(Color.valueOf(cssFileDefaultButton));
虽然我对第1步和第2步没有问题. 2,我不知道如何处理步骤3.
我看过其他CSS解析器库(谢谢Google),但它们似乎更适合站立式CSS,并且不支持FX属性. StackExchange问题
一个答案建议使用 CSS解析器来完成此操作,但是由于很少了解文档(还有什么超出我目前的理解水平),我不知道从哪里开始.
我知道目前可能没有标准的API可以完成此任务,但我希望那里可能有一个我找不到的简单库或解决方案.
有几种方法可以解决将CSS声明转换为Color的问题.
设置辅助节点样式
这很简单,但是很有效:想法是您可以设置具有相同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);
}
}
其中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;
}
使用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);
}
}
其中style.css
是您的CSS文件:
.root {
-fx-background: #325c81;
-fx-default-button: #77a3ca;
-fx-base: #a7c4dd;
}
使用JavaFX CSSParser
如果您正在寻找CSSParser,为什么不只使用JavaFX中包含的那个,即您实际用于将样式应用于应用程序的那个呢?
它在 其中 My application allows users to use custom CSS themes to style the interface. I have several pre-built "themes" available to choose from that are very simple, with only 3 properties. Sample CSS: The application has 3 I have no problem with actually writing the CSS file, but I cannot find a way to parse the Basic Program Flow 1) User selects a premade theme from 2) The associated 3) The 3 While I have no problem with steps 1 & 2, I do not know how to process step 3. I have looked at other CSS Parser libraries (thank you, Google) but they seem more geared toward stand CSS and don't support FX properties. The StackExchange question edit or parse FX-CSS file programmatically appears to be asking the same question but it was never successfully answered. One answer suggests using CSS Parser to accomplish this, but as there is little to know documentation (and what is there is beyond my current comprehension level), I don't know where to begin. I understand there may not be a standard API currently available to accomplish this, but I was hoping there may be a simple library or solution out there that I have been unable to find. There are several ways you can tackle the conversion of a CSS declaration into a Color. Style an auxiliar node This is quite simple, but effective: The idea is that you could just style the background color of a node with the same css, and then set the colorPicker value with that color. The only thing you need to take into account in this case is that the node is styled only when is added to a scene. So you have to add the node to the scene. Adding a node with 0x0 size won't cause any issue, but maybe you don't want it to be there, so you can use an auxiliar scene. where Use StylableProperties A similar, more elegant solution is found here. It uses Basically it is the same idea as the one above, maybe more clean, as you don't need to modify your css file. Using where Use JavaFX CSSParser If you are looking for a CSSParser, why don't you just use the one included in JavaFX, the one you actually use to apply styling to your app? It is under With it you can parse the css file and retrieve any parsed value easily. where
这篇关于如何解析/映射JavaFX CSS文件以检索其属性和值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!com.sun.javafx.css.parser.CSSParser
下,如果答案是您不想使用私有API,那么好消息是它将成为style.css
是您的CSS文件:.root {
-fx-background: #325c81;
-fx-default-button: #77a3ca;
-fx-base: #a7c4dd;
}
.root{
-fx-background: #325c81;
-fx-default-button: #77a3ca;
-fx-base: #a7c4dd;
}
ColorPicker
controls that need to allow users to select a color for each of those properties and save back to the CSS file..css
file in order to set the values of the ColorPicker
controls with the values from the .css
file.ComboBox
:cboPresetTheme.valueProperty().addListener((observable, priorTheme, newTheme) -> {
Utility.applyTheme(cboPresetTheme.getScene(), newTheme);
});
.css
file is loaded and applied to the current 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());
}
ColorPicker
controls are updated with the values from the applied StyleSheet
:cpBackground.setValue(Color.valueOf(cssFileBackground));
cpBase.setValue(Color.valueOf(cssFileBase));
cpDefaultButton.setValue(Color.valueOf(cssFileDefaultButton));
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);
}
}
style.css
is:.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
to create a node, that you can style with a custom -named-color
property, and then adds this helper
node to the main scene.CssToColorHelper
, your code will be like this: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);
}
}
style.css
is your css file:.root {
-fx-background: #325c81;
-fx-default-button: #77a3ca;
-fx-base: #a7c4dd;
}
com.sun.javafx.css.parser.CSSParser
, and if the answer is you don't want to use private API, the good news is that it will be public API in JavaFX 9. 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
is your css file:.root {
-fx-background: #325c81;
-fx-default-button: #77a3ca;
-fx-base: #a7c4dd;
}