poniedziałek, 17 lutego 2014

Podstawowa grafika 2D


Kod źródłowy do tej lekcji znajduje się tutaj. Rozpakuj go i zaimportuj. W katalogu z kodem źródłowym znajdą się podkatalogi oznaczone numerami. Są to po prostu kolejne wersje kodu, tworzonego w ramach przykładów. Możesz analizować kolejne kroki tworzenia aplikacji, lub od razu zabrać się za kod z katalogu o najwyższym numerku.



Aby wykonywać jakiekolwiek rysunki, będziemy potrzebowali płótna na którym będziemy rysować. Takie płótno będzie obiektem klasy Canvas. Tworzę zwyczajny projekt, a z ekranu głównego usuwam domyślnie pojawiający się tam kompontent textView1. Zasadniczo nasze płótno przykryje całość ekranu włącznie z tym komponentem, więc kasowanie go nie jest konieczne.


Obiekt klasy Canvas początkowo będzie pusty. Możemy rysować obiekty korzystając z wyznaczania kolejnych linii wg współrzędnych, ale możemy też skorzystać z gotowych w klasie Canvas metod które narysują dla nas wybrane figury geometryczne – typu prostokąt czy okrąg. Aby stworzyć i wykorzystywać nasze „płótno”, nasza aktywność musi posiadać wewnętrzną klasę dziedziczącą po klasie View dla której przesłaniamy metodę „onDraw” przyjmującej jako parametr obiekt klasy canvas z którego będziemy korzystać. Myślę że posłużymy się tutaj obrazem. Pierwsze co robię, to do aktywności na której chcę rysować dodaję klasę wewnętrzną CanvasView (nazwa dowolna), dziedziczącą po klasie View (android.view.View). Musimy dodać do niej konstruktor przyjmujący jako parametr kontekst. W zasadzie z kontekstem nic szczególnego tutaj nie robimy, jedynie przekazujemy je do super klasy, niemniej taki konstruktor po prostu musi się tutaj pojawić (wymogi implementacyjne klasy View). Nas bardziej interesuje metoda „onDraw”, bo to w niej właśnie opisujemy wszystko co ma zostać narysowane na „dzień dobry” na naszym płótnie.

Jak na razie, nic szczególnego się nie dzieje. Musimy sprawić, by zamiast domyślnego layoutu (tego określanego w pliku XML), na ekranie pojawiło się nasze „płótno”.


Zmiany tej dokonałem podmieniając parametr dla metody setContentView w metodzie onCreate naszej aktywności. Widzimy to na powyższej ilustracji w linii 26. W linii 25 pozostawiłem (dla przykładu) wykomentowane domyślne ustawienie.
Skoro już wszystko mamy popodpinane, zajmiemy się teraz samym rysowaniem. Dodałem trzy linie do metody onDraw. W linii 19 definiuję obiekt klasy Paint. Jest to pędzel którym będziemy rysować różne kształty. Możemy dla niego ustawiać różne parametry – np. kolor – ale o tym za chwilę. Linie 20 i 21 to wywołanie metody drawLine , służącej rysowaniu linii. Przyjmuje ona 5 parametrów. Wg. Kolejności: X początkowe, Y początkowe, X końcowe, Y końcowe, obiekt klasy paint którym rysujemy (nasz pędzel). Narysowałem więc po prostu dwie linie złączone na końcach:



Efekt:


Pobawimy się teraz kolorami pędzla. Do zmiany jego koloru, służy metoda setARGB klasy Paint (której nasz pędzel jest obiektem). Przyjmuje ona cztery parametry. Pierwszy to stopień przeźroczystości linii / figury. 0 to całkowita przeźroczystość – czyli w praktyce niewidoczność, 255 to całkowita nieprzezroczystość. Kolejne trzy parametry to RGB - stopień nasycenia trzech kolorów wg kolejności : Red, Green,Blue. Przyjmowane wartości to 0-255. Przed narysowaniem pierwszej linii ustawiam kolor pędzla na czerwień (255 dla RED, reszta 0), następnie rysuję linię. Ponownie zmieniam kolor pędzla, tym razem na zielony (255 dla GREEN, reszta 0) i znowu rysuję linię:



