INSTRUKCJA DO ĆWICZENIA 2 Aplikacja zawiera przykłady ilustrujące wybrane metody graficzne klasy Graphics (powtórzenie) oraz klasy Graphics2D. Tworzenie własnej klasy, tworzącej wieloboki o zadanym kształcie oraz zawierającej metody obiektowe. Tworzenie listy obiektów oraz interfejs myszy powtórzenie I Ilustracja metod rysujących podstawowe elementy graficzne 1. Utwórz projekt na bazie klasy JFrame z pakietu Swing o nazwie Projekt2, z klasą główną Grafika. Jako tytuł ramki wpisz Grafika. Rozwiń menu podręczne ramki i w poleceniu Set Layout wybierz opcję Free Design. 2. Poniżej konstruktora klasy Grafika zdefiniuj klasę wewnętrzną Figury, dziedziczącą od klasy JComponent: class Figury extends JComponent { 3. W klasie Figury wpisz metodę paintcomponent() tworzącą na powierzchni komponentu rysunek złożony z tła, wyśrodkowanego napisu namalowanego czcionką f klasy Font oraz elementów geometrycznych: linii poziomej, wypełnionego prostokąta, koła i wycinka wraz z obramowaniem : g.clearrect(0, 0, getwidth(), getheight()); Font f = new Font("SanSerif", Font.ITALIC, 16); g.setfont(f); String s = "Rysowanie figur geometrycznych-powtórzenie"; int z = getwidth() / 2 - g.getfontmetrics().stringwidth(s) / 2; // 1/2 szerokości panelu odjąć 1/2 szerokości tekstu g.drawstring(s, z, 20); g.setcolor(color.black); g.drawline(0, getheight() / 2, getwidth(), getheight() / 2); g.setcolor(color.magenta); g.fillrect(30, 60, 80, 100); g.drawrect(30, 60, 80, 100); g.setcolor(color.red); g.filloval(getwidth() / 2-100, 50, 120, 130); g.drawoval(getwidth() / 2-100, 50, 120, 130); g.setcolor(color.green); g.fillarc(getwidth() - 150, 50, 120, 120, 20, 310); g.drawarc(getwidth() - 150, 50, 120, 120, 20, 310); 4. W konstruktorze klasy Grafika wywołaj metodę określającą rozmiary ramki oraz ustaw kolor tła metodą setbackground(): setbackground(color.orange); setsize(700, 500); Następnie dopisz instrukcje tworzące nowy komponent klasy Figury, dodające go do ramki i określające jego rozmiary i położenie: Figury figury = new Figury(); add(figury); figury.setbounds(0, 0, getwidth(), getheight()); 5. Uruchom aplikację i zobacz efekt wykonania metody paintcomponent(). 6. Pod nagłówkiem klasy Grafika zadeklaruj pole generatora liczb losowych: Random r = new Random(); 7. Dodaj do metody paintcomponent() instrukcje, które losowym kolorem rysują trójkąt równoramienny o wysokości 60 pikseli, którego podstawą jest dolna krawędź komponentu: int[] x = {0, getwidth() / 2, getwidth(); // tablica współrzędnych x wierzchołków trójkąta int[] y = {getheight(), getheight() - 100, getheight(); // tablica współrzędnych y wierzchołków trójkąta Color kolor = new Color(r.nextInt(256), r.nextint(256), r.nextint(256)); //losowy kolor g.setcolor(kolor); g.fillpolygon(x, y, 3); g.drawpolygon(x, y, 3); 8. Sprawdź działanie wpisanych instrukcji, zmieniając rozmiary okna ramki II Wykorzystanie okna z zakładkami klasa JTabbedPane 1. W menu podręcznym ramki w poleceniu Set Layout wybierz opcję Border Layout. Z palety komponentów przeciągnij na ramkę komponent Tabbed Pane z grupy Swing Containers. W kolejnych punktach ćwiczenia do utworzonego w ten sposób kontenera jtabbedpane1 będą dodawane strony z zakładkami, ilustrujące wybrane metody graficzne języka Java. Materiały do użytku wewnętrznego strona 1
2. W konstruktorze klasy Grafika usuń instrukcje: add(figury) oraz figury.setbounds(0, 0, getwidth(), getheight()); Zamiast nich. dopisz instrukcję dodającą komponent klasy Figury jako nową stronę komponentu jtabbedpane1: jtabbedpane1.add ("Przykłady figur", figury); 3. Sprawdź efekt wprowadzonych zmian. III Przykład metod graficznych klasy Graphics2D klasa GradientPaint, BasicStroke, metody- setpaint, rotate 1. Zdefiniuj kolejną klasę wewnętrzną o nazwie Grafika2D dziedziczącą od klasy JComponent; class Grafika2D extends JComponent{ 2. Wpisz w nowej klasie metodę rysująca komponent, utwórz w niej obiekt klasy Graphics2D i wpisz instrukcje rysowania prostokąta z wykorzystaniem gradientu koloru: Graphics2D g2d = (Graphics2D) g; GradientPaint g1 = new GradientPaint(0, 0, Color.blue, getwidth(), 0, Color.red); g2d.setpaint(g1); g2d.fillrect(0, 20, getwidth(), 40); 3. W konstruktorze klasy Grafika dodaj do kontenera jtabbedpane1 komponent klasy Grafika2D z tytułem Grafika 2D instrukcją: jtabbedpane1.add("grafika 2D ", new Grafika2D ()); Uruchom aplikację. 4. W metodzie paintcomponent() klasy Grafika2D dopisz deklarację nowego gradientu: GradientPaint g2 = new GradientPaint(10, 10, Color.blue, 15, 15, Color.red, true); 5. Utwórz instrukcje rysowania drugiego prostokąta za pomocą nowego gradientu i uruchom aplikację: g2d.setpaint(g2); g2d.fillrect(0, getheight() - 80, getwidth(), 40 ); 6. Dopisz instrukcje rysowania rozety z użyciem kolejnego gradientu i sprawdź ich efekt: g2d.setstroke(new BasicStroke(8.0f)); //ustalenie grubości pióra na 8 g2d.translate(getwidth() / 2, getheight()/ 2); //przesunięcie grafiki do środka komponentu for (int i = 0; i < 8; i++) { g2d.setpaint(new GradientPaint(20, 20, Color.red, 10, 30, Color.yellow, true)); g2d.rotate(math.pi / 4); g2d.fillrect(20, 20, 40, 40); g2d.drawline(0, 10, 0, 40); IV Przykład metod grafiki z klasy Graphics2D klasa TexturePaint 1. Zdefiniuj kolejną klasę wewnętrzną o nazwie Tekstura dziedziczącą od klasy JComponent; class Tekstura extends JComponent{ 2. Wpisz w nowej klasie metodę rysująca komponent, utwórz w niej obiekt klasy Graphics2D i wpisz instrukcje rysowania prostokąta z wykorzystaniem wzoru: Graphics2D g2 = (Graphics2D) g; BufferedImage bi = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB); Graphics2D big = bi.creategraphics(); big.setcolor(color.green); big.fillrect(0, 0, 10, 10); bi big.filloval(0, 0, 8, 8); Rectangle r = new Rectangle(0, 0, 5, 5); g2.setpaint(new TexturePaint(bi, r)); g2.fillrect(150, 50, 200, 250); 3. W konstruktorze klasy Grafika dodaj do kontenera jtabbedpane1 komponent klasy Tekstura z tytułem Tekstura instrukcją: jtabbedpane1.add("tekstura ", new Tekstura ()); Uruchom aplikację. 4. Na końcu metody paintcomponent() klasy Tekstura dodaj instrukcje rysujące prostokąt nową teksturą BufferedImage bi2 = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB); Graphics2D big2 = bi2.creategraphics(); big2.setcolor(color.yellow); big2.fillrect(0, 0, 10, 10); big2.setcolor(color.red); big2.drawline(0, 0, 10, 10); big2.drawline(0, 10, 10, 0); Rectangle r2 = new Rectangle(0, 0, 10, 10); g2.setpaint(new TexturePaint(bi2, r2)); g2.fillrect(350, 50, 200, 250); V Wyświetlanie obrazu z pliku. 1. Do foldera projektu przekopiuj plik graficzny GT.jpg z foldera sieciowego Informatyka\I2\cw2. Zdefiniuj kolejną klasę wewnętrzną o nazwie Obrazek dziedziczącą od klasy JPanel. Pod nagłówkiem klasy Obrazek zadeklaruj pole klasy Image o nazwie obrazek i przypisz mu obraz załadowany z pliku: Image obrazek = new ImageIcon("GT.jpg").getImage(); 2. Zadeklaruj w klasie Obrazek i oprogramuj metodę paintcomponent(), która zawiera instrukcję rysującą obrazek: Materiały do użytku wewnętrznego strona 2
g.drawimage(obrazek, 5, 5, getwidth() - 20, getheight() - 20, null); 3. W konstruktorze klasy Grafika dodaj do kontenera jtabbedpane1 komponent klasy Obrazek z tytułem Obrazek. Obejrzyj stronę z obrazkiem po uruchomieniu aplikacji. 4. Zdefiniuj kolejną klasę wewnętrzną o nazwie Obrazek2D dziedziczącą od klasy Obrazek. Zadeklaruj w tej klasie metodę paintcomponent(), która ogranicza obszar rysowania do elipsy: Graphics2D g2d = (Graphics2D) g; g2d.setclip(new Ellipse2D.Double(5, 5, getwidth() - 30, getheight() - 30)); super.paintcomponent(g); Słowo kluczowe super oznacza wywołanie metody paintcomponent() zdefiniowanej w klasie bazowej Obrazek 5. Dodaj do kontenera jtabbedpane1 obiekt klasy Obrazek2D z tytułem Obrazek 2D. Uruchom aplikację. VI Tworzenie nowej, własnej klasy dziedziczącej ze standardowej klasy Polygon 1. Utwórz w projekcie nową zewnętrzną klasę, umieszczając ją w tym samym pakiecie w którym znajduje się klasa Grafika. W tym celu kliknij prawym przyciskiem myszy i poleceniem New dodaj nowy plik typu Java Class, a następnie nadaj klasie nazwę Wielobok. 2. Spraw, aby utworzona klasa dziedziczyła właściwości i metody od zdefiniowanej w pakiecie java.awt klasy Polygon, która reprezentuje wieloboki. W tym celu uzupełnij nagłówek klasy do postaci: public class Wielobok extends Polygon { // klasę Polygon należy importować poleceniem Fix Imports 3. Pod nagłówkiem klasy umieść deklarację pola kolor: Color kolor; 4. Poniżej umieść konstruktor obiektów klasy Wielobok o zadanych wierzchołkach i kolorze. Ten konstruktor, którego dwa parametry tablicowe określają współrzędne (x, y) kolejnych wierzchołków a trzeci parametr określa kolor figury, ma następującą postać: Wielobok(int[] x, int[] y, Color k) { super(x, y, Math.min(x.length, y.length)); //wywołanie konstruktora klasy Polygon //trzeci parametr to liczba wierzchołków wyliczana jako minimum z długości obu tablic współrzędnych kolor=k; 5. Poniżej konstruktora dopisz metodę rysowania obiektu klasy Wielobok na kanwie obiektu klasy Graphics: void rysuj(graphics g) { g.setcolor(kolor); g.fillpolygon(this); // klasę Graphics należy zaimportować // zmiana bieżącego koloru dla kanwy graficznej // narysowanie wieloboku o kształcie obiektu klasy Wielobok (Polygon) 6. Usuń ewentualne błędy i zapisz zmiany wprowadzone w pliku Wielobok.java. VII Tworzenie klas dziedziczących z klasy Wielobok 1. Analogicznie jak w punkcie VI.1-2, utwórz nową klasę o nazwie Samochód dziedziczącą z klasy Wielobok. Pojawia się błąd, który zostanie usunięty po uzupełnieniu definicji klasy w sposób opisany poniżej. 2. Pod nagłówkiem klasy Samochód zadeklaruj dwa statyczne pola zawierające tablice współrzędnych x i y: (można skorzystać z pliku wspolrzedne.txt w folderze Informatyka\I2, zawierającego wartości współrzędnych) static int[] x = {0,10,10,12,20,22,22,68,68,72,78,80,80,90, 90,70,65,20,10,0; static int[] y = {35,35,38,42,42,38,35,35,36,42,42,38, 35,35,15,15,0,0,15,15; 3. Do definicji klasy Samochód dodaj konstruktor, a w nim metodą super wywołaj konstruktor nadrzędnej klasy Wielobok: Samochód(Color k) { super(x, y, k); // klasę Color należy importować // tu został wywołany konstruktor klasy nadrzędnej Wielobok z parametrami x, y, k 4. Podobnie utwórz klasę Lokomotywa dziedziczącą z klasy Wielobok, przy czym zmień odpowiednio współrzędne wektorów x i y na poniższe: static int[] x= {0,35,35,50,45,60,55,75,75,70,75,70,55,50,55, 45,50,45,30,25,30,20,25,20,5,0,5,0; static int[] y= {0,0,25,25,0,0,25,25,55,55,65,75,75,65,55,55, 65,75,75,65,55,55,65,75,75,65,55,55; 5. Utwórz konstruktor klasy Lokomotywa analogicznie jak w p.vii.3 6. Zapisz pliki utworzonych klas. Następnie przejdź do definicji klasy Grafika i utwórz kolejną klasę wewnętrzną o nazwie Pojazdy, która dziedziczy z klasy JPanel. class Pojazdy extends JPanel{ 7. W klasie Pojazdy zadeklaruj obiekty klas Samochód i Lokomotywa, dopisując poniżej nagłówka instrukcje: Samochód S; Lokomotywa L; Materiały do użytku wewnętrznego strona 3
7. Utwórz konstruktor klasy Pojazdy i wpisz w nim instrukcje tworzenia obiektów S i L oraz przesunięcia lokomotywy na panelu: Prawym przyciskiem myszy kliknij wewnątrz klasy Pojazdy i polecenie Insert Code utwórz konstruktor klasy Pojazdy i utwórz w nim obiekty klasy samochód i Lokomotywa: public Pojazdy() { S = new Samochód(Color.red); L = new Lokomotywa(Color.black); L.translate( 0, 100 ); 8. Poniżej konstruktora utwórz metodę paintcomponent() i wywołaj w niej metody rysowania obiektów S i L: g.clearrect(0, 0, getwidth(), getheight()); S.rysuj(g); L.rysuj(g); 9. Przejdź do konstruktora klasy Grafika i dopisz instrukcję tworzącą kolejną zakładkę komponentu TabbedPane1, która wyświetli grafikę obiektu klasy Pojazdy. jtabbedpane1.add ("Samochody i Lokomotywy", new Pojazdy()); VIII Dodanie nowych metod do klasy Wielobok 1. Na końcu klasy Wielobok dodaj metodę skaluj(), skalującą dany obiekt względem punktu (0, 0), tj. lewego górnego wierzchołka panelu: void skaluj(double sx, double sy){ for (int i = 0; i < npoints; i++) { xpoints[i] = (int) Math.round( xpoints[i]*sx ); ypoints[i] = (int) Math.round( ypoints[i]*sy ); 2. Pod nagłówkiem klasy Pojazdy, dopisz deklarację obiektu L1 klasy Lokomotywa : Lokomotywa L1; 3. W konstruktorze klasy Pojazdy utwórz ten obiekt nadając mu kolor żółty. Korzystając z wbudowanej metody translate() klasy Polygon, przesuń ten obiekt na panelu o wektor [100,100]. Następnie korzystając z własnej obiektowej metody skaluj() z parametrami (2, 1.5) zmień rozmiar tego obiektu : L1 = new Lokomotywa(Color.YELLOW); L1.translate(100, 100); L1.skaluj(2, 1.5); 4. W metodzie paintcomponent() dodaj instrukcję rysującą obiekt L1: L1.rysuj(g);. 5. Sprawdź działanie tych instrukcji uruchamiając aplikację 6. Podobnie jak w punktach VIII.2-4odpowiednio zadeklaruj i utwórz obiekt S1 klasy Samochód, nadając mu dowolny kolor. Wywołaj dla niego metodę skaluj() z parametrami (2, 1.5) oraz metodę translate() z parametrami (100, 0). Następnie w metodzie paintcomponent() narysuj ten obiekt. Uruchom aplikację i zobacz efekt swojej pracy. IX Tworzenie wielu obiektów klasy Samochód zastosowanie tablicy dynamicznej typu ArrayList oraz interfejsu myszy -powtórzenie Zmodyfikujemy aplikację Grafika tak, aby. kolejny samochód powstawał w miejscu wskazanym kursorem myszy. Wszystkie obiekty klasy Samochód będą zapisywane na dynamicznej liście.. 1. Pod nagłówkiem klasy Pojazdy zadeklaruj dynamiczną tablicę samochodów List< Samochód> LK = new ArrayList<>(); Zaimportuj klasy List i ArrayList z pakietu java.util. 2. W treści metody paintcomponent() dopisz instrukcje rysowania wszystkich obiektów umieszczonych w dynamicznej tablicy LK: for (Samochód K : LK) { K.rysuj(g); 3. Aby na panelu umożliwić tworzenie samochodów za pomocą myszy, doprowadź nagłówek klasy Pojazdy do postaci: class Pojazdy extends JPanel implements MouseListener Zaimportuj ten interfejs, utwórz wszystkie jego abstrakcyjne metody, usuń w nich instrukcje throw wyrzucające wyjątek, a metodę mousepressed() uzupełnij do postaci: public void mousepressed(mouseevent e) { int x = e.getx(); int y = e.gety(); if (e.getbutton() == MouseEvent.BUTTON1) { Samochód S = new Samochód(new Color(r.nextInt(256), r.nextint(256), r.nextint(256))); S.translate( x, y ); LK.add(S); else { LK.clear(); //usuwanie wszystkich obiektów prawym lub środkowym przyciskiem myszy repaint(); Materiały do użytku wewnętrznego strona 4
4. W konstruktorze klasy Pojazdy dopisz instrukcję dodającą nasłuch akcji związanej z myszą: addmouselistener( this ); 5. Uruchom aplikację i sprawdź działanie przycisków myszy. 6. Aby wypełnić obiekty klas Samochód i Lokomotywa gradientem koloru lub teksturą, zdefiniuj w klasie Wielobok dodatkową metodę rysowania wieloboków: void rysujtekstura( Graphics2D g ) { g.fillpolygon(this); 7. Dopisz w klasie Tekstura, instrukcje tworzące obiekty klas Samochód i Lokomotywa. Następnie w metodzie paintcomponent() tej klasy, narysuj te obiekty korzystając z metody rysujtekstura() tak, by powstał obraz przedstawiony obok. Zadania do samodzielnego rozwiązania 1. W klasie Grafika2D zmodyfikuj instrukcje rysowania rozety. W pętli for (int i = 0; i < 8; i++) zmień instrukcje ustalania gradientu na następującą: g2d.setpaint(new GradientPaint(0, 0, Color.red, 10, 5, Color.white, true)); Uruchom aplikację, obejrzyj nową postać rozety. Zaproponuj własne modyfikacje rysunku. Zmień w dowolny sposób instrukcje rysowania prostokątów z wykorzystaniem gradientu koloru. 2. W klasie Tekstura zmodyfikuj instrukcje wypełniania prostokąta tak, aby miał on wygląd jak na rysunku. W poszczególnych częściach prostokąta zastosuj różne kolory figur. 3. Dodaj do klasy Wielobok metodę void obrót (int x0, int y0, int alfa), obracającą obiekt tej klasy o podany w stopniach kąt alfa względem punktu (x 0, y 0 ). Punkty po transformacji opisywane są wzorem: ' ' x = xcosα ysinα + x x cosα + y sinα; y = xsinα + ycosα + y x sinα y cosα 0 0 0 0 0 0 (kąt α w radianach) Następnie przetestuj działanie tej metody na obiektach klas Samochód i Lokomotywa. 4. Wykorzystaj klasę Wielobok do narysowania trójkąta w klasie Figury. Zamiast istniejącej instrukcji rysowania trójkąta utwórz nowy obiekt T klasy Wielobok i wywołaj na rzecz tego obiektu metodę rysuj() Wielobok T = new Wielobok(x, y, Color.WHITE); T.rysuj(g); // wielobok T jest trójkątem równoramiennym 5. Wykorzystując poznane metody graficzne, zdefiniuj nową klasę wewnętrzną o nazwie MojaGrafika dziedziczącą od klasy JPanel. Narysuj w niej dowolny obrazek, a następnie dodaj do kontenera jtabbedpane1. 6. Namaluj dowolny obrazek w aplikacji paint, a następnie wyświetl go na zakładce o tytule Obrazek i Obrazek2D 7. Tak zmodyfikuj klasę Grafika2D, by powstał obraz przedstawiony poniżej Materiały do użytku wewnętrznego strona 5