→ Slide 1

JavaFX i OpenJFX

→ Slide 2

JavaFX - historia i pozycja w ekosystemie

→ Slide 3

Cechy JavaFX

→ Slide 4

Architektura JavaFX

→ Slide 5

Warstwy JavaFX

→ Slide 6

JavaFX SDK API

→ Slide 7

Struktura aplikacji JavaFX

141_1.jpg

→ Slide 8

Scene Graph

137_1.jpg

→ Slide 9

Elementy Scene Graph

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);
→ Slide 10

Cykl życia aplikacji

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);
    }
}
→ Slide 11

Konfiguracja JavaFX w IntelliJ

JavaFX nie jest już częścią JDK. Istnieje kilka sposobów na dodanie JavaFX do projektu:

Dokumentacja OpenJFX zawiera szczegółowe instrukcje dla różnych IDE i systemów budowania.

→ Slide 12

Ręczna konfiguracja JavaFX

→ Slide 13

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:

  1. Utwórz projekt Maven (lub użyj archetypu JavaFX)
  2. Wyszukaj JavaFX w repozytorium Maven Maven Central lub https://mvnrepository.com/
  3. Dodaj zależności javafx-controls (opcjonalnie javafx-fxml) do pliku pom.xml
  4. Skonfiguruj plugin javafx-maven-plugin do uruchamiania (zdarzenie javafx:run) oraz maven-compiler-plugin
  5. Uruchamiaj (z CLI) przez zadanie Maven, z okna narzędzi Maven IDE albo skonfiguruj IDE
    mvn javafx:run

JavaFX Maven Project in IntelliJ IDEA from Scratch

→ Slide 14

Przykładowa konfiguracja Maven dla JavaFX

<dependencies>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>26</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-fxml</artifactId>
        <version>26</version>
        <scope>compile</scope>
    </dependency>
</dependencies>
→ Slide 15

Pluginy Maven dla JavaFX

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.15.0</version>
            <configuration>
                <source>25</source>  <!-- Match your JDK version -->
                <target>25</target>
            </configuration>
        </plugin>
 
        <plugin>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-maven-plugin</artifactId>
            <version>0.0.8</version>
            <executions>
                <execution>
                    <id>default-cli</id>
                    <configuration>
                        <mainClass>MyJavaFXApp</mainClass>  <!-- Your main class -->
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
→ Slide 16

Uruchamianie aplikacji JavaFX z IDE

→ Slide 17

Wątki i JavaFX

→ Slide 18

Układy

Układy JavaFX

GUI Design with JavaFX Layout Managers

→ Slide 19

Layouty

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);
→ Slide 20

Efekty graficzne

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));
→ Slide 21

Animacje

RotateTransition rotate = new RotateTransition(Duration.millis(2500), stackPane);
rotate.setToAngle(360);
rotate.setFromAngle(0);
rotate.setInterpolator(Interpolator.LINEAR);
rotate.play();
→ Slide 22

Obsługa zdarzeń

stackPane.setOnMouseClicked(mouseEvent -> {
    if (rotate.getStatus().equals(Animation.Status.RUNNING)) {
        rotate.pause();
    } else {
        rotate.play();
    }
});
→ Slide 23

Obserwowanie i wiązanie właściwości

→ Slide 24

Przykład

rotate.statusProperty().addListener(new InvalidationListener() {
    @Override
    public  void invalidated(Observable observable) {
        text.setText("Animation status: " +
        ((ObservableObjectValue<Animation.Status>)observable).getValue());
    }
});

lub krócej

rotate.statusProperty().addListener(observable -> {
    text.setText("Animation status: " + rotate.getStatus());
});
→ Slide 25

Binding

text.rotateProperty().bind(stackPane.rotateProperty());
text2.textProperty().bind(stackPane.rotateProperty().asString("%.1f"));
TextField firstName = new TextField();
TextField lastName = new TextField();
Label fullName = new Label();
 
