Je voudrais lier un fichier css à mon application. Dans mon fichier fxml, j'utilise ceci:
<stylesheets>
<URL value="@../stylesheet1.css" />
</stylesheets>
... et je peux voir un aperçu stylisé lorsque j'ouvre le fichier fxml dans scenebuilder. Mais lorsque j'essaie d'exécuter l'application, j'obtiens une erreur:
Java.net.MalformedURLException: pas de protocole: ../stylesheet1.css
Je l'ai donc testé de cette façon:
<stylesheets>
<String fx:value="stylesheet1.css" />
</stylesheets>
et maintenant c'est l'inverse - l'application démarre et applique le CSS, mais je ne vois pas l'aperçu dans scenebuilder. Le message d'erreur:
"Le fichier stylesheet1.css n'existe pas. Ressource stylesheet1.css introuvable."
Alors, comment puis-je joindre correctement le fichier CSS?
Eh bien, même si ma question n'a pas répondu pourquoi exactement cela ne fonctionne pas de la manière ci-dessus, j'ai trouvé une solution qui fonctionne pour moi. Dans mon FXML j'ai juste la ligne
<?scenebuilder-stylesheet ../stylesheet1.css?>
donc Scenebuilder fonctionne avec ce CSS. Et dans ma classe principale, j'ai défini la feuille de style par programme:
Scene scene = new Scene(root);
String css = this.getClass().getResource("../stylesheet1.css").toExternalForm();
scene.getStylesheets().add(css);
Ce que j'ai trouvé une solution utilisable et fonctionnelle pour inclure le fichier css
dans fxml
, c'est ajouter stylesheets="@app/cssfilename.css"
au nœud parent du fichier fxml
comme pour le volet de pile
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="app.fxml.SettingsController" stylesheets="@app/cssfilepath.css">
......
.....
.....
</StackPane>
Voici une solution qui fonctionne dans l'environnement de développement, dans Scene Builder et dans un JAR packagé.
La structure des dossiers:
Main.Java:
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
FXMLLoader loader = new FXMLLoader(Main.class.getResource("view/RootLayout.fxml"));
AnchorPane rootLayout = (AnchorPane) loader.load();
Scene scene = new Scene(rootLayout, 400, 400);
scene.getStylesheets().add(getClass().getResource("css/application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
RootLayout.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import Java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.view.RootLayoutController">
<children>
<Pane layoutX="0.0" layoutY="0.0" prefHeight="200.0" prefWidth="200.0">
<children>
<Button fx:id="sunButton" layoutX="74.0" layoutY="88.0" mnemonicParsing="false" onAction="#handleSunButtonClick" styleClass="Sun-button" stylesheets="@../css/toolbar.css" text="Button" />
</children>
</Pane>
</children>
</AnchorPane>
RootLayoutController.Java:
package application.view;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
public class RootLayoutController {
@FXML
Button sunButton;
@FXML
public void handleSunButtonClick() {
System.out.println( "Button clicked");
}
}
toolbar.css:
.Sun-button {
-fx-graphic: url('./icons/Sun.png');
}
application.css:
.root {
-fx-background-color:lightgray;
}
Sun.png:
Cela fonctionne à la fois dans l'environnement de développement et lorsque vous empaquetez le JAR (choisissez "Extraire les bibliothèques requises dans le JAR généré" dans Eclipse).
Capture d'écran (juste un bouton avec une icône chargée via css)
Si vous ne voulez pas le faire par programme, vous pouvez le faire en séparant le code et les ressources. J'ai une structure de projet Maven comme celle-ci, mais ce n'est pas une exigence.
src/main/Java/${packageName}
MainWindow.fxml
src/main/resources/${packageName}
stylesheet1.css
Vous pouvez maintenant utiliser la feuille de style dans le .fxml
stylesheets="@stylesheet1.css"
ou en utilisant la balise stylesheets comme vous l'avez fait.
Il peut y avoir un avertissement dans SceneBuilder
mais cela fonctionne.