JavaFX Tutorial: CSS-Stil

Wie man JavaFX-Komponenten mit einem guten alten CSS formatiert.

Alle Beiträge in der JavaFX-Reihe:

  1. JavaFX Tutorial: Erste Schritte
  2. JavaFX Tutorial: Hallo Welt!
  3. JavaFX Tutorial: FXML und SceneBuilder
  4. JavaFX Tutorial: Grundlegende Layouts
  5. JavaFX Tutorial: Erweiterte Layouts
  6. JavaFX Tutorial: CSS-Stil
  7. JavaFX Weaver: Integration von JavaFX- und Spring-Boot-Anwendungen

Trennung visueller Elemente


In einem früheren Artikel über FXML haben wir erfahren, wie JavaFX eine klare Aufgabentrennung ermöglicht, indem der Code der Benutzeroberfläche in zwei Teile aufgeteilt wird . Komponenten und ihre Eigenschaften werden in der FXML-Datei deklariert und die Interaktionslogik ist dem Controller eindeutig zugeordnet.

Darüber hinaus gibt es einen dritten Teil, die FXML-Sprache, die nur die Komponenten Ihrer Anwendung, ihre Eigenschaften und ihre Einbettung ineinander steuert. Es definiert nicht die visuellen Elemente einer Komponente, nämlich: Schriftarten, Farben, Hintergründe, Einzüge. Im Allgemeinen können Sie dies in FXML erreichen, sollten es aber nicht. Stattdessen sollten visuelle Elemente in CSS-Stylesheets klar definiert sein.

Auf diese Weise wird Ihr Design unabhängig und kann leicht ersetzt oder geändert werden, ohne den Rest der Anwendung zu beeinträchtigen. Sie können sogar einfach mehrere Themen implementieren, die auf Wunsch des Benutzers umgeschaltet werden können.

CSS


Sie sind wahrscheinlich mit CSS (Cascading Style Sheets) vertraut, mit denen HTML-Seiten im Web formatiert werden. Ein ähnlicher Ansatz ist in JavaFX implementiert, obwohl JavaFX eine Reihe eigener benutzerdefinierter Eigenschaften verwendet.

Schauen wir uns ein Beispiel an:

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

Hier werden zwei Hauptkonzepte verwendet. Der erste ist der. Button Selector. Es legt fest, auf welche Komponenten der Stil angewendet werden soll. In diesem Beispiel wird der Stil auf alle Schaltflächen angewendet.

Der zweite Teil sind die tatsächlichen Eigenschaften des Stils, die auf alle Komponenten angewendet werden, die zu unserer Auswahl passen. Eigenschaften sind alles in geschweiften Klammern.

Jede Eigenschaft hat eine bestimmte Bedeutung. In unserem Beispiel gibt es die Eigenschaft -fx-font-size , die bestimmt, wie groß der Text sein wird. In diesem Beispiel ist der Wert 15px , aber dieser Wert kann jeder andere sein.

Zusammenfassend haben wir eine Regel erstellt, die besagt, dass alle Schaltflächen überall Text mit 15 Pixeln enthalten sollen.

Selektoren


Schauen wir uns nun genauer an, wie Selektoren in JavaFX funktionieren. Dies geschieht fast genauso wie bei normalem CSS.

Klasse


