====== Zajecia 9. - JavaFX - zadania do samodzielnego wykonania ====== ===== Organizacja ===== * Czas: 20-30 min * Forma: samodzielnie lub w parach * Zakres: od prostych kontrolek po mini-aplikacje z FXML i CSS ===== Zadanie A (latwe): Konwerter temperatur ===== Wymagania: * Pole wejscia temperatury * Dwa przyciski: ''C -> F'' i ''F -> C'' * Etykieta z wynikiem Wskazowki: * Uzyj ''Double.parseDouble'' * Obsluz ''NumberFormatException'' * Obliczenia: ''F = C * 9 / 5 + 32'' oraz ''C = (F - 32) * 5 / 9'' Rozwiazanie (przykladowe): btnCtoF.setOnAction(e -> { try { double c = Double.parseDouble(input.getText().trim()); result.setText(String.format("%.2f F", c * 9 / 5 + 32)); } catch (NumberFormatException ex) { result.setText("Blad danych"); } }); btnFtoC.setOnAction(e -> { try { double f = Double.parseDouble(input.getText().trim()); result.setText(String.format("%.2f C", (f - 32) * 5 / 9)); } catch (NumberFormatException ex) { result.setText("Blad danych"); } }); ===== Zadanie B (srednie): Formularz studenta ===== Wymagania: * Pola: imie, nazwisko, numer indeksu * ''ComboBox'' z kierunkiem studiow * Przycisk ''Zapisz'' wyswietla podsumowanie w ''TextArea'' Wskazowki: * Uzyj ''GridPane'' do ukladu formularza * Waliduj, czy pola tekstowe nie sa puste * Przed zapisem wyczysc ''TextArea'' i wpisz podsumowanie Rozwiazanie (przykladowe): saveBtn.setOnAction(e -> { String first = firstName.getText().trim(); String last = lastName.getText().trim(); String index = indexField.getText().trim(); String major = majorBox.getValue(); if (first.isEmpty() || last.isEmpty() || index.isEmpty() || major == null) { summary.setText("Uzupelnij wszystkie pola"); return; } summary.setText( "Student:\n" + "Imie: " + first + "\n" + "Nazwisko: " + last + "\n" + "Indeks: " + index + "\n" + "Kierunek: " + major ); }); ===== Zadanie C (srednie+): Lista wydatkow ===== Wymagania: * ''TableView'' z kolumnami: nazwa, kategoria, kwota * Dodawanie nowego wydatku przez formularz * Etykieta sumy wszystkich wydatkow Wskazowki: * Model danych jako klasa ''Expense'' z ''StringProperty'' i ''DoubleProperty'' * Po dodaniu rekordu aktualizuj etykiete sumy * Uzyj ''PropertyValueFactory'' albo bindingu kolumn Rozwiazanie (przykladowe): private final ObservableList expenses = FXCollections.observableArrayList(); private void updateTotal() { double total = expenses.stream().mapToDouble(Expense::getAmount).sum(); totalLabel.setText(String.format("Suma: %.2f PLN", total)); } addBtn.setOnAction(e -> { try { Expense expense = new Expense( nameField.getText().trim(), categoryBox.getValue(), Double.parseDouble(amountField.getText().trim()) ); expenses.add(expense); updateTotal(); } catch (Exception ex) { totalLabel.setText("Blad: sprawdz dane"); } }); ===== Zadanie D (trudniejsze): Logowanie w FXML + CSS + walidacja ===== Wymagania: * Widok w FXML (email, haslo, przycisk, status) * Kontroler z walidacja danych * Stylowanie przez zewnetrzny plik CSS * Przycisk aktywny tylko dla poprawnych danych Wskazowki: * ''fx:id'' mapuj na pola ''@FXML'' * Aktywacje przycisku zrob przez binding ''disableProperty'' * Reguly: email zawiera ''@'' i ''.'', haslo minimum 8 znakow Rozwiazanie (przykladowe): loginBtn.disableProperty().bind( Bindings.createBooleanBinding( () -> { String email = emailField.getText().trim(); String pass = passwordField.getText(); return !(email.contains("@") && email.contains(".") && pass.length() >= 8); }, emailField.textProperty(), passwordField.textProperty() ) ); loginBtn.setOnAction(e -> statusLabel.setText("Dane poprawne - logowanie...")); ===== Zadanie E (dla chetnych): Mini klient RIA ===== Wymagania: * Widok JavaFX pobiera dane JSON z lokalnego endpointu REST * Wyswietlenie listy rekordow (np. studenci) w ''ListView'' lub ''TableView'' * Obsluga bledu polaczenia Wskazowki: * Uzyj ''HttpClient'' i ''Task'' (nie blokuj watku UI) * Wynik wrzuc do UI przez ''Platform.runLater(...)'' * Przygotuj fallback: komunikat o bledzie i pusta lista Rozwiazanie (szkic): Task loadTask = new Task<>() { @Override protected String call() throws Exception { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("http://localhost:8080/api/students")) .GET() .build(); return HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandlers.ofString()) .body(); } }; loadTask.setOnSucceeded(e -> statusLabel.setText("Pobrano dane")); loadTask.setOnFailed(e -> statusLabel.setText("Blad polaczenia")); new Thread(loadTask).start(); ===== Kryteria oceny wykonania ===== * Dzialajacy interfejs i reakcja na zdarzenia * Poprawna walidacja danych i obsluga bledow * Czytelny podzial kodu (UI, logika, model) * Dla wyzszej oceny: FXML + CSS + binding + dobra struktura projektu