JavaFX z Arią - powrót do strony głównej

FXML tutorial (1) – wprowadzenie

FXML

FXML jest językiem znaczników, opartym na XML-u, pozwalającym na używanie języka skryptowego, służącym do konstruowania scenografu lub jego fragmentów w JavaFX.
Zaletą FXML-u, podobnie jak innych rodzajów XML-u, jest bezpośredni dostęp do pliku, co daje możliwość dynamicznego zmieniania zarówno układu elementów jak i wartości atrybutów.
Kod JavaFX, odwołujący się do pliku FXML, nie musi być kompilowany, gdy zmieni się treść plików.

Układ projektu

W projekcie użyłem JDK 19, JavaFX 19, Groovy 4.0.8, IntelliJ IDEA v. Community.
Układ pakietów w module:

Układ pakietów w module
Układ pakietów w module

Wspólna klasa module-info.java dla wszystkich kodów w tutorialu.

module-info.java
module fxmlgroovyscript {

    requires java.scripting;
    requires java.sql;

    requires javafx.base;
    requires javafx.controls;
    requires javafx.fxml;
    requires javafx.graphics;

    exports codes to javafx.graphics, javafx.fxml;

    opens codes to javafx.fxml, javafx.base;
    opens resources;


}

Aplikacja JavaFX bez FXML

Aplikacja jest prosta. Zawiera etykietkę i trzy przyciski, które na razie nie wykonują żadnego zadania.

Listing01_hello_groovy.java
package codes;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Listing01_hello_groovy extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) {
        try {
            VBox root = new VBox();
            HBox hbox = new HBox();
            Label lab1 = new Label();
            lab1.setText("Twoja decyzja?");
            Button but1 = new Button("Tak");
            Button but2 = new Button("Nie");
            Button but3 = new Button("Anuluj");
            hbox.getChildren().addAll(but1, but2, but3);
            root.getChildren().addAll(lab1, hbox);
            Scene scene = new Scene(root, 150, 80);
            stage.setScene(scene);
            stage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Po uruchomieniu klasy zobaczymy:

Okno aplikacji
Okno aplikacji

Aplikacja JavaFX z FXML

Aplikacja jest prosta. Zawiera etykietkę i trzy przyciski, które na razie nie wykonują żadnego zadania.
Tym razem mamy klase oraz plik FXML zawierający scenograf aplikacji.

listing02_fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>

<VBox xmlns:fx="http://javafx.com/fxml">
	<Label fx:id="lab1" text="Twoja decyzja?" />
	<HBox fx:id="hbox">
		<Button fx:id="but1" text="Tak" />
		<Button fx:id="but2" text="Nie" />
		<Button fx:id="but3" text="Anuluj" />
	</HBox>
</VBox>

Zwróć uwagę na sposób importowania klas <?import javafx.scene.layout.VBox?>, wszechobecne elementy fx:id, identyfikujące poszczególne instancje klas, oraz narzuconą przestrzeń nazw xmlns:fx="http://javafx.com/fxml. Atrybut przestrzeni nazw zawsze znajduje się w elemencie root, czyli w korzeniu scenografu.
Dozwolony, choć odradzany ze względu na niepotrzebne obciążanie pamięci, jest też import <?import javafx.scene.layout.*?>. Import statyczny nie jest dozwolony.

Listing02_hello_groovy_fxml.java
package codes;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.net.URL;

public class Listing02__hello_groovy_fxml extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) {
        try {
            URL fxmlUrl = this.getClass().getClassLoader().getResource("resources/listing02.fxml");
            VBox root = fxmlUrl != null ? FXMLLoader.load(fxmlUrl) : new VBox();
            Scene scene = new Scene(root, 150, 80);
            stage.setScene(scene);
            stage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Klasa wywołuje FXMLLoader, który pobiera zasoby, określa klasę korzenia scenografu, buduje ‘stage’ i scenę, na której umieszcza utworzony scenograf.
Należy zwrócić uwagę, że obiekty Stage i Scene nie są listowane w pliku FXML.
W znacznikach lab1, but1, but2 i but3 widzimy atrybuty text oraz umieszczoną w nich wartość.
Po uruchomieniu klasy otrzymamy identyczne okno aplikacji jak przedstawione na obrazku powyżej.