Eine Klasse in CSS repräsentiert mehrere ähnliche Elemente. Zum Beispiel Schaltflächen oder Kontrollkästchen. Die Auswahl, die auf alle Elemente derselben Klasse angewendet werden soll, beginnt mit einem Punkt ".", Unmittelbar gefolgt vom Klassennamen. Eine Klassennamenskonvention besteht darin, einzelne Wörter mit dem Zeichen "-" zu trennen. Der folgende Selektor gilt für alle Elemente mit der Beschriftungsklasse .

 .label { // Some properties } 

Eingebaute Klassen


Die gute Nachricht ist, dass alle in JavaFX integrierten Komponenten (wie Label oder Button) bereits eine vordefinierte Klasse haben. Wenn Sie den Stil aller Beschriftungen in Ihrer Anwendung anpassen möchten, müssen Sie für jede Beschriftung keine benutzerdefinierten Klassen hinzufügen. Jedes Etikett hat standardmäßig eine Etikettenklasse .

Es ist einfach, den Klassennamen aus der Komponente zu ermitteln:

  • Nehmen Sie zum Beispiel den Namen der Java-Komponentenklasse. Label
  • Machen Sie den Namen in Kleinbuchstaben
  • Wenn es aus mehreren Wörtern besteht, trennen Sie diese mit dem Symbol "-"

Einige Beispiele:

  • Beschriftung → Beschriftung
  • Kontrollkästchen → Kontrollkästchen

Wenn Sie Klassen wie Selektoren verwenden, müssen Sie "." Hinzufügen. Dies bedeutet, dass der Selektor für die Label- Klasse .label ist .

Eigene Klassen


Wenn die integrierten Klassen nicht ausreichen, können Sie Ihren Komponenten eigene Klassen hinzufügen. Sie können mehrere durch Komma getrennte Klassen verwenden:

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

Oder in Java:

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

Durch das Hinzufügen von Klassen auf diese Weise wird die Komponentenklasse nicht standardmäßig entfernt (in diesem Fall label ).

Es gibt eine spezielle Klasse namens root . Es ist die Wurzelkomponente Ihrer Szene. Sie können damit alles in Ihrer Szene gestalten (z. B. eine globale Schriftart festlegen). Dies ähnelt der Verwendung des Body-Tag-Selektors in HTML.

ID


Eine andere Möglichkeit, Komponenten in CSS auszuwählen, ist die Verwendung einer Komponenten-ID. Es ist eine eindeutige Kennung für eine Komponente. Im Gegensatz zu Klassen, die mehreren Komponenten zugewiesen werden können, muss der Bezeichner in der Szene eindeutig sein.

Das Symbol "." Kennzeichnet die Klasse. Vor dem Namen in ihren Selektoren sind Bezeichner mit dem Symbol "#" gekennzeichnet.

 #my-component { ... } 

In FXML können Sie mit fx: id die CSS-Kennung einer Komponente festlegen.

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

Es gibt jedoch eine Einschränkung. Mit demselben Bezeichner wird auf das in Ihrer Steuerung deklarierte Komponentenobjekt mit demselben Namen verwiesen. Da der Bezeichner und der Feldname im Controller übereinstimmen müssen, muss fx: id die Java-Namensbeschränkung für Feldnamen berücksichtigen. Obwohl die CSS-Namenskonvention einzelne Wörter definiert, die durch ein "-" getrennt sind, ist dies ein ungültiges Zeichen für Java-Feldnamen. Daher müssen Sie für fx: id mit ein paar Wörtern eine andere Namenskonvention wie CamelCase oder einen Unterstrich verwenden.

 <!-- 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> 

In Java können Sie einfach die setId () -Methode Ihrer Komponente aufrufen.

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

Eigenschaften


Obwohl das in JavaFX verwendete CSS dem ursprünglichen Web-CSS sehr ähnlich ist, gibt es einen großen Unterschied. Eigenschaftsnamen sind unterschiedlich und es gibt viele neue JavaFX-spezifische Eigenschaften. Sie haben das Präfix -fx- .

Hier einige Beispiele:

  • -fx-background-color : Hintergrundfarbe
  • -fx-text-fill : Textfarbe
  • -fx-font-size : Textgröße

Eine Auflistung aller Objekte finden Sie im offiziellen Planungshandbuch .

Pseudoklassen


Neben den üblichen Klassen, die bestimmte Komponenten kennzeichnen, gibt es sogenannte Pseudoklassen, die den Zustand einer Komponente anzeigen. Dies kann beispielsweise eine Klasse sein, mit der markiert wird, dass die Komponente den Fokus hat oder sich der Mauszeiger darauf befindet.

Es gibt viele eingebaute Pseudoklassen. Schauen wir uns den Knopf an. Es gibt verschiedene Pseudoklassen, die Sie beispielsweise verwenden können:

  • Hover : Maus über Button
  • fokussiert : Die Schaltfläche ist fokussiert
  • disabled : Schaltfläche ist deaktiviert
  • gedrückt : Taste gedrückt

Pseudoklassen beginnen in CSS-Selektoren mit dem Zeichen ":" (z. B. :: hover ). Natürlich müssen Sie angeben, zu welcher Komponente Ihre Pseudoklasse gehört - zum Beispiel button: hover . Das folgende Beispiel zeigt eine Auswahl, die für alle Schaltflächen mit Fokus gilt:

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

Im Gegensatz zu CSS, das nur grundlegende Pseudoklassen für Zustände wie focus und hover enthält , verfügt JavaFX über komponentenspezifische Pseudoklassen, die sich auf verschiedene Zustände oder Eigenschaften von Komponenten beziehen.

Zum Beispiel:

  • Bildlaufleisten haben horizontale und vertikale Pseudoklassen
  • Elemente (Zellen) haben gerade und ungerade Pseudoklassen
  • TitledPane hat Pseudoklassen erweitert und reduziert.

Benutzerdefinierte Pseudoklassen


Zusätzlich zu den eingebauten Pseudoklassen können Sie Ihre eigenen Pseudoklassen definieren und verwenden.

Lassen Sie uns ein eigenes Label erstellen (das von der Label-Klasse erbt). Es wird eine neue logische Eigenschaft namens shiny haben . In diesem Fall möchten wir, dass unser Label eine glänzende Pseudoklasse hat.

Da das Tag eine glänzende Pseudoklasse hat, können wir den Hintergrund des Gold- Tags festlegen:

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

Erstellen Sie nun die Klasse selbst.

 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); } } 