Efekt:



Wzbogaciłem kod o kolejne kilka linii. Zmieniłem kolor pędzla na niebieski i dorysowałem kolejną linię. Doszło nam wywołanie metody setStrokeWidth dla pędzla (linia 25). Ustawia ona grubość linii pędzla:



Efekt:


Zajmiemy się teraz rysowaniem figur geometrycznych. Zaczniemy od prostokątów (i kwadratów, wszak kwadrat też jest prostokątem tyle że o równych ramionach :) ).
Stworzyłem nowy projekt, wszystko na identycznej zasadzie jak w poprzednim przykładzie. Różni się tylko zawartością metody onDraw:



Metoda setARGB jest już znana z poprzednich przykładów, jednak tutaj pobawiłem się troszkę przezroczystością. Z nowych rzeczy mamy tutaj dwukrotne wywołanie metody drawRect klasy Canvas. Metoda ta służy rysowaniu prostokątów. Pierwsze dwa argumenty to współrzędne (x,y) jednego z rogów, kolejne dwa to współrzędne(x,y) rogu przeciwległego. W tym przypadku według kolejności – lewy górny i prawy dolny. Ostatni argument to obiekt klasy Paint, czyli pędzel którym będziemy rysować. Tutaj narysowałem dwa prostokąty – jeden nieprzezroczysty fioletowy ((?) sorry, mężczyźni nie rozróżniają kolorów zbyt szczegółowo) , drugi częściowo przezroczysty w kolorze szybki przyciemnianych okularów (?). Drugi ma ustawioną częściową przezroczystość. W przypadku rysowania pierwszego prostokąta przezroczystość dla pędzla ustawiłem na 0, w drugim na 100. Efekt wygląda tak:



Rysowanie kółek nie sprawia również wielu problemów. Stworzyłem kolejny projekt, tym razem metoda onDraw wygląda tak:

Generalnie do rysowania kół służy metoda drawCircle która przyjmuje cztery parametry. Pierwsze dwa to X i Y środka koła, trzeci to promień, a czwarty to pędzel którego parametry ustawiamy na identycznych zasadach co wcześniej. Zaprzęgnąłem tutaj pętle do wyrysowania mi kilku kół, które częsciowo na siebie nachodzą. W zasadzie cały kod to rysowane w rożnych miejscach koła, ze zmianą właściwości pędzla. Efekt wygląda tak :



Robacek :) Ponieważ uznałem że przeciętny robaczek żyje na listku/trawce/gałązce/czołgu/czymś innym zielonym, musiałem zmienić kolor tła. Do tego celu użyłem (linia 20) metody drawRGB obiektu klasy Canvas. Ta metoda nie przyjmuje atrybutu przezroczystości tak metoda drawARGB dla obiektów klasy Paint. Płótno samo w sobie nie może być przezroczyste :). Kolejność kolorów jak sama nazwa wskazuje RGB - Red, Green, Blue.

6 komentarzy:

  1. Nie wypada tworzyć obiektu Paint w metodzie onDraw (nawet środowisko to zauważyło:) )

    OdpowiedzUsuń
    Odpowiedzi
    1. A gdzie prawidłowo powinien być tworzony obiekt Paint?
      Reszta kodu jest w dobrym miejscu?
      (Wybacz - pytanie początkującego)

      Usuń
  2. A ja chciałbym wiedzieć jak narysować okrąg, da się w prosty sposób?

    OdpowiedzUsuń
    Odpowiedzi
    1. Sam sobie odpowiem, bo już znalazłem, trzeba ustawić: p.setStyle(Paint.Style.STROKE) :)

      Usuń