Tutoriel JavaFX: style CSS

Comment styliser les composants JavaFX en utilisant un bon vieux CSS.

Tous les articles de la série JavaFX:

  1. Tutoriel JavaFX: Prise en main
  2. Tutoriel JavaFX: Bonjour tout le monde!
  3. Tutoriel JavaFX: FXML et SceneBuilder
  4. Tutoriel JavaFX: dispositions de base
  5. Tutoriel JavaFX: dispositions avancées
  6. Tutoriel JavaFX: style CSS
  7. JavaFX Weaver: intégration des applications JavaFX et Spring Boot

Séparation des éléments visuels


Dans un article précédent sur FXML, nous avons appris comment JavaFX fournit une séparation claire des tâches en divisant le code de l'interface utilisateur en deux. Les composants et leurs propriétés sont déclarés dans le fichier FXML et la logique d'interaction est clairement allouée au contrôleur.

De plus, il existe une troisième partie, le langage FXML, qui contrôle uniquement les composants de votre application, leurs propriétés et la façon dont ils sont intégrés les uns aux autres. Il ne définit pas les éléments visuels d'un composant, à savoir: les polices, les couleurs, les arrière-plans, les retraits. En général, vous pouvez y parvenir dans FXML, mais vous ne devriez pas. Au lieu de cela, les éléments visuels doivent être clairement définis dans les feuilles de style CSS.

Ainsi, votre conception devient indépendante et peut être facilement remplacée ou modifiée sans affecter le reste de l'application. Vous pouvez même simplement implémenter plusieurs thèmes qui peuvent être commutés à la demande de l'utilisateur.

CSS


Vous connaissez probablement les CSS (feuilles de style en cascade) utilisées pour styliser les pages HTML sur le Web. Une approche similaire est implémentée dans JavaFX, bien que JavaFX utilise un ensemble de ses propres propriétés personnalisées.

Regardons un exemple:

.button { -fx-font-size: 15px; } 

Deux concepts principaux sont utilisés ici. Le premier est le sélecteur .button . Il détermine à quels composants le style doit s'appliquer. Dans cet exemple, le style est appliqué à tous les boutons.

La deuxième partie est les propriétés réelles du style, qui seront appliquées à tous les composants qui correspondent à notre sélecteur. Les propriétés sont tout à l'intérieur des accolades bouclées.

Chaque propriété a une signification spécifique. Dans notre exemple, il existe la propriété -fx-font-size , qui détermine la taille du texte. Dans l'exemple, la valeur est 15px , mais cette valeur peut être toute autre.

Pour résumer - nous avons créé une règle qui stipule que tous les boutons partout doivent avoir un texte de 15 pixels.

Sélecteurs


Examinons maintenant de plus près le fonctionnement des sélecteurs dans JavaFX. Cela se produit presque de la même manière qu'en CSS standard.

Classe


