Program-Me-Rev
Program-Me-Rev

Reputation: 6624

How to include css file in a JavaFx Spring application

When I include the path to css resources in the JavaFx Application class the project runs perfectly.

public class SampleApp extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        AnnotationConfigApplicationContext context
                = new AnnotationConfigApplicationContext(SampleAppFactory.class);

        SampleController sampleController = context.getBean(SampleController.class);
        Scene scene = new Scene((Parent) sampleController.getView(), 320, 240);
        scene.getStylesheets().add("/resources/css/fxmlapp.css");

        stage.setScene(scene);
        stage.setTitle("JFX2.0 Sprung");
        stage.show();
    }
}

However, it fails to complile when I include the css path in the FXML file.

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<StackPane fx:id="view" prefHeight="98.0" prefWidth="160.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.rev.SampleController">
  <children>
    <Button fx:id="printBtn" onAction="#print" text="Click Me" />
  </children>
  <stylesheets>
    <URL value="@../css/fxmlapp.css" />
  </stylesheets>
</StackPane>

Note the inclussion on the line <URL value="@../css/fxmlapp.css" />.

I'd like to work with the css included in the FXML since it is much easier to design the FXML with the css there, you know - you can see how a particular css property affects a page's look and feel. How can I go about to make it work? Thank you all.

The other classes are as follows:

@Configuration
public class SampleAppFactory {

    @Bean
    public Person person() {
        return new Person("Richard");
    }

    @Bean
    public SampleController sampleController() throws IOException {
        return (SampleController) loadController("/resources/fxml/Sample.fxml");
    }

    protected Object loadController(String url) throws IOException {
        InputStream fxmlStream = null;
        try {
            fxmlStream = getClass().getResourceAsStream(url);
            FXMLLoader loader = new FXMLLoader();
            loader.load(fxmlStream);
            return loader.getController();
        } finally {
            if (fxmlStream != null) {
                fxmlStream.close();
            }
        }
    }
}

public class SampleController {

    @FXML
    private Node view;
    @Autowired
    private Person person;

    public Node getView() {
        return view;
    }

    public Person getPerson() {
        return person;
    }

    public void print(ActionEvent event) {
        System.out.println("Well done, " + person.getFirstName() + "!");
    }
}

The file: fxmlapp.css


.root {
    -fx-background-color: linear-gradient(from 0% 0% to 0% 100%, #cbd0d7 0%, white 100%);
}

#printBtn {
    -fx-text-fill: #e4f3fc;
    -fx-font: 20pt "Tahoma Bold";
    -fx-padding: 10;
    -fx-base: #2d4b8e
}

#printBtn:hover{
    -fx-base: #395bae;
}

Upvotes: 0

Views: 299

Answers (1)

Nikos Paraskevopoulos
Nikos Paraskevopoulos

Reputation: 40298

Use the a java.net.URL instead of an InputStream, e.g. as follows:

protected Object loadController(String url) throws IOException {
    try {
        FXMLLoader loader = new FXMLLoader(getClass().getResource(url));
        loader.load();
        return loader.getController();
    }
    catch(...) {...}
}

This way the FXML mechanism will be able to resolve the relative URI.

Upvotes: 1

Related Questions