Hier gibt es mehrere wichtige Teile:

  1. Wir haben die Eigenschaft BooleanProperty boolean anstelle des üblichen Booleschen Werts . Dies bedeutet, dass das glänzende Objekt beobachtbar ist und wir Änderungen in seinem Wert verfolgen (anhören) können.
  2. Wir registrieren einen Listener, der jedes Mal aufgerufen wird, wenn sich der Wert des glänzenden Objekts mit shiny.addListener () ändert.
  3. Wenn sich der glänzende Wert ändert, wird die glänzende Pseudoklasse abhängig vom aktuellen Wert von pseudoClassStateChanged (PseudoClass.getPseudoClass ("shiny"), shiny.get ()) hinzugefügt / entfernt .
  4. Wir fügen eine benutzerdefinierte Klasse für alle glänzenden Beschriftungen hinzu , anstatt nur die Beschriftungsklasse vom übergeordneten Element zu erben. Daher können wir nur glänzende Tags auswählen.

Standard-Stylesheet


Auch wenn Sie selbst keine Stile angeben, verfügt jede JavaFX-Anwendung bereits über einige visuelle Stile. Es gibt ein Standard-Stylesheet, das für jede Anwendung gilt. Es heißt Modena (seit JavaFX 8, früher Kaspisch ).

Dieses Stylesheet finden Sie in der Datei:

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

Oder Sie finden die Datei hier . Im selben Verzeichnis befinden sich viele Bilder, die vom Stylesheet verwendet werden.

Dieses Stylesheet bietet Standardstile, hat jedoch die niedrigste Priorität gegenüber anderen Stylesheet-Typen, sodass Sie es leicht überschreiben können.

Szenen-Stylesheet


