====== Zajecia 9. - JavaFX - cwiczenia demonstracyjne (hands-on) ====== ===== Organizacja czesci praktycznej ===== * Czas: 20-30 min * Forma: prowadzÄ…cy koduje na zywo, studenci odtwarzaja kroki * Cel: przejsc od prostego UI do formularza z FXML i CSS ===== Demo 1 (latwe): Kalkulator netto/brutto ===== Cel: * Uzyc ''TextField'', ''ComboBox'', ''Button'', ''Label'' * Obsluzyc zdarzenie klikniecia i walidacje danych Zadanie demonstracyjne: * Pole kwoty netto * Lista stawek VAT (23%, 8%, 5%) * Przycisk ''Przelicz'' * Wynik brutto w etykiecie Wskazowki: * Parsuj wejscie przez ''Double.parseDouble'' * Przy bledzie wyswietl komunikat * Sformatuj wynik do 2 miejsc po przecinku 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 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: * Uzyc ''ObservableList'', ''ListView'', ''TextField'' * Pokazac prosty binding aktywacji przycisku Zadanie demonstracyjne: * Pole tekstowe na nazwe zadania * Przycisk ''Dodaj'' (aktywny tylko, gdy pole niepuste) * ''ListView'' z zadaniami * Przycisk ''Usun zaznaczone'' Wskazowki: * ''disableProperty().bind(...)'' dla przycisku * ''getSelectionModel().getSelectedIndex()'' dla usuwania * Puste wejscie ignoruj przez ''trim().isEmpty()'' 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 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 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: * Pokazac workflow: FXML (widok) + Controller (logika) + CSS (styl) Zadanie demonstracyjne: * Widok logowania (email, haslo, przycisk) * Walidacja prostych danych i komunikat statusu * Stylowanie przycisku i tla Wskazowki: * Polacz ''fx:id'' z polami ''@FXML'' * ''onAction'' kieruj do metody w kontrolerze * Arkusz CSS podlacz przez ''scene.getStylesheets().add(...)'' 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: