I am building a small password manager using JavaFX and currently working on make it easy to change the color theme. For that, I declared variables containing the hexcodes of different colors and saved’em in a stylesheet called "utility.css". This stylesheet is imported in two different stylesheets and the variables are called as described here.
Somehow I get this error while parsing:
Feb. 21, 2023 5:32:48 PM javafx.css.CssParser parse
WARNING: CSS Error parsing file:/G:/.../Coding/.../target/classes/css/utility.css: Expected RBRACE at [3,4]
Feb. 21, 2023 5:32:48 PM javafx.css.CssParser term
WARNING: CSS Error parsing file:/G:/.../Coding/.../target/classes/css/login-menu.css: Unexpected token '-' at [4,30]
Feb. 21, 2023 5:32:48 PM javafx.css.CssParser term
WARNING: CSS Error parsing file:/G:/.../Coding/.../target/classes/css/login-menu.css: Unexpected token '-' at [4,30]
Feb. 21, 2023 5:32:48 PM javafx.css.CssParser reportException
WARNING: Please report java.lang.NullPointerException at:
javafx.graphics@19/javafx.css.CssParser.term(CssParser.java:4689)
javafx.graphics@19/javafx.css.CssParser.expr(CssParser.java:4583)
javafx.graphics@19/javafx.css.CssParser.declaration(CssParser.java:4554)
javafx.graphics@19/javafx.css.CssParser.declarations(CssParser.java:4472)
javafx.graphics@19/javafx.css.CssParser.parse(CssParser.java:3981)
javafx.graphics@19/javafx.css.CssParser.parse(CssParser.java:253)
javafx.graphics@19/javafx.css.CssParser.parse(CssParser.java:241)
I already asked chatGPT but seems there are things, AI can’t help us with (yet) 😀
This is the code of the "utility.css"-file, where I declared the variables
:root {
--maincolor: #2b284d;
--backgrounddark: #2b284d;
--backgroundlight: #5a4f7d;
--panel: #3c325c;
--panelhighlighted: #503d6b;
--panelselected: #503d6f;
--casualbutton: #2b284d;
--casualbuttonhighlighted: #5d5478;
--crucialbuttonhightled: #eb5b0e;
--textfield: #2b288d;
--textfill: #b5b5b5;
}
and this of the two stylesheets:
@import "utility.css";
.combo-box .list-cell:filled:selected {
-fx-background-color: var(--panelhighlighted);
-fx-text-fill: #b5b5b5 ;
-fx-font-family: "Calibri Light" ;
-fx-font-size: 17;
-fx-background-radius: 20px;
}
.combo-box .combo-box-popup .list-view, .combo-box .combo-box-popup .list-cell {
-fx-background-color: var(--panel);
-fx-text-fill: var(--textfill) ;
-fx-font-family: "Calibri Light" ;
-fx-font-size: 17;
-fx-background-radius: 20px;
}
.combo-box .combo-box-popup .list-cell:hover {
-fx-text-fill: var(--textfill);
-fx-background-color: var(--panelhighlighted);
}
.password-field {
-fx-text-fill: #b5b5b5 ;
-fx-prompt-text-fill: #b5b5b5 ;
}
.anchor-pane {
overflow:hidden;
-fx-background-color: #2b284d;
}
and
@import "utility.css";
.list-cell:filled:selected:focused, .list-cell:filled:selected {
-fx-background-color: var(--panelselected);
}
.list-cell:filled:hover {
-fx-background-color: var(--panelhighlighted);
}
.list-cell {
-fx-background-color: var(--panel);
-fx-pref-height: 60;
-fx-background-radius: 20px;
-fx-background-insets: 0;
-fx-text-fill: var(--textfill) ;
-fx-font-family: "Calibri Light" ;
-fx-font-size: 20;
-fx-alignment: center-left;
}
.list-view {
-fx-background-color: var(--backgrounddark);
-fx-border-color: var(--backgrounddark);
-fx-background-insets: 0;
-fx-padding: 0px;
}
.password-field {
-fx-text-fill: var(--textfill) ;
-fx-prompt-text-fill: var(--textfill) ;
-fx-background-radius: 20px;
-fx-background-color: var(--textfield);
}
.label {
-fx-text-fill: var(--textfill);
-fx-background-color: var(--textfield);
}
So I tried to eliminate ‘-‘ in the variable names, because these are used in css as the start of a command or sth but this didn’t work out.
I also tried an online css debugging tool, which only said I should switch the import statement with something called link to improve performance, which is not important for me atm.
I have absolutely no idea, what’s the problem here. I am using IntelliJ 2022.3.1 (Ultimate Edition).
The error happens at runtime, before that, IntelliJ doesn’t complain at all and even auto-completes my variable names in the stylesheets, so they are definitely there and definitely correct.
The error appears to happen, when the css parser reaches the firtst ‘-‘ in the first stylesheet that calls a variable, as if this may not happen there.
>Solution :
Glancing quickly at the CSS Specification, it looks like a valid identifier can only have a single hyphen at the start:
Macro Definition ident [-]?{nmstart}{nmchar}* name {nmchar}+ nmstart [_a-z]|{nonascii}|{escape}
The : in a selector signifies a pseudoclass, which I don’t think is what you want here. If you want the looked-up colors to be applied to the root pane and inherited by everything in the application, use the class selector for the root (.root).
I did a quick test with all the looked-up color names renamed to a start with a single hyphen, and changed the selector to select the root:
.root {
-maincolor: #2b284d;
-backgrounddark: #2b284d;
-backgroundlight: #5a4f7d;
-panel: #3c325c;
-panelhighlighted: #503d6b;
-panelselected: #503d6f;
-casualbutton: #2b284d;
-casualbuttonhighlighted: #5d5478;
-crucialbuttonhightled: #eb5b0e;
-textfield: #2b288d;
-textfill: #b5b5b5;
}
Note that CSS naming conventions recommend separating words with hyphens, so your looked-up color names should probably be something like -main-color, etc. You might also consider putting a vendor prefix on them to avoid name collisions.
There is no need for var(...) in the CSS referencing a looked-up color. Just reference these directly. See the JavaFX CSS documentation.
I tested this with a CSS stylesheet style.css as follows:
@import "utility.css";
.label {
-fx-background-color: -backgrounddark;
}
and ran it with IntelliJ’s "default" JavaFX template (which I included below), and it worked as expected with no errors.
HelloApplication.java:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
HelloController.java:
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class HelloController {
@FXML
private Label welcomeText;
@FXML
protected void onHelloButtonClick() {
welcomeText.setText("Welcome to JavaFX Application!");
}
}
and hello-view.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Button?>
<VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml"
fx:controller="org.jamesd.examples.csstest.HelloController">
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
</padding>
<Label fx:id="welcomeText"/>
<Button text="Hello!" onAction="#onHelloButtonClick"/>
</VBox>