fullName.textProperty().bind(
    firstName.textProperty().concat(" ").concat(lastName.textProperty())
);
→ Slide 26

Wiązanie dwukierunkowe

firstName.textProperty().bindBidirectional(model.firstNameProperty());
→ Slide 27

FXML - deklaratywny język UI

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>  
 
<VBox xmlns:fx="http://javafx.com/fxml">
    <Button text="OK" />
    <Label text="Witaj JavaFX" />
</VBox>
FXMLLoader loader = new FXMLLoader(getClass().getResource("main-view.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
stage.setScene(scene);
→ Slide 28

Scene Builder

Scene Builder in Action

→ Slide 29

Elementy FXML

→ Slide 30

Atrybuty FXML

→ Slide 31

FXML + Controller

// MainController.java
public class MainController {
    @FXML 
    private TextField input;
    @FXML 
    private Label output;
 
    @FXML
    private void onGenerate() {
        output.setText("Witaj, " + input.getText().trim());
    }
}
<!-- main-view.fxml -->
<VBox spacing="8" xmlns:fx="http://javafx.com/fxml" fx:controller="demo.MainController">
    <TextField fx:id="input" promptText="Podaj imię" />
    <Button text="Generuj" onAction="#onGenerate" />
    <Label fx:id="output" />
</VBox>
→ Slide 32

Inicjalizacja kontrolera

public class MainController implements Initializable {
    @FXML private TextField input;
    @FXML private Label output;
 
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        input.setText("Jan");
        output.setText("Witaj, " + input.getText());
    }
}
→ Slide 33

FXMLLoader

URL location = getClass().getResource("example.fxml");
ResourceBundle resources = ResourceBundle.getBundle("com.foo.example");
FXMLLoader fxmlLoader = new FXMLLoader(location, resources);
 
Pane root = (Pane)fxmlLoader.load();
MyController controller = (MyController)fxmlLoader.getController();
→ Slide 34

Metoda load()

  1. Odczyt pliku FXML, tworzenie obiektów i ustawienie właściwości węzłów
  2. Utworzenie instancji kontrolera (jeśli fx:controller jest określony)
  3. Wstrzyknięcie zależności do kontrolera (pola publiczne lub oznaczone @FXML i odpowiadające im fx:id w FXML)
  4. Rejestrowanie nasłuchiwaczy zdarzeń (np. onAction=#methodName)
  5. Wywołanie metody initialize() kontrolera (jeśli implementuje Initializable lub posiada metodę oznaczoną @FXML o nazwie initialize)
→ Slide 35

CSS w JavaFX

→ Slide 36

Powiązanie stylów z węzłami

label.getStyleClass().add("greeting");
button.setId("primaryButton");
→ Slide 37

Selektry CSS JavaFX

/* Plik CSS dla JavaFX */
/* Selekcja po nazwie węzła */
Button {
    -fx-background-color: lightblue;
    -fx-text-fill: darkblue;
}
 
/* Selekcja po klasie CSS */
.primaryButton {
    -fx-background-color: linear-gradient(to right, #ff7e5f, #feb47b);
    -fx-text-fill: white;  
    -fx-font-size: 16px;
    -fx-padding: 10px 20px;
    -fx-background-radius: 8px;
}
 
/* Selekcja po identyfikatorze */
#primaryButton {
    -fx-background-color: linear-gradient(to right, #ff7e5f, #feb47b);
    -fx-text-fill: white;   
    -fx-font-size: 16px;
    -fx-padding: 10px 20px;
    -fx-background-radius: 8px;
}
 
/* Selekcja pseudoklasy */
Button:hover {
    -fx-background-color: linear-gradient(to right, #feb47b, #ff7e5f);
}
→ Slide 38

Priorytety stylowania

→ Slide 39

Materiały

→ Slide 40

Zadanie 8: Lista zakupów

Stwórz prostą aplikację JavaFX do zarządzania listą zakupów.

Wymagania:

Wskazówki: