scalatutorial.de

Stufe 6Werkzeuge und Oberflächen · Lektion 34 von 34

ScalaFX: Oberflächen mit JavaFX

Aktualisiert am 24. September 20263 Min. LesezeitSchritt 6/6 dieser Stufe

ScalaFX ist eine Scala-Schicht über JavaFX, dem modernen Oberflächen-Toolkit der Java-Welt. Es beschreibt Fenster und Bedienelemente als verschachtelte Objekte und verbindet Werte über Bindings – Oberflächen aktualisieren sich damit von selbst.

JavaFX und ScalaFX

JavaFX ist der Nachfolger von Swing: Es bringt hardwarebeschleunigte Grafik, Animationen, Styling mit CSS und ein Konzept für beobachtbare Werte (Properties) mit. Seit Java 11 gehört JavaFX nicht mehr zum JDK, sondern wird als eigenständiges Projekt (OpenJFX) entwickelt und wie eine gewöhnliche Bibliothek eingebunden. ScalaFX übernimmt diese Abhängigkeiten in der Regel gleich mit.

Die Stärke von ScalaFX ist eine deklarative Schreibweise: Statt Objekte zu erzeugen und Eigenschaften nacheinander zu setzen, beschreiben Sie die Oberfläche als Baum.

Einrichten

build.sbtsbt
libraryDependencies += "org.scalafx" %% "scalafx" % scalafxVersion
fork := true

Für scalafxVersion tragen Sie die aktuelle Version von der Projektseite ein; sie orientiert sich an der JavaFX-Version (zum Beispiel beginnt eine Version für JavaFX 21 mit „21.“). fork := true sorgt dafür, dass sbt das Programm in einer eigenen JVM startet – JavaFX verträgt es schlecht, mehrfach in derselben JVM gestartet zu werden.

Das erste Fenster

Hallo.scalaScala 3
import scalafx.application.JFXApp3
import scalafx.scene.Scene
import scalafx.scene.control.{Button, Label}
import scalafx.scene.layout.VBox
import scalafx.geometry.Insets

object Hallo extends JFXApp3:
  override def start(): Unit =
    val anzeige = new Label("Noch nicht geklickt")

    stage = new JFXApp3.PrimaryStage:
      title = "Hallo ScalaFX"
      scene = new Scene(360, 180):
        root = new VBox:
          spacing = 12
          padding = Insets(20)
          children = Seq(
            anzeige,
            new Button("Klick mich"):
              onAction = _ => anzeige.text = "Geklickt!"
          )

Der Aufbau folgt der JavaFX-Hierarchie: Eine Stage ist das Fenster, darin liegt eine Scene, deren root der oberste Knoten des Oberflächenbaums ist. onAction erwartet eine Funktion; der Unterstrich ignoriert das übergebene Ereignisobjekt.

Layouts

LayoutAnordnung
VBox / HBoxuntereinander / nebeneinander
BorderPaneoben, unten, links, rechts, Mitte
GridPaneRaster mit Zeilen und Spalten
StackPaneübereinander gestapelt, z. B. Text auf Bild
FlowPanefließend mit Umbruch

Die Idee ist dieselbe wie bei den Panels in Swing: Layouts werden verschachtelt, bis die gewünschte Anordnung entsteht.

Properties und Bindings

Das Besondere an JavaFX sind beobachtbare Werte. In ScalaFX lassen sie sich mit wenigen Zeichen verknüpfen:

 Scala 3
import scalafx.scene.control.{Slider, Label}
import scalafx.beans.binding.Bindings

val regler = new Slider(0, 100, 50)
val wert   = new Label

wert.text <== Bindings.createStringBinding(
  () => f"${regler.value()}%.0f Prozent",
  regler.value
)

Der Operator <== bindet eine Eigenschaft einseitig an eine andere: Bewegt jemand den Regler, ändert sich die Beschriftung von selbst. Mit <==> entsteht eine Bindung in beide Richtungen, etwa zwischen zwei Eingabefeldern. Code, der Oberflächen mühsam „von Hand“ aktualisiert, entfällt damit größtenteils.

Auch Bedingungen lassen sich binden:

 Scala 3
knopf.disable <== eingabe.text.isEmpty

Der Knopf ist nur aktiv, solange etwas eingegeben wurde.

Gestalten mit CSS

JavaFX-Oberflächen lassen sich mit einer eigenen CSS-Variante gestalten. Eigenschaften beginnen mit -fx-:

stil.cssAusgabe
.root { -fx-font-size: 14px; -fx-background-color: #1a1d23; }
.button { -fx-background-color: #d8392a; -fx-text-fill: white; }
.label { -fx-text-fill: #ebe7de; }

Eingebunden wird die Datei über die Szene: scene.stylesheets += getClass.getResource("/stil.css").toExternalForm. Einzelne Knoten lassen sich zusätzlich mit style = "-fx-font-weight: bold" gestalten.

Swing oder ScalaFX?

Swing (scala-swing)ScalaFX
im JDK enthaltenjanein, Bibliothek nötig
Aussehenklassisch, begrenzt anpassbarmodern, per CSS gestaltbar
Bindingsneinja
Grafik, Animationeinfachumfangreich
EinsatzWerkzeuge, Bestandneue Desktop-Anwendungen

Passt dazu