Une classe en CSS représente plusieurs éléments similaires. Par exemple, des boutons ou des cases à cocher. Le sélecteur, qui doit être appliqué à tous les éléments d'une même classe, commence par un point ".", Suivi immédiatement du nom de la classe. Une convention de dénomination de classe consiste à séparer les mots individuels avec le caractère "-". Le sélecteur suivant s'applique à tous les éléments avec la classe d' étiquette .

 .label { // Some properties } 

Classes intégrées


La bonne nouvelle est que tous les composants intégrés JavaFX (tels que Label ou Button) ont déjà une classe prédéfinie. Si vous souhaitez personnaliser le style de toutes les étiquettes de votre application, vous n'avez pas besoin d'ajouter de classes personnalisées pour chacune de vos étiquettes. Chaque étiquette a une classe d' étiquette par défaut.

Il est facile de déterminer le nom de classe à partir du composant:

  • Prenez le nom de la classe de composants Java, par exemple. Étiquette
  • Rendre le nom en minuscule
  • S'il se compose de plusieurs mots, séparez-les par le symbole "-"

Quelques exemples:

  • Étiquette → Étiquette
  • CheckBox → case à cocher

Lorsque vous utilisez des classes telles que des sélecteurs, assurez-vous d'ajouter ".". Cela signifie que le sélecteur de la classe d' étiquette est .label .

Cours personnalisés


Si les classes intégrées ne suffisent pas, vous pouvez ajouter vos propres classes à vos composants. Vous pouvez utiliser plusieurs classes séparées par une virgule:

 <Label styleClass="my-label,other-class">I am a simple label</Label> 

Ou en Java:

 Label label = new Label("I am a simple label"); label.getStyleClass().addAll("my-label", "other-class"); 

L'ajout de classes de cette manière ne supprime pas la classe de composants par défaut (dans ce cas, label ).

Il existe une classe spéciale appelée root . C'est le composant racine de votre scène. Vous pouvez l'utiliser pour tout styliser à l'intérieur de votre scène (par exemple, définir une police globale). Ceci est similaire à l'utilisation du sélecteur de balises body en HTML.

Identifiant


Une autre façon de sélectionner des composants en CSS consiste à utiliser un identifiant de composant (ID). Il s'agit d'un identifiant unique pour un composant. Contrairement aux classes qui peuvent être affectées à plusieurs composants, l'identifiant doit être unique dans la scène.

Alors que le symbole "." Est utilisé pour indiquer la classe. devant le nom dans leurs sélecteurs, les identifiants sont marqués du symbole "#".

 #my-component { ... } 

Dans FXML, vous pouvez utiliser fx: id pour définir l'identifiant CSS d'un composant.

 <Label fx:id="foo">I am a simple label</Label> 

Cependant, il y a une mise en garde. Le même identifiant est utilisé pour faire référence à l'objet composant déclaré dans votre contrôleur avec le même nom. Étant donné que l'identifiant et le nom de champ dans le contrôleur doivent correspondre, fx: id doit prendre en compte la restriction de nommage Java pour les noms de champ. Bien que la convention de dénomination CSS définisse des mots individuels séparés par un caractère "-", il s'agit d'un caractère non valide pour les noms de champ Java. Par conséquent, pour fx: id avec quelques mots, vous devez utiliser une convention de dénomination différente telle que CamelCase, ou utiliser un trait de soulignement.

 <!-- This is not valid --> <Label fx:id="my-label">I am a simple label</Label> <!-- This is valid --> <Label fx:id="my_label">I am a simple label</Label> <Label fx:id="MyLabel">I am a simple label</Label> 

En Java, vous pouvez simplement appeler la méthode setId () de votre composant.

 Label label = new Label("I am a simple label"); label.setId("foo"); 

Propriétés


Bien que le CSS utilisé dans JavaFX soit très similaire au CSS Web d'origine, il y a une grande différence. Les noms de propriété sont différents et il existe de nombreuses nouvelles propriétés spécifiques à JavaFX. Ils ont le préfixe -fx- .

Voici quelques exemples:

  • -fx-background-color : Couleur d'arrière- plan
  • -fx-text-fill : couleur du texte
  • -fx-font-size : taille du texte

Vous pouvez trouver une liste de toutes les propriétés dans le guide de conception officiel .

Pseudo-cours


En plus des classes habituelles qui marquent des composants spécifiques, il existe des pseudo-classes qui indiquent l'état d'un composant. Cela pourrait être, par exemple, une classe pour marquer que le composant a le focus ou que le curseur de la souris est dessus.

Il existe de nombreuses pseudo-classes intégrées. Regardons le bouton. Il existe plusieurs pseudo-classes que vous pouvez utiliser, par exemple:

  • survoler : passer la souris sur le bouton
  • focalisé : le bouton a le focus
  • désactivé : le bouton est désactivé
  • enfoncé : bouton enfoncé

Les pseudo-classes commencent par le caractère ":" (par exemple :: hover ) dans les sélecteurs CSS. Bien sûr, vous devez spécifier à quel composant votre pseudo-classe appartient - par exemple, button: hover . L'exemple suivant montre un sélecteur qui s'applique à tous les boutons qui ont le focus:

 .button:focused { -fx-background-color: red; } 

Contrairement à CSS, qui ne possède que des pseudo-classes de base pour des états tels que focus et survol , JavaFX possède des pseudo-classes spécifiques aux composants qui se rapportent à différents états ou propriétés de composants.

Par exemple:

  • Les barres de défilement ont des pseudo-classes horizontales et verticales
  • Les éléments (cellules) ont des pseudo-classes impaires et paires
  • TitledPane a développé et réduit les pseudo-classes.

Pseudo-classes personnalisées


En plus des pseudo-classes intégrées, vous pouvez définir et utiliser vos propres pseudo-classes.

Créons notre propre étiquette (héritant de la classe Label). Il aura une nouvelle propriété logique appelée brillant . Dans ce cas, nous voulons que notre étiquette ait une pseudo- classe brillante .

Puisque la balise a une pseudo- classe brillante , nous pouvons définir l'arrière-plan de la balise or :

 .shiny-label:shiny { -fx-background-color: gold; } 

Créez maintenant la classe elle-même.

 public class ShinyLabel extends Label { private BooleanProperty shiny; public ShinyLabel() { getStyleClass().add("shiny-label"); shiny = new SimpleBooleanProperty(false); shiny.addListener(e -> { pseudoClassStateChanged(PseudoClass.getPseudoClass("shiny"), shiny.get()); }); } public boolean isShiny() { return shiny.get(); } public void setShiny(boolean shiny) { this.shiny.set(shiny); } } 

Il y a plusieurs parties importantes ici:

  1. Nous avons la propriété booléenne BooleanProperty au lieu du booléen habituel. Cela signifie que l'objet brillant est observable, et nous pouvons suivre (écouter) les changements de sa valeur.
  2. Nous enregistrons un écouteur qui sera appelé à chaque fois que la valeur de l'objet brillant change à l'aide de shiny.addListener () .
  3. Lorsque la valeur brillante change, nous ajoutons / supprimons la pseudo- classe brillante en fonction de la valeur actuelle de pseudoClassStateChanged (PseudoClass.getPseudoClass ("shiny"), shiny.get ()) .
  4. Nous ajoutons une classe personnalisée pour toutes les étiquettes à étiquette brillante , au lieu d'avoir uniquement la classe d' étiquette héritée du parent. Ainsi, nous ne pouvons sélectionner que des tags brillants .

Feuille de style par défaut


Même si vous ne fournissez vous-même aucun style, chaque application JavaFX possède déjà certains styles visuels. Il existe une feuille de style par défaut qui s'applique à chaque application. Il s'appelle modena (depuis JavaFX 8, il s'appelait auparavant caspien ).

Cette feuille de style se trouve dans le fichier:

jfxrt.jar \ com \ sun \ javafx \ scene \ control \ skin \ modena \ modena.css

Ou vous pouvez trouver le fichier ici . Dans le même répertoire, de nombreuses images sont utilisées par la feuille de style.

Cette feuille de style fournit des styles par défaut, mais a la priorité la plus faible sur les autres types de feuilles de style, vous pouvez donc facilement la remplacer.

Feuille de style de scène


En plus de la feuille de style par défaut mentionnée ci-dessus, vous pouvez bien sûr fournir la vôtre. Le niveau le plus élevé auquel vous pouvez appliquer la stylisation est la scène entière. Vous pouvez implémenter cela dans votre FXML:

 <BorderPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" stylesheets="styles.css" ... > ... </BorderPane> 

Ou dans votre code Java:

 String stylesheet = getClass().getResource("/styles.css").toExternalForm(); scene.getStylesheets().add(stylesheet); 

Faites attention à l'appel àExternalForm () . La scène s'attend à obtenir le contenu de la feuille de style sous forme de chaîne, pas un fichier, nous devons donc fournir le contenu de notre feuille de style sous forme de chaîne.

Feuille de style parent


En plus de la feuille de style pour la scène entière, il est parfois utile d'avoir des styles au niveau de la mise en page. C'est-à-dire pour un conteneur séparé, tel que VBox, HBox ou GridPane. Le parent commun de toutes les présentations est la classe parent, qui définit les méthodes de traitement des feuilles de style au niveau de la présentation. Ces styles s'appliquent uniquement aux composants de cette disposition et non à la scène entière. Un style au niveau de la disposition est prioritaire sur un style au niveau de la scène.

 <HBox stylesheets="styles.css"> ... </HBox> 

En Java, vous devez charger vous-même le contenu de la feuille de style, comme précédemment pour la scène:

 HBox box = new HBox(); String stylesheet = getClass().getResource("/styles.css").toExternalForm(); box.getStylesheets().add(stylesheet); 

Styles en ligne


Jusqu'à présent, nous n'avons examiné que les cas où une feuille de style externe a été affectée à une scène ou à une disposition entière. Mais vous pouvez définir des propriétés de style individuelles au niveau du composant.

Ici, vous n'avez pas à vous soucier du sélecteur, car toutes les propriétés sont définies pour un composant spécifique.

Vous pouvez spécifier plusieurs propriétés séparées par des points-virgules:

 <Label style="-fx-background-color: blue; -fx-text-fill: white"> I'm feeling blue. </Label> 

En Java, vous pouvez utiliser la méthode setStyle () :

 Label label = new Label("I'm feeling blue."); label.setStyle("-fx-background-color: blue; -fx-text-fill: white"); 

Les styles au niveau du composant ont priorité sur les styles de scène ainsi que sur les styles parents au niveau de la disposition.

Pourquoi vous devez les éviter


Le style au niveau des composants peut être pratique, mais c'est une solution rapide et sale. Vous abandonnez le principal avantage de CSS, qui est la séparation des styles des composants. Maintenant, vous liez rigidement vos éléments visuels directement aux composants. Vous ne pouvez plus facilement changer vos feuilles de style si nécessaire, vous ne pouvez pas changer de thème.

De plus, vous n'avez plus un seul endroit central où votre style est défini. Lorsque vous devez modifier quelque chose dans un ensemble de composants similaires, vous devez modifier chacun des composants séparément et ne pas modifier un seul emplacement dans la feuille de style externe. Par conséquent, les styles de composants en ligne doivent être évités.

Priorités des feuilles de style


Vous pouvez fournir un style à plusieurs niveaux - scène, parent, styles en ligne et il existe également une feuille de style de modem par défaut. Si vous modifiez la même propriété du même composant à plusieurs niveaux, JavaFX a un paramètre de priorité qui détermine les styles à utiliser. Liste de priorité - du plus élevé au plus bas:

  1. Styles en ligne
  2. Styles parents
  3. Styles de scène
  4. Styles par défaut

Cela signifie que si vous définissez la couleur d'arrière-plan d'une certaine étiquette au niveau en ligne et au niveau de la scène, JavaFX utilisera la valeur définie dans les styles en ligne car elle a une priorité plus élevée.

Lecture complémentaire


JavaFX possède de nombreuses propriétés CSS, et leur description dépasse le cadre de cet article; pour une liste détaillée, consultez le guide de référence CSS officiel pour JavaFX .

Source: https://habr.com/ru/post/fr477924/


All Articles