Zusätzlich zu dem oben genannten Standard-Stylesheet können Sie natürlich auch ein eigenes bereitstellen. Die höchste Ebene, auf der Sie die Stilisierung anwenden können, ist die gesamte Szene. Sie können dies in Ihre FXML implementieren:

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

Oder in Ihrem Java-Code:

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

Achten Sie auf den Aufruf vonExternalForm () . Scene erwartet, dass der Inhalt des Stylesheets als Zeichenfolge und nicht als Datei abgerufen wird. Daher müssen wir den Inhalt unseres Stylesheets als Zeichenfolge bereitstellen.

Übergeordnetes Stylesheet


Zusätzlich zum Stylesheet für die gesamte Szene ist es manchmal nützlich, Stile auf Layoutebene zu haben. Das heißt - für einen separaten Container wie VBox, HBox oder GridPane. Das gemeinsame übergeordnete Element aller Layouts ist die übergeordnete Klasse, die Methoden für die Verarbeitung von Stylesheets auf Layoutebene definiert. Diese Stile gelten nur für die Komponenten in diesem Layout und nicht für die gesamte Szene. Ein Stil auf Layoutebene hat Vorrang vor einem Stil auf Szenenebene.

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

In Java müssen Sie den Inhalt des Stylesheets wie zuvor für die Szene selbst laden:

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

Inline-Stile


Bisher haben wir nur Fälle betrachtet, in denen ein externes Stylesheet einer gesamten Szene oder einem Layout zugewiesen wurde. Sie können jedoch einzelne Stileigenschaften auf Komponentenebene festlegen.

Hier müssen Sie sich nicht um den Selektor kümmern, da alle Eigenschaften für eine bestimmte Komponente festgelegt sind.

Sie können mehrere durch Semikolon getrennte Eigenschaften angeben:

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

In Java können Sie die Methode setStyle () verwenden:

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

Stile auf Komponentenebene haben Vorrang vor Szenenstilen sowie übergeordneten Stilen auf Layoutebene.

Warum müssen Sie sie vermeiden


Styling auf Komponentenebene kann praktisch sein, ist aber eine schnelle und schmutzige Lösung. Sie verzichten auf den Hauptvorteil von CSS, nämlich die Trennung von Stilen und Komponenten. Jetzt binden Sie Ihre visuellen Elemente direkt an die Komponenten. Sie können Ihre Stylesheets bei Bedarf nicht mehr einfach wechseln, Sie können keine Themen mehr ändern.

Außerdem haben Sie keine zentrale Stelle mehr, an der Ihr Stil definiert ist. Wenn Sie etwas in einer Reihe ähnlicher Komponenten ändern müssen, müssen Sie jede der Komponenten einzeln ändern und dürfen nicht nur eine Stelle im externen Stylesheet bearbeiten. Daher sollten Inline-Komponentenstile vermieden werden.

Stylesheet-Prioritäten


Sie können das Styling auf verschiedenen Ebenen bereitstellen - Szenen-, übergeordnete und Inline-Styles. Außerdem gibt es ein Standard-Modem-Stylesheet. Wenn Sie dieselbe Eigenschaft derselben Komponente auf mehreren Ebenen ändern, hat JavaFX eine Prioritätseinstellung, die bestimmt, welche Stile verwendet werden sollen. Prioritätenliste - von der höchsten zur niedrigsten:

  1. Inline-Stile
  2. Übergeordnete Stile
  3. Szenenstile
  4. Standardstile

Das heißt, wenn Sie die Hintergrundfarbe einer bestimmten Beschriftung sowohl auf Inline- als auch auf Szenenebene festlegen, verwendet JavaFX den in den Inline-Stilen festgelegten Wert, da er eine höhere Priorität hat.

Zusätzliche Lektüre


JavaFX verfügt über viele CSS-Eigenschaften, deren Beschreibung den Rahmen dieses Beitrags sprengt . Eine detaillierte Liste finden Sie im offiziellen CSS-Referenzhandbuch für JavaFX .

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


All Articles