JavaFX Probe-App

1. Source Probe-App

/**
 * JavaFX Probe-App mit BorderPane, TextField und Button, etc.; Stand 2022-02-14
 *
 * @author Maximilian_Renkin
 */
public class JfxApp extends Application {

    public JfxApp() {
        System.out.println("Constructor JfxApp() called");
    }

    public static void main(String[] args) {
        System.out.println("main(...) called, now calling launch(...)");
        launch(args); // ruft indirekt start(...) auf
        System.out.println("main(...) finished");
    }

    @Override    // Optional Initialis. VOR Zugriff auf GUI (Dateien auslesen, etc.)!!
    public void init() throws Exception {
        super.init();
        System.out.println("init() - initialization (BEFORE access to GUI) called");
    }

    @Override
    public void stop() throws Exception {
        // Aufraeumen - MIT Zugriff auf GUI
        System.out.println("stop() called");
        super.stop();
    }

    @Override
    public void start(Stage primaryStage) throws Exception { // Hauptfenster als Param geliefert
        // start(...) indirekt aufgerufen von launch(...), ihrerseits in main(...) aufgerufen
        System.out.println("start(...)- the GUI activities - called)");
        // Vom JavaFX Laufzeitsystem wird das Hauptfenster (hier 'primaryStage') bereitgestellt.
        // Erzeugen Basis-Container - entspricht in HTML ca. dem Bereich innerhalb <body>...</body>:
        BorderPane root = new BorderPane(); // Wurzel-Container aller GUI-Elem., 'scene' übergeben
        // BorderPane hat 5 Bereiche: Top, Bottom, Left, Right, Center, die separate Inhalte haben.
        //
        // Scene ist gesamter Window-Inhalt - Fenstertitel, UI-Elemente wie Menü, Hauptbereich -
        // in Analogie zu Webseite entspricht es allem innerhalb von <html>...</html>.
        // Bei Erzeugung der Scene wird Basis-Container, Breite, Höhe des Fensters übergeben:
        Scene scene = new Scene(root, 450, 250);
        // Es können CSS-Stylesheets verwendet werden. Hier wird die aktuelle Stylesheet-Liste
        // abgefragt und eine eigene Stylesheet-Datei hinzugefügt (Pfad rel. zu Module-Basis-Dir):
        String cssUrl = getClass().getResource("jfx-app.css").toExternalForm();
        scene.getStylesheets().add(cssUrl);
        System.out.format("CSS-File URL is '%s'%n", cssUrl);
        //
        // nun wird dieser Basis-Container dem Hauptfenster zugeordnet:
        primaryStage.setScene(scene);
        //
        // der Fenstertitel wird gesetzt (wie HTML-<title>):
        primaryStage.setTitle("Mein erstes JavaFX-Programm");
        //
        // Nun erstellen wir einige "richtige" UI-Elemente: ein Label, anschließend
        // einem der Container-Arten: VBox ...
        Label lblHello = new Label("Hello User!"); // Erzeugen
        // Label z.B. einfach mit CSS stylen - spezielle CSS-Namen mit Prefix '-fx-':
        lblHello.setStyle("-fx-font-size: 2em;-fx-background-color:yellow; -fx-text-fill: blue;");

        root.setTop(lblHello);  // Variable nötig, da weitere Operation: setStyle(..)
        root.setBottom(new Label("Das ist der Bottom-Bereich, für Status-Info o.ä.")); // direkt
        //
        // Zur Demo noch schnell ein Label im linken und rechten Bereich:
        root.setLeft(new Label("Linker\nBereich")); // wenn Label nicht direkt ansprechbar sein muss
        Label lbl4RootRight = new Label("hier\nist\nrechts!"); // \n ... Zeilenschaltung
        root.setRight(lbl4RootRight); // Label in Variabler kann später leicht geändert werden:
        lbl4RootRight.setMinWidth(100);
        //
        // Minimal-Variante (dzt. aktiv):
        root.setCenter(new Label("Zentral-Bereich"));
        // Große Variante (dzt. auskommentiert, Mini-Formular im Center plazieren):
        // root.setCenter(composeMiniForm());
        //
        primaryStage.show(); // erzeugtes Fenster wird erst nach expliziter Aufforderung angezeigt.
        System.out.println("start(...) finished");
    }

//////// Zu Beginn auskommentieren Start: ////////
// /*
    private VBox composeMiniForm() {
        // Hier erzeugen wir ein Mini-Formular mit Eingabefeld, Button und Ausgabe-Label.
        // Wir planen zwei "Zeilen": eine mit Textfeld und Button, darunter die erzeugte
        //.. Antwort. Wir verwenden eine VBox - und für die obere Zeile darin als erstes
        //.. Element eine HBox.
        //.. Das zweite, untere Element ist direkt ein Label, das die Antwort anzeigen kann:
        VBox miniFormVbox = new VBox();  // dies ist der Container der zurückgeliefert wird
        // noch min. Größe für VBox setzen (füllt verfügbaren Platz, wächst bei Bedarf automatisch):
        miniFormVbox.setMinSize(300, 150);
        // Bei Bedarf auch Obergrenze: miniFormVbox.setMaxSize(maxWidth, maxHeight);
        miniFormVbox.setStyle("-fx-border-color: red;"); // wieder stylen
        miniFormVbox.setPadding(new Insets(10));
        //========
        // die HBox für die erste Zeile:
        HBox textPlusButtonHbox = new HBox(10.0);
        miniFormVbox.getChildren().add(textPlusButtonHbox);
        // Textfeld und Button:
        String namePrompt = "Name eingeben";   // zu Prüfung nötig, ob schon Text eingegeben wurde
        TextField nameTxfield = new TextField();
        nameTxfield.setPromptText(namePrompt);
        // JavaFX CSS siehe [JavaFX CSS Reference Guide] (Suche z.B. nach 'derive'):
        // https://openjfx.io/javadoc/17/javafx.graphics/javafx/scene/doc-files/cssref.html
        nameTxfield.setStyle("-fx-prompt-text-fill: derive(-fx-control-inner-background,-30%); }");
        nameTxfield.setTooltip(new Tooltip("Hier bitte den Namen eingeben"));  // nach 1s sichtbar
        textPlusButtonHbox.getChildren().add(nameTxfield);
        //
        // danach einen Button hinzufügen (noch inaktiv):
        Button answerButton = new Button("Sag was");
        textPlusButtonHbox.getChildren().add(answerButton);
        answerButton.setId("answerButton");
        //========
        // das AnswerLabel:
        Label answerLabel = new Label("-- hier wird die Antwort sichtbar --");
        answerLabel.setId("answerLabel");
        miniFormVbox.getChildren().add(answerLabel);
        // Button-Klick-Aktion als 'anonyme innere Klasse':
        answerButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                if (nameTxfield.getText().equals(namePrompt)) {
                    answerLabel.setText("kein Name eingegeben");
                } else {
                    answerLabel.setText("Hallo " + nameTxfield.getText() + ", wie gehts?");
                }
            }
        });
//        // Button-Klick-Aktion eleganter definieren per Lambda-Ausdruck:
//        answerButton.setOnAction((ActionEvent event) -> {
              // obiger Parameter-Typ 'ActionEvent' könnte weggelassen werden!
//            if (nameTxfield.getText().equals(namePrompt)) {
//                answerLabel.setText("kein Name eingegeben");
//            } else {
//                answerLabel.setText("Hallo " + nameTxfield.getText() + ", wie gehts?");
//            }
//        });
        return miniFormVbox;
    }
// */
//////// Zu Beginn auskommentieren Ende: ////////
}

2. Source CSS-File

/* JavaFX CSS - Leave this comment until there is min. one rule using -fx-Property */
.root {      /*Basis-CSS-Klasse - dem root-Element der Scene zugeordnet*/
    -fx-font-size: 12pt;
    -fx-font-family: "Helvetica, Arial, Sans-Serif";
    -fx-text-fill: blue;
    -fx-background: rgb(32, 128, 128);
}
#answerButton {
    -fx-font-family: "Serif";
}

#answerLabel {
    -fx-font-family: "Courier New";
}

3. Erläuterungen