Spis treści

Zajecia 9. - JavaFX - cwiczenia demonstracyjne (hands-on)

Organizacja czesci praktycznej

Demo 1 (latwe): Kalkulator netto/brutto

Cel:

Zadanie demonstracyjne:

Wskazowki:

Rozwiazanie:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
 
public class DemoVatCalculator extends Application {
    @Override
    public void start(Stage stage) {
        TextField netField = new TextField();
        ComboBox<Double> vatBox = new ComboBox<>();
        vatBox.getItems().addAll(0.23, 0.08, 0.05);
        vatBox.setValue(0.23);
 
        Button calcBtn = new Button("Przelicz");
        Label result = new Label("Brutto: -");
 
        calcBtn.setOnAction(e -> {
            try {
                double net = Double.parseDouble(netField.getText().trim());
                double gross = net * (1.0 + vatBox.getValue());
                result.setText(String.format("Brutto: %.2f PLN", gross));
            } catch (NumberFormatException ex) {
                result.setText("Blad: podaj poprawna liczbe");
            }
        });
 
        GridPane root = new GridPane();
        root.setPadding(new Insets(12));
        root.setHgap(8);
        root.setVgap(8);
        root.add(new Label("Netto:"), 0, 0);
        root.add(netField, 1, 0);
        root.add(new Label("VAT:"), 0, 1);
        root.add(vatBox, 1, 1);
        root.add(calcBtn, 1, 2);
        root.add(result, 1, 3);
 
        stage.setScene(new Scene(root, 420, 220));
        stage.setTitle("Demo 1 - VAT");
        stage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
}

Demo 2 (srednie): Lista zadan TODO + binding

Cel:

Zadanie demonstracyjne:

Wskazowki:

Rozwiazanie:

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
 
public class DemoTodoList extends Application {
    @Override
    public void start(Stage stage) {
        ObservableList<String> tasks = FXCollections.observableArrayList();
 
        TextField input = new TextField();
        input.setPromptText("Nowe zadanie");
        Button addBtn = new Button("Dodaj");
        Button removeBtn = new Button("Usun zaznaczone");
 
        addBtn.disableProperty().bind(
            Bindings.createBooleanBinding(
                () -> input.getText().trim().isEmpty(),
                input.textProperty()
            )
        );
 
        ListView<String> listView = new ListView<>(tasks);
 
        addBtn.setOnAction(e -> {
            String value = input.getText().trim();
            if (!value.isEmpty()) {
                tasks.add(value);
                input.clear();
            }
        });
 
        removeBtn.setOnAction(e -> {
            int idx = listView.getSelectionModel().getSelectedIndex();
            if (idx >= 0) {
                tasks.remove(idx);
            }
        });
 
        HBox top = new HBox(8, input, addBtn, removeBtn);
        BorderPane root = new BorderPane();
        root.setTop(top);
        root.setCenter(listView);
 
        stage.setScene(new Scene(root, 560, 320));
        stage.setTitle("Demo 2 - TODO");
        stage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
}

Demo 3 (trudniejsze): FXML + CSS + kontroler

Cel:

Zadanie demonstracyjne:

Wskazowki:

Rozwiazanie - kontroler:

package demo;
 
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
 
public class LoginController {
    @FXML private TextField emailField;
    @FXML private PasswordField passwordField;
    @FXML private Label statusLabel;
 
    @FXML
    private void onLogin() {
        String email = emailField.getText().trim();
        String pass = passwordField.getText();
 
        boolean validEmail = email.contains("@") && email.contains(".");
        boolean validPass = pass.length() >= 8;
 
        if (validEmail && validPass) {
            statusLabel.setText("Logowanie poprawne");
        } else {
            statusLabel.setText("Sprawdz email i haslo (min. 8 znakow)");
        }
    }
}

Rozwiazanie - FXML:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.VBox?>
 
<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="demo.LoginController" spacing="10" styleClass="app-root">
    <padding><Insets top="14" right="14" bottom="14" left="14"/></padding>
    <Label text="Panel logowania" styleClass="title"/>
    <TextField fx:id="emailField" promptText="Email"/>
    <PasswordField fx:id="passwordField" promptText="Haslo"/>
    <Button text="Zaloguj" onAction="#onLogin" id="primaryButton"/>
    <Label fx:id="statusLabel" text="Wpisz dane"/>
</VBox>

Rozwiazanie - CSS:

.app-root {
    -fx-background-color: linear-gradient(to bottom, #f8fafc, #e5ecf4);
}
 
.title {
    -fx-font-size: 18px;
    -fx-font-weight: bold;
}
 
#primaryButton {
    -fx-background-radius: 8;
    -fx-font-weight: bold;
}

Rozwiazanie - uruchomienie:

FXMLLoader loader = new FXMLLoader(getClass().getResource("login-view.fxml"));
Scene scene = new Scene(loader.load(), 420, 260);
scene.getStylesheets().add(getClass().getResource("app.css").toExternalForm());
stage.setScene(scene);
stage.show();

Podsumowanie hands-on