Zajecia 9. - JavaFX - zadania do samodzielnego wykonania

Writing /home/grochu/public_html/wiki/data/meta/zajecia/java_2026_1/sidebar.meta failed
Unable to save metadata file. Hint: disk full; file permissions; safe_mode setting.

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<Expense> 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<String> 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