2012. január 29.

Adat vizualizáció processing-gel

A Számítógépes Nyelvészeten korábban már szóba került a processing programozási környezet, amelyet azért terveztek, hogy egyszerűen és hatékonyan lehessen vizuális alkalmazásokat készíteni: egy java-ra épülő (pontosabban, a java alá épülő) nyelvről van szó, amely a számos grafikus megjelenítéssel kacsolatos feladatot megkönnyít a beépített funciók segítségével.


Mint már akkor Zoli elmondta, nem egy játékról van szó, hanem egy igen hatékony eszközről; ugyanezt Ben Fry (a nyelv egyik atyja), Visualizing Data c. könyvében úgy fogalmazza meg, hogy kész eszközök helyett a processing építőkockákat ad -- egyedi problémákhoz ugyanis szinte lehetetlen előre legyártott szabványos megoldásokat kitalálni.

A processing építőkockái valójában nem mások, mint a beépített funkciók -- valójában mindent a Java programnyelv végez, így nem is meglepő, hogy a szintaxis megegyező; és az sem, hogy bármikor "kinyúlhatunk" a processing nyelvből a Java funkcióihoz.

Mit szeretnénk tehát? A processing két dologban jó: a vizualizációban és az interaktivitásban; tehát -- hogy újra feltaláljuk a spanyolviaszt -- készítünk egy primitív tag-felhőt. A megoldás annyiban nem lesz szabványos, hogy kezdetben minden tag-et azonos méretben fogunk megjeleníteni; csak utóbb, a az egér mozgatásával dönti el a felhasználó, hogy mennyire szeretné "kiugrasztani" a gyakran előforduló elemeket. Tehát, lesz egy "áttekintő nézetünk" és egy "közelítő nézetünk".



 Áttekintő nézet -- minden szó egyforma méretű

  
A gyakori szavakat kiemeltük


OK. A legegyszerűbb processing program két funkcióból áll: a setup() és a draw(). A setup() induláskor fut le egyszer, mint neve is mutatja, itt érdemes elhelyezni minden kezdetben szükséges lépést. Pl., mi itt állítjuk be a rajzfelület méretét (800x600), itt töltjük be a betűtípust és itt olvassuk be az adat.txt-ből a szavakat, amelyeket majd később ki szeretnénk írni a képernyőre.

Ezután a draw() funkció fut le. Ez, mint neve is mutatja, alapvetően a megjelenítésért felel, de természetesen bármi mást is elhelyezhetünk itt. Kiemelt szerepe abban áll, hogy folyamatosan ismétlődik, vagyis miután a program mindent kirajzolt, azonnal újra kezdi. Hogy mire jó ez? Ha úgy képzeljük el a dolgok, mint az egymást követő filmkockákat, egyből értelmet nyer a dolog: ha a két kocka közt nincs eltérés, akkor nem veszünk észre semmit. Azonban ha van, akkor mozgásba lendül a kép. Pl., ha egy kirajzolt pont koordinátáit minden egyes funkció-híváskor megnöveljük egyel (x++;), akkor egy mozgó pont lesz az eredmény. A processing környezet tehát azt a könnyedséget adja, hogy nem kell magunknak megírnunk a "filmkockák kirajzolásáért" felelős részt, elég csak a képekkel foglalkoznunk.

Ezen a ponton érdemes megjegyezni, hogy a processing komolyan veszi a globális és lokális változók kérdését. Pl. a draw() funkción belül deklarált változók minden egyes újrahíváskor elvesznek, így ha pl. a mozgó képpont x koordinátáját az x változóban tárolnánk, azt mindenképpen globálisan (vagyis a funkción kívül) kell először deklarálnunk. A programunkban pl. ilyen az adat[], meret_szamlalo vagy a lastMX.

Az interaktivitás beépítését a processing azzal támogatja, hogy nagyon egyszerűvé teszi teszi a különböző események figyelését. Pl. minden alkalommal, amikor kattintunk, a mousePressed() funkció kerül meghívásra, majd visszatér a program oda, ahol abbahagyta a futást. Ugyanez a történik a mouseMoved() funkció esetén is. Az egérkurzor koordinátáit a mouseX ill. a mouseY változókból tudhatjuk meg.

Lássuk tehát, mi történik az interaktív szövegfelhőnk kódjában. Először deklarálunk néhány globális változót (mivel azt szeretnénk, hogy minden funkció elérje ezeket). Ezután elindul a setup(), ami betölti az adat.txt tartalmát (itt a szavak és a hozzájuk tartozó értékek találhatók).

Végül elindul a draw(), amely folyamatosan ismétlődik a program leálltáig. Először kirajzoljuk az "irányító felületet" -- ez az a része a képernyőnek, amelyen ha megmozdítjuk az egeret, akkor változik a szavak mérete. Majd kiszámoljuk (egy gyökvonással), hogy hány sorba és hány oszlopba rendezzük az adatainkat. Ezután elindítunk egy ciklust, amely szép sorban kiírja megfelelő helyekre az adat[] tömbben tárolt szavakat. Ha a szó maximális mérete nagyobb, mint az aktuálisan beállított szövegméret, akkor az utóbbit használjuk. Ha az aktuális szövegméret nagyobb, akkor a szó maximális méretét használjuk.

Az utolsó két funkció az egér mozgatását és az egérkattintást figyeli. Ha megmozdítjuk az egeret ÉS a kurzor a "kezelőfelület" felett áll, akkor növeljük vagy csökkentjük a szöveg méretét (attól függően, hogy jobbra vagy balra húztuk az egeret). Ha kattintunk, akkor egy új szöveg-elrendezést kérünk -- ezt egyszerűen úgy érjük el, hogy megkeverjük az adat[] tömböt.




Végül néhány megjegyzés:

1. A virtuális gép és a grafikus felület sajnos lelassítja a program futását. Nagyon. Ezért az egymásba ágyazott ciklusokkal, nagy tömbökkel és minden hasonlóval csak nagyon óvatosan szabad bánni. Szerencsére a bonyolultabb grafikus műveletekhez vannak beépített funkciók.

2. A Java típusai sokkal finnyásabbak, mint mondjuk a python-éi. A float nem változik automatikusan integerré, a string-et nem lehet csak úgy pikk-pakk karakterekké szedni, stb... A tömbök sem túl rugalmasak: deklaráláskor el kell döntenünk, milyen hosszúak legyenek, tehát nem tudjuk őket a végtelenségig bővíteni. Többdimenziós tömbök léteznek, de egy tömbnek csak egy eleme már nem lehet egy újabb tömb. Dictionary/hash típus nincsen.

4. A programok könnyen konvertálhatók java appletté, illetve az processing.js javascript könyvtár segítségével közvetlenül böngészőből is futtathatók.

3. Az oktató anyagok és a dokumentáció jók; sok kiegészítő könyvtár is készült már.


Folyt. köv.

1 megjegyzés:

Gerő Dávid írta...

Tetszik a példa program ötlete! Hasznos és inspiratív! - Újra megjött a kedvem a processinghez ;)