~~NOCACHE~~
~~REVEAL theme=simple&disableLayout=0&transition=none&controls=1&show_progress_bar=1&build_all_lists=0&show_image_borders=0&horizontal_slide_level=2&enlarge_vertical_slide_headers=0&show_slide_details=1&open_in_new_window=1&size=1024x768~~
====== JavaFX i OpenJFX ======
===== JavaFX - historia i pozycja w ekosystemie =====
* **JavaFX** - zestaw bibliotek do tworzenia nowoczesnych aplikacji desktopowych w Javie
* Od JDK 8 wbudowany w Oracle JDK jako nowoczesna alternatywa dla AWT/Swing
* Od JDK 11 nie jest już częścią JDK, rozwijany osobno jako OpenJFX
* **OpenJFX** - otwartoźródłowy projekt rozwijający JavaFX przez społeczność, Oracle i firmę Gluon
* Aktualne wydania: [[https://gluonhq.com/products/javafx/|Gluon OpenJFX]]
===== Cechy JavaFX =====
* architektura oparta o graf ''Scene Graph''
* deklaratywne UI (FXML)
* stylowanie CSS
* multimedia, wsparcie dla animacji
* obsługa grafiki 2D i 3D oraz renderowania sprzętowego (akceleracja GPU)
* duża liczba wbudowanych kontrolek i możliwość rozbudowy
* WebView, silnik WebKit do osadzania treści webowej
* integracja z Swing (''SwingNode'')
* mechanizm danych reaktywnych (''Observable'', ''Property'', ''Binding'')
===== Architektura JavaFX =====
{{ zajecia:java_2026_1:136_1.jpg?600 | }}
===== Warstwy JavaFX =====
* **Prism** - akcelerowany potok renderowania (GPU: DirectX/OpenGL). \\ W przypadku braku wsparcia sprzętowego JavaFX przechodzi w tryb renderowania programowego.
* **Glass Windowing Toolkit** - warstwa okien, zdarzeń i timerów; interfejs między JavaFX a systemem operacyjnym.
* **WebView** - kontrolka osadzająca HTML/JS (silnik WebKit) umożliwiająca renderowanie i interakcję z treścią webową.
* **Media Engine** - silnik multimediów (audio/video) obsługujący różne formaty i kodeki.
* **Quantum Toolkit** - łączy warstwy niskopoziomowe z API JavaFX.
* **Scene Graph** - drzewo węzłów UI i grafiki
* **JavaFX API** - publiczne klasy i interfejsy do budowy interfejsu graficznego
===== JavaFX SDK API =====
* [[https://openjfx.io/javadoc/26/|JavaFX API Documentation]]
* ''javafx.base'' - podstawowe klasy, kolekcje, properties
* ''javafx.graphics'' - grafika 2D/3D, scena, renderowanie
* ''javafx.controls'' - gotowe kontrolki UI
* ''javafx.fxml'' - FXML, loader, kontrolery
* ''javafx.media'' - multimedia
* ''javafx.web'' - WebView, silnik WebKit
* ''javafx.swing'' - integracja z Swing (''SwingNode'')
===== Struktura aplikacji JavaFX =====
{{ zajecia:java_2026_1:141_1.jpg }}
* **Stage** - okno aplikacji - scena teatralna, gdzie odbywa się przedstawienie
* **Scene** - zawartość okna - konkretna scenografia, rekwizyty i aktorzy ustawieni na scenie, zawiera hierarchię węzłów (''Scene Graph'')
* **Node** - elementy UI, grafiki
===== Scene Graph =====
{{zajecia:java_2026_1:137_1.jpg}}
* Każdy element UI (obiekty 2D/3D, kontrolki UI, kontenery, elementy multimedialne) jest węzłem grafu (''Node'')
* Renderowanie, transformacje i zdarzenia propagują się po drzewie
* Zmiana stanu węzła natychmiast widoczna w interfejsie
===== Elementy Scene Graph =====
* ''Scene'' to główny kontener, w którym umieszczamy hierarchię węzłów
* Korzeń (''Root'') - główny węzeł sceny, zwykle layout (np. ''VBox'', ''BorderPane'')
* Węzły rodzicielskie (''Parent'') - zawierają inne węzły (dzieci)
* elementy grupujące (''Group''),
* układy (''Pane'', ''HBox'', ''StackPane'', ''GridPane'')
* kontrolki (''Button'', ''TextField'', ''Label''), też są rodzicami i mogą zawierać wewnętrzne węzły
* Liście - elementy graficzne 2D/3D (''Shape'', ''ImageView'', ''Text'', ''SwingNode'')
VBox root = new VBox();
Label title = new Label("Kurs JavaFX");
Button button = new Button("Kliknij");
root.getChildren().addAll(title, button);
Scene scene = new Scene(root, 600, 400);
===== Cykl życia aplikacji =====
* Punkt wejścia: klasa dziedzicząca po ''Application''
* Kluczowa metoda: ''start(Stage stage)'' udostępniająca główny ''Stage''. \\ W metodzie ''start()'':
* przygotowujemy scenę (tworzymy węzły, układamy je w layoutach)
* ustawiamy ''Stage'' (tytuł, rozmiar, scenę)
* wywołujemy ''show()'', aby wyświetlić okno.
* Uruchomienie: ''launch(args)'' w ''main()''
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
public class HelloFxApp extends Application {
@Override
public void start(Stage stage) {
Scene scene = new Scene(new Label("Witaj JavaFX"), 400, 200);
stage.setTitle("Hello FX");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
===== Konfiguracja JavaFX w IntelliJ =====
JavaFX nie jest już częścią JDK. Istnieje kilka sposobów na dodanie JavaFX do projektu:
* instalacja ręczna - pobierz OpenJFX, dodaj biblioteki do projektu, ustaw VM options
* z użyciem Maven lub Gradle - dodaj zależności do ''pom.xml'' lub ''build.gradle''
* szablon projektu JavaFX w IntelliJ (plugin JavaFX, używa Maven) - brakujące zależności powinny zostać pobrane automatycznie
[[https://openjfx.io/openjfx-docs/|Dokumentacja OpenJFX]] zawiera szczegółowe instrukcje dla różnych IDE i systemów budowania.
===== Ręczna konfiguracja JavaFX =====
* Pobierz SDK JavaFX z [[https://gluonhq.com/products/javafx/|Gluon]] lub [[https://www.oracle.com/java/technologies/downloads/javafx/|Oracle]] zgodny z wersją JDK
* Dodaj biblioteki JavaFX do projektu \\ ''File'' -> ''Project Structure'' -> ''Libraries''
* Ustaw ścieżkę do modułu w VM options przy uruchamianiu: \\ ''Build'' -> ''Edit Configurations'' -> ''VM options'' \\ --module-path "ścieżka/do/javafx-sdk-XX/lib" --add-modules javafx.controls,javafx.fxml
===== Konfiguracja JavaFX z użyciem Maven =====
Maven - system zarządzania projektem i budowania, który automatycznie pobiera zależności i konfiguruje projekt. Jak skonfigurować JavaFX z Maven:
- Utwórz projekt Maven (lub użyj archetypu JavaFX)
- Wyszukaj JavaFX w repozytorium Maven [[https://search.maven.org/search?q=javafx|Maven Central]] lub [[https://mvnrepository.com/search?q=javafx|https://mvnrepository.com/]]
- Dodaj zależności ''javafx-controls'' (opcjonalnie ''javafx-fxml'') do pliku ''pom.xml'' \\
- Skonfiguruj plugin ''javafx-maven-plugin'' do uruchamiania (zdarzenie ''javafx:run'') oraz ''maven-compiler-plugin''
- Uruchamiaj (z CLI) przez zadanie Maven, z okna narzędzi Maven IDE albo skonfiguruj IDE \\ mvn javafx:run
[[https://www.javaspring.net/blog/how-to-create-a-javafx-maven-project-in-intellij-idea/|JavaFX Maven Project in IntelliJ IDEA from Scratch]]
===== Przykładowa konfiguracja Maven dla JavaFX =====
org.openjfxjavafx-controls26org.openjfxjavafx-fxml26compile
===== Pluginy Maven dla JavaFX =====
org.apache.maven.pluginsmaven-compiler-plugin3.15.02525org.openjfxjavafx-maven-plugin0.0.8default-cliMyJavaFXApp
===== Uruchamianie aplikacji JavaFX z IDE =====
* Opcja 1: Okno narzędzi Maven
* ''Lifecycle'' -> ''clean''
* ''Plugins'' -> ''javafx'' -> ''javafx:run''
* Opcja 2: Dodaj konfigurację uruchomienia w IntelliJ
* ''Run'' -> ''Edit Configurations''
* Dodaj ''+'' -> ''Maven''
* W polu ''Command line'' wpisz: ''clean javafx:run''
===== Wątki i JavaFX =====
* JavaFX ma własny wątek UI (''JavaFX Application Thread'') uruchamiany automatycznie przy starcie aplikacji
* Wszystkie operacje na węzłach muszą być wykonywane w tym wątku
* Aby zachować responsywność, długotrwałe zadania powinny być wykonywane w osobnych wątkach, np. przez ''Task'' lub ''Service'', a aktualizacje UI przez ''Platform.runLater()''
===== Układy =====
{{ https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmdscoc82nafwdz6xzh4j.png?600 |Układy JavaFX}}
{{https://dev.to/alex_ricciardi/gui-design-with-javafx-layout-managers-54gj|GUI Design with JavaFX Layout Managers}}
===== Layouty =====
* ''javafx.scene.layout'' - układy (''layout'') - specjalne kontenery, które automatycznie rozmieszczają swoje dzieci według określonych reguł
* ''HBox'', ''VBox'', ''ButtonBar'' - układ poziomy/pionowy, rozmieszcza dzieci w linii
* ''BorderPane'' - układ z pięcioma regionami (top, bottom, left, right, center)
* ''SplitPane'' - układ dzielący przestrzeń na panele o regulowanej wielkości
* ''GridPane'' - układ siatkowy, rozmieszcza dzieci w wierszach i kolumnach
* ''FlowPane'' - układ przepływowy, rozmieszcza dzieci w linii, zawija do następnego wiersza
* ''AnchorPane'' - układ kotwiczący, pozwala przypiąć dzieci do krawędzi
* ''StackPane'' - nakłada dzieci jedno na drugie, centrowanie
StackPane stackPane = new StackPane();
Ellipse ellipse = new Ellipse(110, 70);
ellipse.setFill(Color.LIGHTBLUE);
Text text = new Text("Hello World");
text.setFont(new Font("Arial Bold", 24));
stackPane.getChildren().addAll(ellipse, text);
Scene scene = new Scene(stackPane, 350, 230, Color.LIGHTYELLOW);
===== Efekty graficzne =====
* [[https://download.java.net/java/GA/javafx26/docs/api/javafx.graphics/javafx/scene/effect/Effect.html|Effect]] - wbudowane efekty graficzne do stylizacji węzłów:
* [[https://download.java.net/java/GA/javafx26/docs/api/javafx.graphics/javafx/scene/effect/DropShadow.html|DropShadow]] - efekt cienia, można dostosować kolor, rozmycie i przesunięcie
* [[https://download.java.net/java/GA/javafx26/docs/api/javafx.graphics/javafx/scene/effect/Reflection.html|Reflection]] - efekt odbicia, można dostosować wysokość i rozmycie
* Wypełnienie kształtu:
* ''Color'', ''ImagePattern'', ''RadialGradient''
* [[https://download.java.net/java/GA/javafx26/docs/api/javafx.graphics/javafx/scene/paint/LinearGradient.html|LinearGradient]] - gradient liniowy, definiowany przez punkty początkowy i końcowy oraz zestaw ''Stop'' (pozycja + kolor)
Stop[] stops = new Stop[] {
new Stop(0, Color.DODGERBLUE),
new Stop(0.5, Color.LIGHTBLUE),
new Stop(1.0, Color.LIGHTGREEN) };
LinearGradient gradient = new LinearGradient(0, 0, 1, 1, true, CycleMethod.NO_CYCLE, stops);
ellipse.setFill(gradient);
ellipse.setEffect(new DropShadow(30, 10, 10, Color.GRAY));
===== Animacje =====
* System animacji oparty na klasie ''[[https://openjfx.io/javadoc/26/javafx.graphics/javafx/animation/Transition.html|Transition]]'' i ''[[https://openjfx.io/javadoc/26/javafx.graphics/javafx/animation/Timeline.html|Timeline]]''
* Można animować właściwości węzłów (pozycja, rozmiar, kolor) oraz tworzyć sekwencje animacji
* Animacje są płynne dzięki renderowaniu sprzętowemu
* ''[[https://openjfx.io/javadoc/26/javafx.graphics/javafx/animation/FadeTransition.html|FadeTransition]]'', ''[[https://openjfx.io/javadoc/26/javafx.graphics/javafx/animation/RotateTransition.html|RotateTransition]]'', ''[[https://openjfx.io/javadoc/26/javafx.graphics/javafx/animation/ScaleTransition.html|ScaleTransition]]'', ''[[https://openjfx.io/javadoc/26/javafx.graphics/javafx/animation/TranslateTransition.html|TranslateTransition]] '' - gotowe klasy do animacji określonych właściwości
* ''[[https://openjfx.io/javadoc/26/javafx.graphics/javafx/animation/Timeline.html|Timeline]]'' - bardziej elastyczna klasa do animowania dowolnych właściwości w określonych punktach czasowych
* ''[[https://openjfx.io/javadoc/26/javafx.graphics/javafx/animation/ParallelTransition.html|ParallelTransition]]'' i ''[[https://openjfx.io/javadoc/26/javafx.graphics/javafx/animation/SequentialTransition.html|SequentialTransition]]'' - do łączenia wielu animacji
* ''play()'' - uruchamia animację, ''stop()'' - zatrzymuje, ''pause()'' - wstrzymuje, ''getStatus()'' - sprawdza status animacji
RotateTransition rotate = new RotateTransition(Duration.millis(2500), stackPane);
rotate.setToAngle(360);
rotate.setFromAngle(0);
rotate.setInterpolator(Interpolator.LINEAR);
rotate.play();
===== Obsługa zdarzeń =====
* [[https://openjfx.io/javadoc/26/javafx.base/javafx/event/Event.html|Event]] - obsługa zdarzeń (myszy, klawiatury, akcji)
* Można rejestrować nasłuchiwacze zdarzeń na węzłach grafu
* Zdarzenia propagują się po drzewie, rodzic może przechwycić zdarzenie dziecka
* ''setOnAction(EventHandler)'', ''setOnMouseClicked(EventHandler)'' dla kontrolek (węzłów) obsługujących konkretne zdarzenia,
* ''addEventHandler(EventType, EventHandler)'' dla ogólnych zdarzeń
stackPane.setOnMouseClicked(mouseEvent -> {
if (rotate.getStatus().equals(Animation.Status.RUNNING)) {
rotate.pause();
} else {
rotate.play();
}
});
===== Obserwowanie i wiązanie właściwości =====
* JavaFX posiada wbudowany mechanizm danych reaktywnych, możemy wiązać właściwości węzłów z innymi właściwościami lub źródłami danych, tak aby zmiany były automatycznie odzwierciedlane w interfejsie
* właściwości węzłów są obserwowalne np. ''textProperty()'' dla ''Label'' czy ''TextField'', możemy ustawić nasłuchiwacz reagujący na zmiany lub powiązać je z innymi właściwościami
* [[https://openjfx.io/javadoc/26/javafx.base/javafx/beans/Observable.html|Observable]] oraz [[https://openjfx.io/javadoc/26/javafx.base/javafx/beans/value/ObservableValue.html|ObservableValue]] - interfejsy reprezentujące obserwowalną wartość, posiadają metody do dodawania nasłuchiwaczy ''addListener()'' i pobierania aktualnej wartości
* [[https://openjfx.io/javadoc/26/javafx.base/javafx/beans/InvalidationListener.html|InvalidationListener]] - reaguje na zmianę
* [[https://openjfx.io/javadoc/26/javafx.base/javafx/beans/value/ChangeListener.html|ChangeListener]] - reaguje na zmianę wartości, dostarcza starą i nową wartość
===== Przykład =====
rotate.statusProperty().addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
text.setText("Animation status: " +
((ObservableObjectValue)observable).getValue());
}
});
lub krócej
rotate.statusProperty().addListener(observable -> {
text.setText("Animation status: " + rotate.getStatus());
});
===== Binding =====
* Binding pozwala na tworzenie dynamicznych powiązań między właściwościami implementującymi interfejs [[https://openjfx.io/javadoc/26/javafx.base/javafx/beans/property/Property.html|Property]] bez potrzeby dodawania ręcznych nasłuchiwaczy
* ''bind()'' - tworzy jednokierunkowe powiązanie, gdzie jedna właściwość jest zależna od drugiej
text.rotateProperty().bind(stackPane.rotateProperty());
* przekształcanie wartości do tworzenia złożonych powiązań, np. matematycznych operacji, warunków logicznych, formatowania tekstu
text2.textProperty().bind(stackPane.rotateProperty().asString("%.1f"));
* łączenie wielu właściwości i operacji na nich, np. konkatenacja tekstu z dwóch ''TextField'' do ''Label''
TextField firstName = new TextField();
TextField lastName = new TextField();
Label fullName = new Label();
fullName.textProperty().bind(
firstName.textProperty().concat(" ").concat(lastName.textProperty())
);
===== Wiązanie dwukierunkowe =====
* ''bindBidirectional()'' - dwukierunkowe powiązanie, zmiana jednej właściwości automatycznie aktualizuje drugą i odwrotnie
* przydatne w formularzach, gdzie chcemy, aby zmiany w UI były odzwierciedlane w modelu danych i na odwrót
firstName.textProperty().bindBidirectional(model.firstNameProperty());
===== FXML - deklaratywny język UI =====
* FXML to XML opisujący hierarchię UI, pozwala na oddzielenie logiki od warstwy prezentacji
* [[https://openjfx.io/javadoc/26/javafx.fxml/javafx/fxml/doc-files/introduction_to_fxml.html|Introduction to FXML]]
* ''FXMLLoader'' wczytuje i parsuje plik FXML, tworzy obiekty UI i ustawia je w hierarchii
FXMLLoader loader = new FXMLLoader(getClass().getResource("main-view.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
stage.setScene(scene);
===== Scene Builder =====
* Scene Builder: [[https://gluonhq.com/products/scene-builder/|Gluon Scene Builder]] \\ niezależna aplikacja do projektowania interfejsu drag-and-drop
* Integracja z IntelliJ: [[https://www.jetbrains.com/help/idea/javafx.html|JavaFX w IntelliJ]]
{{ https://gluonhq.com/wp-content/uploads/2016/03/scene-builder-in-action.jpg?400 |Scene Builder in Action}}
===== Elementy FXML =====
* Instancje klas, np. ''