Java 3.pdf

(213 KB) Pobierz
Kurs Javy. Praktyczne progr...
Kurs Javy. Praktyczne programowanie, część III
http://webhosting.pl/print/Kurs.Javy..Praktyczne.programowanie.czesc.III
Kurs Javy. Praktyczne programowanie, część III
W poprzedniej części kursu dowiedzieliśmy się, w jaki sposób stworzyć aplet w Javie i jak renderować
grafikę. Ta część pozwoli nam na zgłębienie wiedzy z tego zakresu na przykładzie apletu Zegar, który
pokazuje sposób zaprogramowania zegara analogowego. Zapoznamy się także z wątkami, czyli
zadaniami, które mogą być wykonywane przez program równocześnie.
Spis treści
4. Wątki
4.1. Szkielet programu
4.2. Rysujemy zegar
4.3. Aktualny czas
4.4. Pojęcie wątku
4.5. Dodajemy kolejny wątek
4.6. Kod źródłowy aplikacji Zegar
4. Wątki
4.1. Szkielet programu
Tak jak w poprzedniej części kursu, tak i w tej tworzenie apletu rozpoczynamy od utworzenia projektu,
wybierając z paska menu edytora NetBeans File | New Project . Przechodzimy wszystkie znane już nam
kroki, wpisując nazwę projektu jako Zegar oraz nazwę pliku apletu o tej samej nazwie. Generuje to nam
szablon apletu. Przystępujemy zatem do tworzenia panelu dla apletu w postaci osobnej klasy. W tym celu w
oknie Project klikamy prawym przyciskiem myszy nazwę projektu i z menu kontekstowego wybieramy New |
Java Class . Jako nazwę nowej klasy wpisujemy PanelZegar . Zostanie wygenerowana pusta klasa. Nie
musimy ręcznie umieszczać w niej konstruktora – wystarczy, że umieścimy wskaźnik myszy między
otwierającym a zamykającym nawiasem klamrowym i wciśniemy kombinację klawiszy [Ctrl]+[spacja] .
Rysunek 29: Przygotowanie klasy PanelZegar.
1 z 12
20101122 00:58
629491247.011.png 629491247.012.png 629491247.013.png
Kurs Javy. Praktyczne programowanie, część III
http://webhosting.pl/print/Kurs.Javy..Praktyczne.programowanie.czesc.III
Wywoła to okienko z listą, w której zaznaczamy konstruktor. Podwójne kliknięcie jego nazwy lewym
przyciskiem myszy wygeneruje ten konstruktor w kodzie klasy.
W identyczny sposób możemy umieścić wewnątrz klasy zmienne czy metody odziedziczone po klasach
nadrzędnych, modyfikatory i tym podobne obiekty języka. My chcieliśmy utworzyć klasę stanowiącą panel
dla apletu, powinniśmy ją zatem rozszerzyć o klasę JPanel . Po nazwie konstruktora wpisujemy więc słowa
extends JPanel . NetBeans podświetli nam JPanel na czerwono, dając znak, że nie mamy zaimportowanego
pakietu, z którego pochodzi ta klasa. Pakiet możemy zaimportować automatycznie, wciskając kombinację
klawiszy [Ctrl]+[Shift]+[I] (jeśli chcemy zaimportować wszystkie klasy, których jeszcze nie
zaimportowaliśmy) lub [Alt]+[Shift]+[I] (gdy zależy nam tylko na tej jednej, którą zaznaczyliśmy).
Wewnątrz konstruktora za pomocą metody setSize() definiujemy rozmiar panelu:
import javax.swing.JPanel;
public class PanelZegar extends JPanel
{
public PanelZegar() { setSize(200,200); }
}
Aby przygotowany panel dodać do powierzchni apletu, przechodzimy w oknie edytora do pliku Zegar.java i
wewnątrz metody init() tworzymy egzemplarz klasy PanelZegar . Następnie, korzystając z metody add() ,
dodajemy go do powierzchni apletu. Aby panel pasował rozmiarami do powierzchni apletu, przed dodaniem
określamy jego wymiary:
public void init() {
setSize(200,200);
PanelZegar pz=new PanelZegar();
add(pz);
}
4.2. Rysujemy zegar
Mamy już gotowy pusty panel o odpowiednich rozmiarach. Możemy więc przystąpić do rysowania na jego
powierzchni. Rysowanie odbywa się za pośrednictwem obiektu Graphics , dostarczanego przez metodę
paintComponent() . To w niej wykonujemy wszystkie operacje związane z grafiką. Na początek rzutujemy
obiekt Graphics na obiekt Graphics2D , który dostarcza kilku dodatkowych metod, oprócz tych dostępnych
w klasie Graphics :
public void paintComponent(Graphics g)
{
Graphics2D g2=(Graphics2D)g;
}
Klasa Graphics2D jest podklasą klasy Graphics i może po niej dziedziczyć. Dlatego też oprócz metod
klasy Graphics dostarcza swoje własne metody (klasy Graphics2D).
Na początku należy wyczyścić zawartość panelu. Posłużymy się w tym celu metodą clearRect() , której
argumentami są współrzędne górnego lewego wierzchołka prostokątnego obszaru oraz jego szerokość i
wysokość. Pomoże nam to w prawidłowym odmalowaniu zawartości panelu podczas odświeżania. Następnie
przystępujemy do rysowania tarczy zegara. Za pomocą metody setColor() ustawiamy kolor pędzla na
jasnoniebieski:
g2.setColor(new Color(0,204,255));
Następnie pobieramy bieżący styl kreski. Służy do tego metoda getStroke() klasy Graphics2D , która zwraca
obiekt typu Stroke :
2 z 12
20101122 00:58
629491247.014.png 629491247.001.png
Kurs Javy. Praktyczne programowanie, część III
http://webhosting.pl/print/Kurs.Javy..Praktyczne.programowanie.czesc.III
Stroke kreska=g2.getStroke();
Po co pobierać styl kreski? Zachowanie go w zmiennej kreska pozwoli nam później na łatwe wprowadzanie
zmian w sposobie rysowania kreski w danym kontekście graficznym i powracanie później do stylu
pierwotnego.
Przed narysowaniem niebieskiego koła definiujemy stałą klasową typu całkowitego (integer), która będzie
przechowywała długość promienia figury. Stałą określamy słowem kluczowym final zapisanym zaraz po
modyfikatorze dostępu. Nazwy stałych przyjęło się pisać wielkimi literami. Warto pamiętać, że zawartości
stałej, w przeciwieństwie do zmiennej, nie możemy już zmienić. Modyfikatorem dostępu dla stałej PROMIEN
jest private , dzięki czemu będzie ona dostępna jedynie dla klasy, w której została zdefiniowana.
public class PanelZegar extends JPanel {
private final int PROMIEN=80;
....
}
W naszym przypadku mamy do dyspozycji panel o rozmiarze 200 na 200 pikseli. Przeznaczymy 20 pikseli
wolnego obszaru na obramowanie wokół powierzchni zegara. Nasz zegar będzie miał wówczas 160 pikseli
średnicy (20040), zatem jego promień będzie wynosił 80 pikseli.
Wypełnione koło rysujemy za pomocą metody fillOval() kontekstu graficznego. Metoda pobiera jako swoje
parametry lewy górny punkt wierzchołka prostokąta oraz jego szerokość i wysokość. Wewnątrz prostokąta
zostaje narysowana z wypełnieniem elipsa lub koło – w zależności od tego, czy boki prostokąta są równe czy
też nie:
g2.fillOval(20,20,PROMIEN*2,PROMIEN*2);
Rysunek 30: Rysowanie koła metodą
fillOval.
Metoda fillOval(0,0,200,200) narysuje nam koło o średnicy 200 pikseli, czyli promieniu równym 100 pikseli.
Korzystając zaś z metody fillOval(0,0,200,100), uzyskamy elipsę. To, czy będzie to koło czy elipsa, zależy od
różnicy szerokości i wysokości obszaru. Jeśli są one równe, uzyskamy koło.
Podobnie wygląda sprawa z narysowaniem prostokąta i kwadratu. Jeśli wartości szerokości i wysokości będą
równe, zostanie narysowany kwadrat. Dlatego właśnie nie istnieją specjalne metody kontekstu graficznego do
rysowania koła czy kwadratu – wystarczą w tym celu uogólnione rozwiązania.
Po raz kolejny ustawiamy kolor pierwszego planu na granatowy:
3 z 12
20101122 00:58
629491247.002.png 629491247.003.png 629491247.004.png
Kurs Javy. Praktyczne programowanie, część III
http://webhosting.pl/print/Kurs.Javy..Praktyczne.programowanie.czesc.III
g2.setColor(new Color(0,0,51));
Tym kolorem narysujemy obwódkę wokół niebieskiego koła:
g2.drawOval(20,20,PROMIEN*21,PROMIEN*21);
Do narysowania obwódki służy metoda drawOval() , która ma takie same parametry jak metoda fillOval() .
Różni się ona w tym przypadku tylko parametrem trzecim i czwartym ze względu na pomniejszenie szerokości
i wysokości pola o 1 piksel.
W podobny sposób rysujemy środek koła:
g2.drawOval(SRODEK1,SRODEK1,1,1);
Metody kontekstu graficznego rozpoczynające się słowem draw rysują obiekt bez wypełnienia go
wewnątrz, podczas gdy metody rozpoczynające się słowem fill rysują obiekt wypełniony.
Oczywiście nie możemy zapomnieć o deklaracji na początku klasy PanelZegar stałej SRODEK :
private final int SRODEK=PROMIEN+20;
Po zapisaniu plików w edytorze NetBeans ( File | Save All ) możemy przystąpić do kompilacji ( [F11] ) i
uruchomienia apletu ( [Shift]+[F6] ).
Pierwszy z apletów przedstawia wygląd tarczy zegara, którą stworzono bez odjęcia od długości średnicy 1
piksela w wywołaniu metody drawOval() , obrysowującej niebieskie koło. Drugi rysunek to wywołanie tej
samej metody, ale z pomniejszeniem długości średnicy przy wywołaniu tej samej metody. Jak widać, na
pierwszym aplecie tarcza nie jest całkowicie wypełniona niebieskim kolorem.
Na tarczy narysujemy jeszcze cztery podstawowe kreski, wyznaczające godzinę dwunastą, trzecią, szóstą oraz
dziewiątą. Do wykonania tego zadania wykorzystamy obiekt klasy Line2D .
Istnieją dwie klasy wywodzące się z klasy Line2D: klasa Line2D.Double oraz klasa Line2D.Float. Nie
możemy bezpośrednio utworzyć obiektu klasy Line2D, ponieważ jest to klasa abstrakcyjna – musimy
skorzystać z którejś z klas pochodnych. Obiekt klasy Line2D.Double pobiera argumenty w postaci liczb
zmiennoprzecinkowych typu double, a obiekt klasy Line2D.Float pobiera liczby zmiennoprzecinkowe
mniejszej precyzji typu float.
4 z 12
20101122 00:58
629491247.005.png 629491247.006.png 629491247.007.png 629491247.008.png
Kurs Javy. Praktyczne programowanie, część III
http://webhosting.pl/print/Kurs.Javy..Praktyczne.programowanie.czesc.III
Na wstępie tworzymy obiekty typu Line2D, a następnie przekazujemy je w postaci parametru do rysującej
linię metody drawLine() :
Line2D kreska12=new Line2D.Double(PROMIEN+20,20,PROMIEN+20,24);
g2.draw(kreska12);
Line2D kreska6=new Line2D.Double(PROMIEN+20,20+PROMIEN*241,PROMIEN+20,20+PROMIEN*21);
g2.draw(kreska6);
Line2D kreska3=new Line2D.Double(20,PROMIEN+20,24,PROMIEN+20);
g2.draw(kreska3);
Line2D kreska9=new Line2D.Double(PROMIEN*2+204,PROMIEN+20,PROMIEN*2+20,PROMIEN+20);
g2.draw(kreska9);
Każda kreska godzinowa będzie miała 4 piksele długości. Teraz tarcza zegara jest już gotowa:
Rysunek 31: Aplet zegara z
zaznaczonymi godzinami.
4.3. Aktualny czas
Co to za zegar, który nie pokazuje aktualnego czasu? Na szczęście w Javie możemy skorzystać z zawartej w
pakiecie java.util klasy GregorianCalendar . Obiekt tej klasy pobiera lokalny czas i datę:
gkalendarz=new GregorianCalendar();
Oczywiście przed utworzeniem egzemplarza klasy musimy pamiętać, aby na początku klasy zadeklarować
prywatną zmienną gkalendarz typu GregorianCalendar . Obiektowi możemy również przypisać wartość
null , tak aby mieć pewność, że jest on pusty:
private GregorianCalendar gkalendarz=null;
W jaki sposób pobrać czas? Mamy już utworzony obiekt GregorianCalendar , który przechowuje bieżący
czas, wystarczy się zatem posłużyć metodą get() , żeby pobrać z niego godzinę, minuty i sekundy. Metoda ta
należy do klasy Calendar , z której wywodzi się klasa GregorianCalendar . Parametrem metody jest zmienna
statyczna klasy Calendar , która przybiera wartości w postaci liczby całkowitej:
int godz=gkalendarz.get(Calendar.HOUR);
int min=gkalendarz.get(Calendar.MINUTE);
int sek=gkalendarz.get(Calendar.SECOND);
Jako że zmienne statyczne należą do klasy, to ich wartości pobieramy nie z obiektu, lecz z klasy. Aby pobrać
wartość takiej zmiennej, wystarczy podać nazwę klasy i po znaku kropki nazwę zmiennej statycznej. Zmienne
statyczne – podobnie jak stałe – zapisuje się zazwyczaj dużymi literami, nie jest to jednak obowiązkowa
notacja.
5 z 12
20101122 00:58
629491247.009.png 629491247.010.png
Zgłoś jeśli naruszono regulamin