Global Stylesheet for your JavaFX Application

You can style your JavaFX Scene by CSS as you can read here and here.All this examples show how to apply a specific Stylesheet to one Scene by using

myScene.getStylesheets().add("path/to/custom.css");

Inside the SceneGraph of this Scene all Nodes will use the defined Stylesheets. But while your Application grows you will normally have more than one Scene. Each Window in JavaFX holds its own Scene. Even if your Application only uses one Stage you will normally have more than one window while every ContextMenu is Window. So if you use custom ContextMenus or a ChoiceBox inside your application this Components will technically be displayed in a separate Window with a new Scene and SceneGraph. But with the code mentioned above only “myScene” will use the custom Stylesheet. The Scene of the ContextMenu will not be affected by this. One trick here is to set the Stylesheet manually to the Scene of the Window:

myContextMenu.getScene().getStylesheets().add("path/to/custom.css");

But this is only a bad workaround and you won’t do this for every ContextMenu. When you use a ChoiceBox you even can’t access the Scene of the popup because this is defined in private methods of the ChoiceBoxSkin.

But there is a way to set a global Stylesheet to all Scenes. By using the JavaFX 8 class StyleManager you can define the default CSS files. The class uses the singleton pattern and can easily accepted. The following code will add a CSS file to all Stylesheets of all Scenes:

StyleManager.getInstance().addUserAgentStylesheet(AQUA_CSS_NAME);

Currently there is one bug with this. The default Stylesheet (currently caspian) is defined inside the StyleManger, too. But the default will not be set until a first Node is created. When adding a additional user defined Stylesheet a Exception is thrown. So to avoid problems you have to set the default CSS before adding a custom one. This can currently only done by calling a private API:

PlatformImpl.setDefaultPlatformUserAgentStylesheet();
StyleManager.getInstance().addUserAgentStylesheet(AQUA_CSS_NAME);

I will open a issue at http://javafx-jira.kenai.com about this behavior.

addition

With the help of Jonathan Giles (see comments) I found a better way without using private APIs. You can easily set the default stylesheet by using “Application.setUserAgentStylesheet(String url)”. If you use null as parameter value the default stylesheet (currently caspian) will be used. So here is the code without using a private API:

Application.setUserAgentStylesheet(null);
StyleManager.getInstance().addUserAgentStylesheet(AQUA_CSS_NAME);

13 Responses to Global Stylesheet for your JavaFX Application

  1. I don’t think I understand. Even with the latest version of JDK 8 (b87), StyleManager is still private api (com.sun.javafx.css.StyleManager). Is there a way to do this without using the private api?

  2. Please help the above :
    Application.setUserAgentStylesheet(null);

    not working.

    It says setUserAgentStylesheet is not a known method.

  3. Hello, I would like to globally override some styles, but can’t seem to figure out how to manage that. Using the code above, I do not see any difference.

    I would like change the default disabled look – as it seems very washed out. I would like it to show disabled, however, not as light as it currently is. If you could provide a sample, I would greatly appreciate it.

    • Yes it is. And therefore you should use
      Application.setUserAgentStylesheet(null);
      StyleManager.getInstance().addUserAgentStylesheet(AQUA_CSS_NAME);

  4. Ok, I don’t understand. Aren’t you still USING StyleManager, a private API? Also when I use

    Application.setUserAgentStylesheet(null);
    StyleManager.getInstance().addUserAgentStylesheet(MY_CSS_NAME);

    my app doesn’t reflect styling in MY_CSS_NAME.

    when I use
    Application.setUserAgentStylesheet(Application.MODENA_STYLE);
    StyleManager.getInstance().addUserAgentStylesheet(MY_CSS_NAME);

    I get what I expect. Using JDK 8_40 on win 8.1

    • I must say I would really like some clarification on this because he is still using StyleManager which did still appear to be part of the non public API as of 8u40 but in 8u51 I am able to use the StyleManager without any errors/warnings by eclipse. I am wondering if this has now been made a part of the public API? I am not sure as I can not find the documentation for the class easily without using Eclipse’s inspecting to read the inline comments, however the class does have the public and final qualifies internally.

      Additionally the following call is not even necessary and it works without it.
      Application.setUserAgentStylesheet(null);
      However the second call only works if you do it after showing the primary stage, it doesn’t work until primaryStage.show() is actually called.
      StyleManager.getInstance().addUserAgentStylesheet(“path/to/global/css/file”);

      I am really unsure of whether to use this class yet or not because it does not seem very well ironed out for public use and I do not want to depend on it. However some clarification would be nice so that people know how to go about attaching a global application style sheet for their application on top of the default style sheets. Having to set a global style sheet manually to all of the stages and scenes is tedious.

      Even Qt framework allows you to stack style sheets onto the default.
      qApp->setStyleSheet(“QLineEdit { background-color: yellow }”);
      http://doc.qt.io/qt-4.8/stylesheet-examples.html
      While their version is still called set it does in fact derive the platform consistent defaults. However if JavaFX provided both the ability to add and remove style sheets globally as it appears to internally then it would have a more robust solution than Qt’s because you could chose the default, a stack of style sheets on the default, or only your own style sheet.

      Anyone that has any further insight please comment.

  5. I’m running into the same problem as Dennis Bulai. The guigarage tutorial isn’t working. It seems that in newer versions of Java, you can’t just pass null, but you need to pass Application.MODENA_STYLE.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>