===== Zadania praktyczne i samodzielne =====
==== 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:
- utwórz ''Frame'' z ''BorderLayout''
- dodaj dwa pola ''TextField'' (imię, nazwisko)
- dodaj przycisk ''Pokaż''
- 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:
- przygotuj klasę ''PaintCanvas'' przechowującą listę punktów
- w ''mouseDragged'' dodawaj punkt i wywołuj ''repaint()''
- 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:
- utwórz panel z 6 przyciskami
- przełączaj layout przyciskiem ''Przełącz układ''
- po zmianie wykonaj ''panel.validate()'' i ''panel.repaint()''
==== Zadania samodzielne - poziom podstawowy ====
- Zadanie A1: Kalkulator sumy
* Dwa pola ''TextField'' + przycisk ''Oblicz'' + ''Label'' z wynikiem
* Obsłuż błędne dane (''NumberFormatException'') i pokaż komunikat
- Zadanie A2: Licznik kliknięć
* Przycisk ''Kliknij mnie'' zwiększa licznik i odświeża ''Label''
- 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 ====
- Zadanie B1: Notatnik mini
* ''TextArea'' + przyciski ''Wyczyść'' i ''Statystyki''
* ''Statystyki'' pokazują liczbę znaków i linii
- 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'')
- 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 ====
- 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".
- 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()''
- 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