I. labor 1. A Java fejlesztői csomag (JDK) letöltése és telepítése után töltsük le a megfelelő dokumentációt, és első feladataink megoldásával párhuzamosan tanulmányozzuk át annak szerkezetét, hogy a későbbiekben könnyen használhassuk. Töltsünk le, és (ha szükséges) telepítsünk két-három fejlesztői környezetet (pl. Eclipse, NetBeans). Az első feladataink megoldása során próbáljuk ki, és próbáljuk meg összehasonlítani ezeket, kiválasztva a számunkra legmegfelelőbbet a munkánk hatékonyabbá tételének szempontjából. 2. Amennyiben szükséges, próbáljuk meg felfrissíteni az objektumorientált programozással és az általunk ismert objektumorientált programozási nyelvekkel (pl. C++) kapcsolatos ismereteinket. 3. Írjunk programot, amely kiszámolja a parancssor argumentumainak összegét, csak az egész számokat véve figyelembe (kivételkezelést alkalmazzunk). Írjuk meg a programnak egy másik változatát is, amelyik minden numerikus argumentumot figyelembe vesz. Az első változatot egészítsük ki olyan módon, hogy a program külön számolja ki a páratlan, illetve páros argumentumok összegeit. 4. Írjunk programot, amely kiírja a konzolra a parancssor argumentumait, a kisbetűket nagybetűkbe, a nagybetűket kisbetűkbe alakítva. Útmutatás: egy String objektum esetében egy adott karaktert a charat(index) metódus segítségével kérdezhetünk le, az ellenőrzés és átalakítás a Character osztály statikus metódusainak segítségével történhet. 5. Hozzunk létre egy tömbökből álló tömböt, amelynek első sora 1, második sora 2, n- edik sora n elemet tartalmaz. Az elemek egész számok 1-től n*(n+1)/2-ig, ahol n, a sorok száma, a parancssor argumentuma. Amennyiben nem adunk meg argumentumot (vagy az nem egy numerikus érték), a sorok alapértelmezett száma legyen 10. Figyeljünk arra, hogy mindenik tömb esetében csak annyi elemnek foglaljunk helyet, amennyire valóban szükség van. A tömb elemeit írassuk ki a konzolra az alábbi példához hasonlóan: 1 2 3 4 5 6 II. labor Az alábbi osztálydiagram (2.10 ábra) alapján hozzuk létre a diagramban feltüntetett csomagokat, interfészt és osztályokat. 1
core Person #name: String #age: int +Person(String, int) +getname(): String +setname(string): void +getage(): int +setage(int): void Student -faculty: String +Student(String, int, String) +getfaculty(): String +setfaculty(string): void +tostring(): String TestStudentList * collection <<inner class>> StudentIteratorImpl -index: int StudentIterator +hasmoreelements(): boolean +nextelement(): Student +StudentIteratorImpl() +hasmoreelements(): boolean +nextelement(): Student StudentList -current: int -students: array of Student +StudentList(int size) +addstudent(student): void +getiterator(): StudentIterator +main(string[] args): static void Magyarázat: létrehozzuk a core és collection csomagokat. A core csomagon belül létrehozunk egy személy (Person) osztályt (POJO) a név (name) és kor (age) adattagokkal, az adattagok értékeit beállító paraméteres konstruktorral, valamint az adattagoknak megfelelő getter és setter metódusokkal. A Person osztályból származtatjuk a hallgató (Student) osztályt, kiegészítve a Kar (faculty) adattaggal, a megfelelő konstruktorral és getter/setter metódusokkal. A Student osztályon belül újradefiniáljuk az Object ősosztály tostring metódusát, visszatérítve a hallgatókkal kapcsolatos információk szöveges reprezentációját (például a név, kor és Kar tulajdonságoknak megfelelő stringek összefűzéséből előállított stringet). A collection csomagon belül létrehozzuk a StudentList osztályt, amelyből hallgató objektumokat tartalmazó gyűjtemények példányosíthatóak. Az osztályon belül egy Student típusú elemeket tartalmazó tömbben rögzítjük a hallgatókkal kapcsolatos információkat. A current adattag mindig a tömb aktuális elemére fog mutatni, így az új hallgató beillesztését végző addstudent metódus felhasználhatja ezt az értéket az új elem pozíciójának meghatározásához, és a beillesztés után elvégezheti az érték frissítését. A tömb méretét (a lista maximális kapacitását) a konstruktor paramétere határozza meg, az elemeknek a konstruktoron belül foglalunk helyet. 2
A lista bejárása egy iterátor segítségével történhet. Az iterátornak megfelelő osztály a StudentIterator interfésznek lesz a megvalósítása. Az interfész két metódust deklarál: a hasmoreelements metódus segítségével lekérdezhető, hogy van-e még elem a listában (vagy annak végéhez értünk), a nextelement metódus segítségével lekérdezhető a lista következő eleme. Ezt az interfészt a StudentIteratorImpl osztály valósítja meg, egy egész típusú attribútum segítségével rögzítve az aktuális pozíciót. Az osztályt a StudentList osztály belső osztályaként hozzuk létre. A StudentList osztály getiterator() metódusa példányosít a StudentIteratorImpl osztályból, és visszatéríti a létrehozott objektumra mutató referenciát (megjegyzés: a visszatérített érték típusa az interfész segítségével van meghatározva, így a metódust meghívó, a bejárást elvégző osztályokat nem befolyásolja, ha a későbbiekben lecseréljük az implementációt). A létrehozott osztályok kipróbálásához írjunk egy rövid programot. A TestStudentList osztály main metódusán belül hozzunk létre néhány Student objektumot. Hozzunk létre egy listát (StudentList példány), és adjuk hozzá ehhez a létrehozott hallgató objektumokat. Az iterátor segítségével egy cikluson belül járjuk be a listát, és írjuk ki a konzolra a hallgatókkal kapcsolatos információkat. III. labor 1. Hozzunk létre egy keretet (Frame), és ezen belül helyezzünk el egy panelt, valamint egy címkét (Label). Ha a felhasználó a panelre kattint az egérrel, a címkén jelenítsük meg az egérkattintás koordinátáit. A komponensek elhelyezésére használjunk egy megfelelő LayoutManager példányt, ne rögzítsük a pozíciókat és méreteket (ez a javaslat a legutolsó kivételével a következő feladatokra is érvényes). Egészítsük ki a programot, olyan módon, hogy ne csak az egérkattintást figyeljük, hanem az egérmutató mozgását is. A címkére az aktuális esemény típusát is írjuk ki a koordináták mellé: amennyiben a felhasználó kattintott a clicked üzenet, amennyiben csak elmozdította a pointert a moved üzenet, amennyiben lenyomott gombbal mozdította a pointert a dragged üzenet jelenjen meg. 2. Hozzunk létre egy keretet, és ezen belül helyezzünk el egy többsoros szöveg megjelenítésére alkalmas komponenst (TextArea), egy egysoros szöveg bevitelére alkalmas szövegmezőt (TextField), valamint egy gombot. Ha a felhasználó a gombra kattint, vagy a szövegmezőn belül lenyomja az enter billentyűt, a szövegmező tartalmát hozzáadjuk a TextArea tartalmához, majd töröljük a szövegmezőből (lehetőséget adva egy új szöveg beírására). 3. Egy kereten belül egy címke szövegét változtassuk jelölőnégyzetek (Checkbox) segítségével: a címkén mindig az aktuálisan kijelölt jelölőnégyzeteknek megfelelő címkék szövegét jelenítsük meg. Alakítsuk át a programot, olyan módon, hogy egyszerre csak egy jelölőnégyzet legyen kiválasztható (a jelölőnégyzet komponensek radio button komponensekbe történő alakítása, a CheckboxGroup osztály segítségével). 3
4. Egy kereten belül helyezzünk el több különböző színű panelt, a színeket véletlenszerűen generálva. Ha az egérmutató belépik egy adott panel fölé, az illető panel véletlenszerűen színt vált. 5. Egy kereten belül helyezzünk el egy gombot, véletlenszerűen generált koordinátákra, a Push me! felirattal. Amikor a felhasználó megpróbál a gombra kattintani (az egérmutató a gomb fölé kerül), a gomb elmozdul (véletlenszerűen újrageneráljuk a koordinátákat, és áthelyezzük a gombot az új koordinátákra). A feladatnak elkészíthetjük egy olyan változatát is, amikor tényleg nem lehetséges a gomb lenyomása: az új koordináták generálásánál kiszűrjük annak a lehetőségét, hogy a gomb újra a mutató alá kerüljön. Útmutatás: a koordináták véletlenszerű generálásához a java.util.random osztályt használhatjuk (figyelem: a generátorból egyetlen példány elégséges, ezután ettől több érték is elkérhető a megfelelő metódusok meghívásával, ezért ne hozzunk létre minden változtatáskor egy új Random példányt). A feladatot úgy oldhatjuk meg legegyszerűbben, ha ezúttal (kivételesen) nem használunk LayoutManager példányt (a setlayout metódus null paramétert is elfogad), hanem meghatározzuk a gomb méretét és pozícióját (ez utóbbit változtatva a megfelelő esemény felléptekor). IV. labor Egy kereten belül helyezzünk el egy rajzvásznat (egy saját osztályt hozunk létre a Canvas osztályból származtatva), két Choice komponenst, egy jelölőnégyzetet (Checkbox), és egy gombot. A felhasználó a két Choice komponens segítségével kiválaszthat egy adott alakzattípust (pl. kör, négyzet, stb.), és egy adott színt (pl. kék, piros, stb.). A gomb lenyomásának hatására a vászonra kirajzoljuk a kiválasztott alakzatot a kiválasztott színnel. Amennyiben a jelölőnégyzet be van jelölve, az alakzat felületét is kitöltjük az illető színnel. A keretnek megfelelő osztályt (a Frame leszármazottja), és a rajzvászonnak megfelelő osztályt (a Canvas leszármazottja) külön osztályként, külön állományokban hozzuk létre (a vásznat ne belső osztályként valósítsuk meg). Figyeljünk arra, hogy a vászon ne függjön a kereten belül alkalmazott komponensektől (pl. ne befolyásolja a vászon osztályt, ha valamelyik Choice komponenst listára cseréljük, stb.) A programnak elkészíthetjük egy olyan változatát is, amelynek esetében nem szükséges a gomb lenyomása: bármelyik másik komponens állapotának változásakor frissítjük a rajzot. Ezen kívül a szín kiválasztására alkalmas Choice komponenst helyettesíthetjük olyan módon, hogy a felhasználó tetszőleges R, G, B értékeket meg tudjon határozni (pl. három szövegmező segítségével). V. labor Készítsünk egy appletet, a megfelelő panelen belül elhelyezve egy rajzvásznat, egy Choice komponenst, egy szövegmezőt és egy gombot. A rajzvászonra az egér 4
segítségével rajzolhatunk: ha lenyomott gombbal mozdítjuk el az egérmutatót (mouse dragged), az nyomot hagy maga után (az előző koordinátákat összekötjük az új koordinátákkal). A rajzolást olyan módon valósítsuk meg, hogy a vászon felülete ne törlődjön, még a rendszer által kezdeményezett frissítés esetében sem (Image példány használata). Ezen kívül próbáljunk meg arra is figyelni, hogy a vászon átméretezésével a rajz ne torzuljon. A Choice komponensnek megfelelő listából különböző parancsokat választhatunk ki: vászon törlése, kép megjelenítése, weboldal megnyitása, hanganyag lejátszása. Bizonyos műveletek esetében paramétert is meg kell határoznunk (pl. kép- /hangállomány neve és elérési útvonala, weboldal címe), ezt a szövegmező segítségével tehetjük meg. A gomb lenyomásának hatására végrehajtásra kerül a kiválasztott utasítás: töröljük a vásznat, vagy megjelenítjük rajta a megadott képet, lejátsszuk a megadott hanganyagot, vagy egy új böngészőablakban megnyitjuk a megadott weboldalt. VI. labor A IV. laborfeladat (alakzat kirajzolása) megoldása során elkészített program grafikus felületét írjuk át SWING komponensek felhasználásával. A programot egészítsük ki néhány új funkcionalitással. Egy JSlider segítségével legyen változtatható az alakzat mérete, olyan módon, hogy az meg is haladhassa a vászon (esetünkben JPanel komponens) aktuális méretét. Amennyiben az alakzat kilóg a vászonból, jelenjenek meg görgetősávok, amelyek segítségével változtathatjuk az éppen látható felületet (JScrollPane komponenst alkalmazhatunk). A szín kiválasztására ezúttal egy külön grafikus felületet is biztosítsunk, a JColorChooser komponens felhasználásával. VII. labor Készítsünk egy egyszerű autóverseny szimulátort. Egy SWING eszköztár segítségével megvalósított grafikus felületen belül rajzoljunk ki egy versenypályát, és azon helyezzünk el néhány autót (az autókat egyszerű téglalapok segítségével is ábrázolhatjuk, de kis állományból beolvasott képeket is felhasználhatunk). Arra is lehetőséget adhatunk, hogy a felhasználó meghatározhassa az autók számát (pl. egy szövegmező segítségével). A verseny egy gomb lenyomására indul. Mindenik autót egy külön végrehajtási szál irányítja, véletlenszerű időközönként változtatva azok pozícióját (a változtatás mértéke is lehet véletlenszerű). A verseny addig tart, ameddig az első autó beér a célvonalba. Készítsünk egy olyan változatot is, amelynek esetében minden autó beér a célba, majd egy párbeszédablak jelenik meg a beérkezés sorrendjével. VIII. labor A VI. laborfeladatot (alakzatok kirajzolása SWING felületen) egészítsük ki mentési és betöltési lehetőséggel. A megfelelő menük segítségével a felhasználó kérheti egy adott 5
konfiguráció (alakzat típusa, színe, mérete) elmentését, illetve betöltését. A cél- és forrásállományok kiválasztásában JFileChooser komponensek szolgáltatnak segítséget. A betöltés esetében az alakzat megjelenítésén kívül a komponensek állapotát is változtassuk. IX. labor A fejlesztési folyamat alapszakaszain belüli lépések betartásával készítsünk egy egyszerű Java projektet. Lehet ez egy kis asztali alkalmazás, vagy egy egyszerű játékprogram, tetszőlegesen választhatunk. Útmutatásként néhány ötlet: - egyszerű, állománykezelésen alapuló nyilvántartó program adataink kezelésére (pl. könyvek, zenék, filmek stb.), vagy más számunkra hasznos asztali alkalmazás (pl. határidőnapló, stb.) - egyszerű rajzolóprogram, vagy valamilyen grafikus szerkesztő (pl. kottaszerkesztő és zenelejátszó) - egyszerű játékprogram, például kígyó (snake), pasziánsz (solitaire), aknakereső (minesweeper), shokoban, mastermind, memória (kártyával, képpel, vagy zenével), vagy bármelyik klasszikus játék valamilyen (lehetőleg minél egyénibb) változata. Ötletekkel szolgálhatnak a különböző egyszerű mobiltelefonra írt, vagy Flash játékok. 6