1

I'm working on a project where I'd like to use an external CSS file with JavaFX to style the VBox and panes and such.

I've used the line below to try to add the style sheet to the respective scene:

scene.getStylesheets().add(getClass().getResource("/style.css").toExternalForm());

This gave me null pointers, I read some other posts on this issue and found that this is often due to the stylesheet not being in the class path that it is trying to be accessed from. Here is a screenshot that allows you to see that this is not the case:

You'll notice there is Styles.css and style.css, I tried both for different troubleshooting purposes

I also found suggestions from people saying that if it is in the class path, that it should be accessed as such:

scene.getStylesheets().add("style.css");

However doing so is giving me

Nov 04, 2018 9:24:10 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
WARNING: Resource "Styles.css" not found.

I'm open to any suggestions, I'm working in IntelliJ using maven.

EDIT: Here is the pom file for further investigation -

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.almasb</groupId>
<artifactId>CashMachine</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <source.version>1.8</source.version>

    <!-- plugins -->
    <maven.compiler.version>3.3</maven.compiler.version>
    <maven.shade.version>2.4.2</maven.shade.version>

    <!-- dependencies -->
</properties>

<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler.version}</version>
            <configuration>
                <source>${source.version}</source>
                <target>${source.version}</target>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>${maven.shade.version}</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.almasb.atm.CashMachineApp</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

9
  • Can you please let us know where is your class sitting in the heirarcy. Is it CashMachineApp ? Commented Nov 5, 2018 at 2:31
  • How are you building your app? Are you using a build tool such as Maven or Gradle? If so, resources should go in src/main/resources not src/main/java. Most build tools will ignore non .java files in the src/main/java directory by default. Commented Nov 5, 2018 at 3:02
  • 1
    Also, if you pass a String with no protocol to getStylesheets().add(...) it will look for it on the classpath—but it requires the absolute path. Commented Nov 5, 2018 at 3:03
  • @Slaw Yes I am using Maven, and the package is arranged the way I received it from my school. The class which is trying to use the stylesheet is CashMachineApp. Commented Nov 5, 2018 at 3:33
  • 1
    Check the target/classes directory to see if your CSS file(s) was copied there when you built the project. Commented Nov 5, 2018 at 3:35

3 Answers 3

5

Maven convention uses a standard directory layout and, unless otherwise configured, requires that you follow it. One of the things the standard directory layout does is separate Java source files (.java) from resource files (everything not .java). It looks like this:

|--projectDir/
|  |--src/
|  |  |--main/
|  |  |  |--java/
|  |  |  |--resources/

The source files go in src/main/java and the resource files go in src/main/resources.

When you build your project Maven will compile the source files and put the .class files in projectDir/target/classes. It will also copy any resource files from src/main/resources into target/classes as well. By default, any non-source files in src/main/java will be ignored. You mention you had put your styles.css file in src/main/java and thus it is not in target/classes when you run your project.

When you execute the project the directory target/classes (as well as any dependencies) is put on the classpath. But because your styles.css file wasn't copied into target/classes it is not included in the classpath and you end up getting NullPointerExceptions when trying to reference it.

The solution is to move the styles.css file into the src/main/resources directory. It looks like you currently have it under src/main/java/rocks/zipcode/atm. If you want to keep the resource file in the same "package" move it to src/main/resources/rocks/zipcode/atm. Then it should be copied to the target/classes directory when you rebuild your project.

Then you can reference it a couple of ways.

The first way is using getClass().getResource(...). If you pass an absolute path (starts with a /) it will look for the resource from the root of the classpath. If you don't pass an absolute path (doesn't start with a /) it will look for the resource relative to the Class's location (in this case, the Class is the one returned by getClass()). This means, since you're getting the resource from within rocks.zipcode.atm.CacheMachineApp, you could either do:

  • getClass().getResource("/rocks/zipcode/atm/styles.css"), or
  • getClass().getResource("styles.css")

The other option is to use the behavior defined in the documentation of getStylesheets():

Gets an observable list of string URLs linking to the stylesheets to use with this scene's contents.

The URL is a hierarchical URI of the form [scheme:][//authority][path]. If the URL does not have a [scheme:] component, the URL is considered to be the [path] component only. Any leading '/' character of the [path] is ignored and the [path] is treated as a path relative to the root of the application's classpath.

As you can see, when there is no scheme (e.g. file:, https:, etc.) it will look for the resource relative to the root of the the classpath. Since it is always relative to the root you need to pass the absolute path (but in this case it doesn't require a leading /).

getStylesheets().add("rocks/zipcode/atm/styles.css");

Important Note: Make sure you get the path completely correct. It is case sensitive when packaged in a JAR file. It may or may not be case sensitive when not packaged in a JAR file, but that is dependent on the underlying file system. Either way, it is best to match the case of the actual path in order to avoid any problems.

Sign up to request clarification or add additional context in comments.

1 Comment

You are a life saver @Slaw, your detailed explanation along with this post here stackoverflow.com/questions/18717038/… where exactly what I needed. Thank you so much for such a detailed response, I truly appreciate it mate.
0

If your css file is sitting in the same package of your class:

scene.getStylesheets().add(getClass().getResource("style.css").toString());

1 Comment

This gave me a null pointer also, though thank you for the suggestion.
-1

What worked for me was adding "//" at the beginning of the 'path from content' Like this:"//src/practice/Viper.css"

1 Comment

This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.