Zadania praktyczne i samodzielne

Writing /home/grochu/public_html/wiki/data/cache/1/1648358e3444afb47655d5afdbdbc940.i failed
Unable to save cache file. Hint: disk full; file permissions; safe_mode setting.
Writing /home/grochu/public_html/wiki/data/cache/1/1648358e3444afb47655d5afdbdbc940.metadata failed
Writing /home/grochu/public_html/wiki/data/cache/7/75e079481936e0d8ade254ee02e13f30.i failed
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.

Zadanie 5.2 z zajęć PA

Wykorzystując bibliotekę AWT stwórz prosty minutnik, który pozwala na odliczanie czasu od wartości podanej przez użytkownika do 0. Po zakonczeniu odliczania poinformuj o tym użytkownika (np. zmieniając kolor tła okna lub wyświetlając widoczną informację). Aplikacja powinna posiadać możliwość uruchomienia odliczania, zatrzymania go, ponownego uruchomienia i powrotu do stanu pierwotnego licznika. W swoim kodzie postaraj się wykorzystać wątki.

Demo 1 (10-15 min): Mini-formularz

Cel: przećwiczyć Frame, Panel, TextField, Button, ActionListener.

Kroki:

  1. utwórz Frame z BorderLayout
  2. dodaj dwa pola TextField (imię, nazwisko)
  3. dodaj przycisk Pokaż
  4. po kliknięciu wyświetl Label: „Witaj, Imię Nazwisko”

Wskazówki:

  • logikę przycisku zapisz jako lambda
  • przypnij WindowAdapter, by poprawnie zamknąć aplikację

Skrócone rozwiązanie:

showButton.addActionListener(e -> {
    resultLabel.setText("Witaj, " + nameTf.getText() + " " + surnameTf.getText());
});

Demo 2 (10-15 min): Canvas - rysowanie i czyszczenie

Cel: przećwiczyć Canvas, paint(), repaint(), MouseMotionListener.

Kroki:

  1. przygotuj klasę PaintCanvas przechowującą listę punktów
  2. w mouseDragged dodawaj punkt i wywołuj repaint()
  3. dodaj przycisk Wyczyść, który resetuje listę punktów

Wskazówki:

  • nie rysuj bezpośrednio w listenerze
  • paint ma tylko odtwarzać stan zapisany w polach klasy

Skrócone rozwiązanie:

clearButton.addActionListener(e -> canvas.clearAll());

Demo 3 (opcjonalne): Zmiana layoutu w runtime

Cel: pokazać różnicę między FlowLayout i GridLayout.

Kroki:

  1. utwórz panel z 6 przyciskami
  2. przełączaj layout przyciskiem Przełącz układ
  3. po zmianie wykonaj panel.validate() i panel.repaint()

Zadania samodzielne - poziom podstawowy

  1. Zadanie A1: Kalkulator sumy
    • Dwa pola TextField + przycisk Oblicz + Label z wynikiem
    • Obsłuż błędne dane (NumberFormatException) i pokaż komunikat
  2. Zadanie A2: Licznik kliknięć
    • Przycisk Kliknij mnie zwiększa licznik i odświeża Label
  3. Zadanie A3: Formularz wyboru
    • CheckboxGroup (np. „Tryb A / Tryb B”) i Choice z 3 opcjami
    • Po zmianie wyboru aktualizuj etykietę podsumowującą

Zadania samodzielne - poziom średni

  1. Zadanie B1: Notatnik mini
    • TextArea + przyciski Wyczyść i Statystyki
    • Statystyki pokazują liczbę znaków i linii
  2. Zadanie B2: Prosty rysownik figur
    • Na Canvas rysuj kliknięciem koło lub prostokąt (wybór przez Choice)
    • Dodaj zmianę koloru figur (np. Checkbox lub Choice)
  3. Zadanie B3: Okno „Ustawienia”
    • Główne okno Frame + Dialog niemodalny
    • W dialogu użytkownik zmienia rozmiar czcionki etykiety w głównym oknie

Zadania samodzielne - poziom zaawansowany

  1. Zadanie C1: Prosty program do rysowania
    • Rysowanie na formie lub Canvas przy wciśniętym klawiszu myszy. Rejestruj kolejne punkty w odpowiedniej strukturze danych tak aby można było je później odtworzyć.
    • Dodaj możliwość wyboru koloru i grubości linii
    • Dodaj przycisk „Wyczyść” do usuwania rysunku
    • Dodaj przycisk „Zapisz” do zapisywania rysunku do pliku (np. jako obraz PNG)
    • Dodaj przycisk „Animuj”, który odtwarza sekwencję rysowania (odtwarzanie kolejnych punktów z opóźnieniem) w osobnym wątku. Zatrzymanie animacji powinno być możliwe po ponownym kliknięciu „Animuj”.
  2. Zadanie C2: Animacja w AWT
    • Obiekt (kula/prostokąt) porusza się po Canvas i odbija od krawędzi
    • Aktualizacja położenia w osobnym wątku + repaint()
  3. Zadanie C3: Mini-gra „reakcja”
    • Co losowy czas pojawia się cel; użytkownik klika jak najszybciej
    • Mierz czas reakcji i wyświetl średnią z ostatnich N prób

Podpowiedzi i szkice rozwiązań do zadań samodzielnych

  • A1 (Kalkulator sumy):
    • Podpowiedź: parsuj przez Integer.parseInt(…) w try/catch
    • Szkic rozwiązania:
try {
    int a = Integer.parseInt(aField.getText().trim());
    int b = Integer.parseInt(bField.getText().trim());
    result.setText("Suma: " + (a + b));
} catch (NumberFormatException ex) {
    result.setText("Błąd: podaj poprawne liczby całkowite");
}
  • A2 (Licznik kliknięć):
    • Podpowiedź: licznik trzymaj w polu klasy, nie w zmiennej lokalnej callbacka
    • Szkic rozwiązania: counter++; label.setText(„Kliknięcia: ” + counter);
  • B1 (Notatnik mini):
    • Podpowiedź: liczba linii = textArea.getText().split(„\R”, -1).length
    • Szkic rozwiązania: po kliknięciu Statystyki pokaż wynik w Label lub Dialog
  • B2 (Rysownik figur):
    • Podpowiedź: przechowuj listę obiektów ShapeModel (typ, x, y, kolor)
    • Szkic rozwiązania: w paint iteruj po liście i rysuj odpowiednią figurę
  • C2 (Animacja):
    • Podpowiedź: osobny wątek aktualizuje pozycję co 16-25 ms, UI tylko odmalowuje
    • Szkic rozwiązania:
new Thread(() -> {
    while (running) {
        x += vx;
        y += vy;
        if (x < 0 || x > getWidth() - size) vx = -vx;
        if (y < 0 || y > getHeight() - size) vy = -vy;
        repaint();
        try { Thread.sleep(16); } catch (InterruptedException ignored) {}
    }
}).start();

Wskazówki do zadań i kryteria oceny

  • Minimalne wymagania:
    • poprawna obsługa zamknięcia okna
    • sensowny layout (bez setLayout(null))
    • działająca obsługa zdarzeń
  • Dodatkowe punkty:
    • walidacja danych wejściowych
    • czytelny podział kodu na klasy
    • użycie adapterów tam, gdzie mają sens
    • brak „zawieszania” GUI