2012. december 17., hétfő

5K

Kevesebb, mint egy év alatt a blogom elérte az 5000 megtekintést. Azt hiszem ezt mindenképpen sikerként könyvelhetem el. Az utóbbi időben picit kifogytam az ötletekből, illetve elfoglalt voltam, s vagyok is még, de jövőre (ha nem lesz világvége :D) igyekszem újabb hasznosságokkal gazdagítani a blogot. Stay tuned! :-)


2012. december 1., szombat

HTML parszolás

Munkám során találkoztam egy Nokogiri nevezetű Ruby library-vel, amivel nagyon szépen lehet HTML-t feldolgozni. Ami nekem a legjobban tetszett benne, hogy CSS szelektorokkal is ki lehet választani elemeket.

Az egyetemen közben még tanultam a CSS-ről bővebben, és ámultam picit: nem is tudtam, hogy mennyiféle módon lehet elemekre szűkíteni ezekkel a szelektorokkal. A szakdolimat - amiben többek között van HTML parszolás is - már régóta tervezem, hogy hobbiból továbbfejlesztem, sőt újraírom, és ezen új infók új ötleteket is adtak.

A múltkor már kerestem a Nokogiri-hez hasonló Java library-t, de nem találtam. Ma viszont sikerrel jártam, és a következő csomagot találtam, amit néhány kódsornyi kipróbálás után bátran ajánlok mindenkinek: Jsoup. A Cookbook szekcióban rengeteg beszédes példa van, mi mindenre képes, szerintem nagyon hasznos! :-)

2012. október 24., szerda

Red

Október 22.-én jelent meg Taylor Swift legújabb albuma, mely a Red címet viseli. Az alap korongon 16 új dal kapott helyet, köztük a már korábban napvilágot látott We Are Never Ever Getting Back Together, az album deluxe változatán pedig 6 bonus track csücsül: 3 újabb dal, illetve 3, az albumon hallható dal demó verziója.

Egymást váltják a pörgősebb és lágyabb, vidámabb és lírikusabb dalok, egyik sem okoz csalódást. A megszokott Taylor Swift stílust kapjuk ismét, néhol a kortársaknak megfelelő újításokkal, melyeket nem vittek túlzásba a stúdióban, letisztultak és tökéletesen belesimulnak a dalokba. A pörgősebb dalok között engem némelyik emlékeztetett a Sid zenekar stílusára.

A kedvenc dalom azt hiszem egyértelműen az I Knew You Were Trouble lett, mely szintén előbb a publikum elé került, mint a teljes album. Ez a gyorsabb számok közé sorolható, de változatos, és fantasztikus a hanghatás a refrénben. Kétszer is meghallgattam. :)

Kihagyhatatlan darab, mint Taylor összes korongja! :)

2012. október 19., péntek

Cloud nine

A minap belefutottam egy Katy Perry dal cover-jébe. Hannah Trigwell adta elő csodálatos hangján a Wide Awake c. dalt, nagyon szép lett. Ahogy hallottam a refrént, felfigyeltem egy szövegrészletre: "falling from cloud nine". Ez a "cloud nine" ismerős... az Evanescence egyik albumán is van egy ilyen című dal... és arra gondoltam, hogy utánanézek, ez biztos valami kifejezés.

És igen, olyannyira kifejezés, hogy ez egy szólás, és wiki oldala is van, rengeteg előadót megihletett. "A Cloud 9 (azaz "kilences felhő") egy főleg Amerikában használatos kifejezés a lelkesedésre, és az euforikus, boldog állapotra."

Szóval mindig van mit tanulni. :) És egyébként tök érdekes, pl. miért pont 9? :)

2012. október 18., csütörtök

Java ME és az SMS

Mobil alkalmazások fejlesztése órára ki kellett ötölnöm egy projekt tervet. Mivel nincs okostelefonom, platformnak a Java ME-t választottam, noha érdekelne az Android, csak tesztkészülék nélkül értelmetlen lenne alkalmazást fejleszteni. Symbian-t is választhattam volna, de sok értelmét nem látom, hogy megtanuljam, mert hanyatlik. Emellett időm sincs most sok, így valami egyszerűbb programot gondoltam megírni a félév során.

Ki is agyaltam egy egyszerű, de hasznos alkalmazás ötletet. Nem írom le, ez a bejegyzés most nem erről szól. A lényeg, hogy SMS-ekkel való operálás és SMS küldés van benne. A tanár még kiegészítette az ötletet, amihez kéne SMS olvasás is.

Az első akadály, amit olvastam, hogy egy Java ME-s alkalmazás nem tudja fogadni a telefonra érkező SMS-eket, nem tudja interceptálni a folyamatot. Csak olyan SMS-t tud fogadni, amit kifejezetten neki, az ő portjára küldtek.

Mondjuk ez még nem lenne baj, ez még megkerülhető lenne azzal, ha az app hozzáfér az inboxhoz. De itt a második bökkenő, nem tud hozzáférni. Symbian-nal viszont megoldható... és gondoltam, hogy feladom az elveket és megpróbálom abban, de a Nokia oldala jelenleg nem akarja az igazságot...

Így hát marad az eredeti ötlet, ami csak küld. Ezt ki is próbáltam, működik... bár itt is van némi hiányosság. Az SMS-t ugyan szépen elküldi, fogadó oldalon minden rendben van, viszont a küldő készülékben nem kerül be a kimenő mappába.

Az SMS-t küldő kód fél perc guglizással is megtalálható:
String message = "Üzenet";
String address = "0036...";
String url = "sms://" + address + ":0";
MessageConnection messageconnection = null;
try {
    messageconnection = (MessageConnection) Connector.open(url);
    TextMessage textmessage = (TextMessage) messageconnection.newMessage(MessageConnection.TEXT_MESSAGE);
    textmessage.setAddress(url);
    textmessage.setPayloadText(message);
    messageconnection.send(textmessage);
    switchDisplayable(null, editor);
} catch (IOException ex) {
    System.out.println(ex.getMessage());
    Alert a = new Alert(ex.getMessage());
    switchDisplayable(a, editor);
} finally {
    try {
        if (messageconnection != null) {
            messageconnection.close();
        }
    } catch (IOException ex) {
    }
}

2012. szeptember 16., vasárnap

Ruby on Rails izzadás II.

A hiba, amibe korábban beleütköztem felvetett újabb problémákat, amik miatt muszáj volt magam beleásni a problémába. Időközben rájöttem, hogy a rake fájlt a --trace paraméterrel is lehet ám futtatni, így megkapom, hol is szállt el pontosan a végrehajtás.

Az új probléma a következő: a new-val való létrehozás nem pakol az adatbázisba, így amikor később volt egy hivatkozás ennek az objektumnak az id mezőjére (ami a kódból nem kap értéket, a tároláskor töltötte volna ki a rails/hobo), nil értékkel dolgozott tovább a program, így el is vesztette a funkcionalitását. Konklúzió: a new nem tárol az adatbázisba, csak simán létrehozza az objektumot - ahogy egyébként gondolhattam is volna, csak elöntött az átírás után eltűnő hibaüzenetek okozta örömmámor, így nem is néztem tovább azt a programrészt.

És most nézem, félreolvastam a múltkor azt a doksit. Nem a create és a new ekvivalenciáját írta, hanem a new különféle szintaxisait mutatta be.

2012. augusztus 30., csütörtök

Ennyi csak - kottamorzsa

(Újraírtam a bejegyzést, mert sikerült az intro is :-))

Folytatom missziómat, hogy hallás után építsem fel a kottát, amit nem találok. Ma és tegnap sikerült az Ennyi csak c. szám néhány hiányzó részletét lekottázni! :D

2012. augusztus 25., szombat

Ki van ez találva - kottamorzsa

Akik ismernek, tudják, hogy hobbi szinten gitározom is, illetve a korábbi blogomra tettem fel 1-1 kisebb kotta részletet (most csodálkozom is picit, hogy ide nem emeltem át, majd lehet pótolom), amit én találtam ki hallás után, vagy egy meglévőt formáltam át, egyszerűsítettem.

Mostanság a Kowalsky meg a Vega zenéjével örvendeztetem füleim. Egyik kedvenc számom tőlük a Ki van ez találva. Sajnos Kowa kottákból elég gyér a választék a neten, ehhez a dalhoz is csak akkordbontást találtam. Viszont a nyitó dallamot is jó lenne játszani, mert hozzá tartozik a dalhoz.

Ezt sikerült most gitárral a kézben félig improvizálva, félig hallás után egyeztetve összeraknom. Nagy öröm, amikor az ember (aki amatőr) maga kottáz le egy kis dalrészletet, szólót, és az eredetivel együtt játszva egybecsengenek a hangok! :)

2012. augusztus 21., kedd

Ruby on Rails izzadás

Hozzámvágtak egy szép nagy Ruby on Rails alkalmazást, több mint 4 tucat entity class-szal, pár rake fájllal, meg ez valami webapp, tehát mindenféle cucc van még itt. Szerencsére nekem csak a rake-ekkel kell foglalkozni, melyek kisebb-nagyobb crawler-eket rejtenek, taszkokba csomagolva.

Ruby-vel (vagy -val?! :D) az egyetemen Script nyelvek órán foglalkoztunk pár előadást, a végén. A Ruby on Rails összetétel jó, ha egyáltalán elhangzott. Nem mélyültünk el a nyelvben, de az alapokat azért átvettük anno, most nézem, még osztályokat is tanultunk definiálni. Ezekből én semmire nem emlékeztem, szóval a rake fájlok olvasgatásával építettem újra a nyelvet a fejemben. :D

Történik egyszer, hogy miután kiegészítettem egy rake fájlt, futtattam, és az első két hibát elhárítottam, ismét megakadt. Valami olyasmit írt, hogy váratlanul nil-t kaptam valahol, ahol nem kéne, és valami nil.update_attribute válthatta ki. Persze a rake fájlban az update szó sem szerepelt.

2012. augusztus 13., hétfő

SyntaxHighlighter sorszám fix

Ma érzékeltem, hogy a SyntaxHighlighter blokkokban a sorok számozása enyhén szólva szét van esve. Minden egyes karakter után sort tör, a 9-nél nagyobb számok így több sorban jelennek meg, így elég furcsa sormintát kapunk: ...,7,8,9,1,0,1,1,1,2,...

Szerencsére ezt egyetlen CSS sor hozzáadásával megbütykölhetjük. Itt Bloggerben a Sablontervezőben, az egyéni stíluslapnál az alábbi sort kell beírni:
div .line { word-wrap: normal; }
Ez szépen meg is oldja, amit kell. :-)

2012. augusztus 5., vasárnap

Memory leak

Hát megijedtem, amikor végre úgy tűnt, hogy funkcionálisan hibátlan a program, erre váratlanul bekopogtat egy "OutOfMemoryException: Java heap space" stack trace. Guglizás, mit lehet ezzel kezdeni, mert az első próbálkozásom, ami egyébként tényleg optimalizáló lépés volt, nem kerülte el az újabb OOM-t.

Első tippnek az -Xmx1024m JVM paramétert találtam, ám sem ez, sem 2048-as értékkel turbózott változata nem hozott javulást.

2012. augusztus 3., péntek

JPA és az idő - tanulság

A múltkor rájöttem, hogyan tudom több szálból használni biztonságosan a JPA-t. Azonban akadt egy újabb gond, ami a kicsi teszteknél (1-200 rekord) nem jött elő. Nevezetesen az, hogy az adatbázis duzzadásával lassul a beszúrás. A következőket mértem:
1. 500 rekord beszúrása - 20 sec
2. 500 rekord beszúrása - 32 sec
3. 500 rekord beszúrása - 42 sec
4. 500 rekord beszúrása - 51 sec
Vagyis rekordonként ~20 milliszekundumot lassul. Ez azért egy több tízezer/százezer rekordot kitermelő crawler esetében elég jelentősen megdobja a futásidőt. Elfogadhatatlan.

2012. július 17., kedd

Google Drive és a sync

Remek ez a Google Drive, egyszerű a kezelőfelület, lehet mappát színezni, egész mappát megosztani, tök jól rendezgetni, meg minden. Viszont ha frissítek egy fájlt, az egészet újra feltölti, ahelyett, hogy csak a változást küldené el a szervernek. És ennek kapcsán több, komolyabb probléma is adódik: http://forums.dropbox.com/topic.php?id=59268.

A Dropbox-szal nincsenek ilyen gondok.

Hiába terveztem el tegnap, hogy mostantól áttérek a GD-re, és hiába alakítottam ki a mappáimat, szép szivárvány színesre mázolva - ez a dolog visszaterelt a Dropbox-hoz.

Reméljük azért megoldják majd ezeket a dolgokat a Google fejlesztői, akkor majd érdemes lesz áttérni.

2012. július 13., péntek

Bash prompt

Mivel az elmúlt napokban 2 alkalommal is szükségem volt rá, úgy gondoltam, valami központi helyre elmentem a saját bash prompt kusztomizációmat. És arra gondoltam, miért ne tegyem ki ide, hátha másnak is megtetszik.

Így néz ki:

Kód:
export PS1="\n\e[1;30m________________________________________________________________________________\n\e[1;34m\u@\h \e[1;30m| \e[0;35m\t \e[1;30m| \e[0;36m\w \e[1;30m\n > "

A vonal segít elkülöníteni a parancsok kimeneteit egymástól, az időt pedig azért tettem bele, mert olykor hasznos, ha tudom, mennyi ideig futott egy parancs.

2012. július 8., vasárnap

JPA több szálon

No, 2 napig izzadtam a JPA-val, mire működésre bírtam, de tanulságos volt.

Szituáció: van 2 táblám, közöttük 2 db N-M kapcsolat (az egyik önmagával). A multithreaded crawler-em pakolja bele a rekordokat, amit a JPA "Duplicate entry" hibaüzenettel jutalmaz. Pedig igyekeztem szinkronizáltan hívogatni a persist-et, meg a find-ot. De nem eléggé, mert entity osztályonként volt csak szinkronizált. Ha rákeresünk a gugliban, azt találjuk, hogy az EntityManager-t egy szálból illik használni.

Viszont nekem több szálam van, és szükségem lenne a tárolásra és lekérdezésre futás közben.

2012. július 4., szerda

throws CutenessOverloadException

A programozó is ember. És nem lehet mindig csak Java-s bejegyzést kirakni. :D Mostanság amúgy sem volt mit írnom. Bejött egy meló (végre :-) ), ami lefoglal, meg igazán bejegyzés ötletem sincs.

Szóval:

2012. június 23., szombat

Google App Engine - Tapasztalatok

Ma rászántam magam végre, és feltöltöttem az első alkalmazásom eddig elkészült részét a Google App Engine-be. Persze az azonosító, amit kigondoltam foglalt volt, úgyhogy egyelőre megmaradok a juzraai-nál. :D Előtte azért átnéztem a súgót, mert egy felhasználó max. 10 alkalmazást üzemeltethet: ha egy alkalmazást törlök, akkor visszakapom azt az 1 lehetőséget, szóval ezzel nincs gáz, lehet próbálkozni.

No, hát a feltöltés tök egyszerű, az appcfg update <a-projekt-web-mappája> parancssal. Utána a webes felületen egyszerűen ki lehet igazodni, listázza a verziókat, sőt, verziónként az egyes példányokat is, melyek lefutottak, és hiba esetén megtekinthető a log.

És erre szükség is volt...

My Last Breath

My Last Breath (Demo)

Szintén az egyik kedvencem Amy Lee-éktől, rengeteg érzelem van benne.

2012. június 21., csütörtök

Pár érdekesség

Most vettem észre, hogy tegnap kijött a Google Data API v3 (legalábbis Bloggerhez és Calendarhoz; YouTube-hoz még nem). Elvileg REST technológiát alkalmaz és az eredményt JSON formátumban küldi. A Java kliens lib még bétaverziónál tart.

Illetve haladok a webappommal, remélem majd sikerül felvarázsolnom GAE-be, local gépen működik. JSF 2.0-hoz ajánlanék egy oldalt, nagyon jó tutorialokat találtam itt: mkyong.com.

2012. június 18., hétfő

Google App Engine SDK + Java

Ma letöltöttem az SDK-t, és kipróbáltam az appszervert. Létrehoztam egy JSF-es webalkalmazást, és ráengedtem.

Persze egy rakat kivételt dobott, picit keresgélni kellett, milyen XML-ekre van szüksége (app-engine.xml), de a legtöbb időt arra vesztegettem, hogy a ClassNotFoundException: javax.faces.webapp.FacesServlet kivétel és a GAE kapcsolatára gugliztam.

A JSF implementáció nem része a GAE-nek, ezért pótolni kell manuálisan. Kipróbáltam a Glassfish könyvtárában levőt, de gondja van vele, újabb (de legalább más) kivételekkel örvendeztet meg. Találtam egy cikket, ahol valaki leírja, mi a hiba, és megoldotta, meghekkelve a jsf-impl lib-et. Ezt a jsf-impl-gae.jar-t és a jsf-api.jar-t (ez utóbbit pl. a GlassFish mappájából) kell hozzáadni a projekthez, és már JSF-et is használhatunk.

Közben pedig támadt már egy webapp ötletem, kíváncsi leszek, futtatható-e GAE-vel. :-)

2012. június 17., vasárnap

Google App Engine

Keresgéltem ingyenes app szervereket, nem sokat találtam. Aztán beugrott, hogy mintha a guglinak lenne, és van: Google App Engine. Beleolvastam a hivatalos leírásba, illetve találtam egy blogot, ahol valaki már használja is, és publikálja tapasztalatait.

Amit nagy vonalakban tud (leírás alapján):
  • fejenként 10 appot lehet feltölteni, mindegyik kap egy *.appspot.com címet (sőt, subdomain-ek is lehetnek még)
  • 1GB-os tárhely, havi 5 millió db oldalletöltés, 60 sec request feldolgozási időkorlát
  • van egy SDK, amivel a local gépen szimulálni lehet az App Engine környezetét, és van uploader tool
  • feltöltéskor új verzió keletkezik, amit ki lehet próbálni, és lehet választani, mely verzió legyen élő a nagyérdeműnek
  • viszont elvileg a fájlrendszer read-only, meg socket-eket sem lehet használni (<- ezek azért ijesztő dolgok :D)

Ki fogom próbálni. :-)

Update @ 2012.06.18: első tapasztalatok az SDK-val

Glassfish érdekesség

Érdekes dolgot tapasztalok az Üveghal szerverrel. Ha NetBeans-ből futtatom a szervert, és leállítom, már nem tudja később újraindítani. Amikor megnézem NB-ben a domain-eket, a kiválasztott domain-re azt írja, hogy "admin-listener disabled or no enabled http-listener". Kérdés, vajon miért állítódik el?

Az első megoldás az volt, hogy létrehoztam egy új domaint. Most kikísérleteztem annyit, hogy csak a domain config mappáját kell lecserélni az első futtatás előttire (esetleg egy manuális indítás utáni verzióra), és akkor ismét tudom indítani NB-ből. De hát ez így nem állapot.

A NB egyébként annyiból is bugos, hogy a JavaDB network servert nem állítja le kilépéskor, manuálisan kell megtenni a javadb/bin/stopNetworkServer.bat-tal.

(NetBeans 7.1beta, Glassfish 3.1.1, a NB töltötte le)

Update @ 12:22: Rájöttem! :D

Egész egyszerűen nem szereti az ékezetes betűket a domain.xml-ben. Merthogy a projektem elérési útvonalában volt 1-2 ékezet, és ez az elérési út bekerül ebbe a fájlba, és a szerver indításakor ParseError-t produkál. (Amit az üveghal manuális indításakor kiírt exception sorozatból olvastam ki, a NB erről véletlenül sem tájékoztat.)
Tanulság: felejtsük el az ékezetes mappaneveket! :D

2012. június 16., szombat

And the journey begins

Ma jutottam el odáig, hogy telepítettem a GlassFish szervert, létrehoztam az első EE-s projektemet, és beírtam a gugliba: "java ee tutorial". :D

Találtam egy "nagyongyorstalpalót", ami arra jó volt, hogy legalább valami fogalmam van róla, kb. miről szól az EE, meg 1-2 fogalmat is definiált (még ha talán "pongyolán" is).

Persze az első találat a hivatalos Oracle tutorial volt, amit már ismertem is korábbról, csak valahogy nekem nagyon töménynek tűnt anno.

Aztán találtam egy könyvajánlót: Beginning Java EE 6 Platform with GlassFish 3: From Novice to Professional (Antonio Goncalves tollából). Ahogy belelapoztam, egész korrekten elmagyarázza, a JPA-t is, szerintem ezt fogom forgatni.

u.i.: jó érzés volt, amikor olvastam a "nagyongyorstalpalót", hogy új dolgokat tanultam :-)

2012. június 14., csütörtök

YouTube API + Java

Neki is ültem, és kipróbáltam a YouTube API-hoz készült Java kliens library-t.

A bevezető doksiban leírtak eléggé pongyolák, mert nem csak a gdata-client-xx és a gdata-youtube-xx JAR fájlok kellenek a futáshoz, hanem még jó pár. Illetve még le kell tölteni hozzá a Java Mail API-t is.

A következő library-k kellenek a projekthez (ami egy videó feed/entry adatait kérdezi le):
  • gdata-client-1.0.jar
  • gdata-core-1.0.jar
  • gdata-media-1.0.jar
  • gdata-youtube-2.0.jar
  • guava-11.0.2.jar
  • mailapi.jar

Az alábbit próbáltam ki, és működik, egész pofás. :-)
YouTubeService yts = new YouTubeService("My first YouTube API app :-)");

String url = "https://gdata.youtube.com/feeds/api/users/juzraai/uploads?v=2";
VideoFeed vf = yts.getFeed(new URL(url), VideoFeed.class);

for (VideoEntry ve : vf.getEntries()) {
    printVideoEntry(ve, true); // ld. doksi
}

Amit a doksiból bemásolt metódus nem ír ki, az a yt:rating elem adatai, amiben a like és dislike számlálók vannak. Ezt a VideoEntry-ből a getYtRating()-gel kérdezhetjük le.
String url = "https://gdata.youtube.com/feeds/api/videos/XPBwXKgDTdE?v=2";
VideoEntry ve = yts.getEntry(new URL(url), VideoEntry.class);

System.out.println(ve.getTitle().getPlainText());
System.out.println(ve.getHtmlLink().getHref());

if (ve.getYtRating() != null) {
    System.out.println("Likes:    " + ve.getYtRating().getNumLikes());
    System.out.println("Dislikes: " + ve.getYtRating().getNumDislikes());
}

YouTube Data API

Ezerrel agyalok ötleteken, milyen progit írjak, ami hasznos is és érdekes is. Ma feltöltöttem egy YouTube videót, és bevillant valami: írhatnék egy progit, ami megnézi nekem, hányszor nézték meg, hogy értékelték, etc. Persze, ezt megnézhetném én is, böngészőből, de így elsőre érdekesnek tűnik. :D

A Google (szerintem) minden termékéhez van egy API, melyek tulajdonsága, hogy HTTP protokollon keresztül lehet adatokat lekérdezni (és frissíteni!), az adatokat pedig XML formátumban kapjuk.

A YouTube-hoz is van ilyen, és böngészőből nézve is egész kényelmesen lehet használni infószerzésre. Az alábbi sémájú URL-ekről lehet adatokat elérni:

https://gdata.youtube.com/feeds/api/videos/<videó azonosítója>?v=2
https://gdata.youtube.com/feeds/api/users/<felhasználónév>?v=2
https://gdata.youtube.com/feeds/api/users/<felhasználónév>/uploads?v=2
stb.

Le lehet kérdezni, hogy az egyes videókat hányszor nézték meg, hány like/dislike érkezett rá, hányan rakták kedvencekbe; le lehet kérdezni egy felhasználó kedvenc videóit, saját feltöltéseit, stb. 

A linkek végére a v=2 paraméter azért kell, mert azzal kaphatjuk meg a legfrissebb, YouTube API 2.0 által szolgáltatott adatokat. Például, ha nem tesszük oda, akkor még a régi, 5 fokozatú értékelés adatait kapjuk csak meg egy videóhoz.

Persze nem muszáj XML-ekkel bajlódni, létezik Java-hoz (meg más nyelvekhez is) library. :-)

Ki is próbáltam...

Ki van ez találva

Tegnap rögzítettem az alábbi covert. Instant metál verzió Kowalsky meg a Vega Ki van ez találva c. számából. Nem hibamentes, de sebaj, a lényeg, hogy ott sikere[m] volt, ahol szerettem volna. :-)


Technikai adatok: Vorson EDG-46 LH gitár, Powerstate PG-10G erősítő, Beta Aivin HM-100 effekt (igen, low-budget infrastruktúra, de a hobbi szinthez megteszi :D). Az ASUS laptopommal rögzítettem. :-)

2012. június 7., csütörtök

Alkotói válság

Habár anno úgy határoztam, semmilyen személyes jellegű írást nem teszek közzé, ez most mégis egy picit az lesz. Elsősorban azért mégiscsak a programozáshoz kapcsolódik, ezért találtam úgy, hogy kiírom.

Mostanság (= az elmúlt pár évben) alkotói válságban vagyok: vagy nincs ötletem, hogy mit programozzak, vagy ha van, akkor belekezdek és 10 perc múlva kiikszelem az IDE-t. Ez most, a vizsgaidőszak végével és a nyár berobbanásával ismét nagyobb gond. És próbálok agyalni, milyen programot írjak, ami fenntartja az érdeklődésem.

Tervben van egy gitáros progi, amilyet már korábban is készítettem más nyelveken, meg átnézhetném a többi régi Delphi-s progimat - hátha valamelyik szimpi és kedvem támad remake-elni Java-ban. (Hmm... például az amőba progim!) A minap elkezdtem egy sudoku modellt is, de egyszerűen lusta vagyok folytatni, pedig érdekes.

Továbbfejleszthetném a szakdolim is, ez is az ötletlistán van: újraépíteném a GUI-t, meg még 1-2 funkciót implementálhatnék. Ki akarom próbálni az új Scene Builder-t a JavaFX-hez, csak a múltkori upgrade mizéria után már kisebb fenntartásokkal vágnék bele egy újabb telepítés sorozatba. :D (Noha NB 7.2beta kell neki... és múltkor is a beta verzió volt működőképes :D)

Viszont ami a jövőm szempontjából kiemelten hasznos lenne: Java EE. Neki akarok indulni, át akarom látni, meg akarom tanulni. Csak el kell kezdeni. :-)

Vendégkönyv

Arra gondoltam, hogy csinálok egy vendégkönyvet a blogomra, ahol általános, nem a konkrét bejegyzésekhez kapcsolódó megjegyzésekkel lehet színesíteni az oldalt - pl. vélemény nyilvánítás, ötletek, kritikák. Szóval íme, ez a bejegyzés lesz a vendégkönyv. :-)

2012. május 28., hétfő

Kombinációk generálása

Jelenleg egy olyan progin dolgozom, amiben szükség lenne arra, hogy megkapjam N darab szám összes K (0<K<N) számból álló kombinációját. Ilyen kombinációkból pontosan N!/K!(N-K)! darab van. De hogy is kéne ezeket meghatározni? Én a következőképp csinálnám:

Példaként az { 1, 2, 3, 4 } halmazból válasszuk ki a 2 elemű részhalmazokat!

Így gondolkodtam:

kiveszem: { 1 }, marad: { 2, 3, 4 }
    kiveszem: { 2 }, marad: { 3, 4 } --> KIMENET
    kiveszem: { 3 }, marad: { 2, 4 } --> KIMENET
    kiveszem: { 4 }, marad: { 2, 3 } --> KIMENET
kiveszem: { 2 }, marad: { 1, 3, 4 }
    ...

Vagyis algoritmikusan:

adott az alaphalmaz
az alaphalmaz minden E elemére {
    halmaz = alaphalmaz - E
    a halmaz minden F elemére {
        kombináció = halmaz - F
        kimenet << kombináció
    }
}

Viszont ez csak 2 elem kivonását végzi el, ha kisebb kombinációkra van
szükségünk, akkor több ciklus kell egybe ágyazva. Viszont a ciklusmagok
ugyanazt a feladatot végzik -> így megoldhatjuk rekurzióval a feladatot:

kombinációk(alaphalmaz, k) {
    az alaphalmaz minden E elemére {
        halmaz = alaphalmaz - E
        ha |halmaz| = k
            kimenet << halmaz
        különben
            kombinációk(halmaz, k)
    }
}

Ezzel az algoritmussal, - ha fent végigjátsszuk, láthatjuk, hogy - egy kombinációt többször is ki fog adni. Biztosan meg lehet oldani algoritmikusan, hogy ezt elkerüljük, ezen most nem gondolkodtam, de Java-ban erre egy egyszerű megoldás: a kombinációkat halmazban gyűjtjük. Java implementáció:

2012. május 21., hétfő

Osztott rendszerek vizsgához

Készítettem egy doksit az Osztott rendszerek vizsgához. Ez nem a diasorok teljes fordítása és nem is feltétlenül a teljes anyag. Elsősorban magamnak csináltam, a jegyzeteim és a diasorok alapján, de úgy gondoltam, közzé teszem, hátha valakinek hasznos lehet még. Ha a valakit érdekel, a mappámban elérhető: LINK. Jó készülést, sok sikert! :-)

Update 2012.05.21. @ 22:04
néhány elírás kijavítva, tételek vázlatosan is bekerültek, a doksi végére

Update 2012.05.22. @ 17:13
néhány elírás kijavítva, vázlat pofozgatva egy picit

Update 2012.06.11. @ 12:43
flat elnevezéseknél a finger tábla működése javítva, kiegészítve

2012. május 17., csütörtök

Online compiler

Most, mielőtt kiraktam az euklidészi algoritmust megvalósító Python szkriptemet, azért le akartam ellenőrizni, hogy jó-e. Mivel a gépemen most nincs Python telepítve, és lusta is vagyok feltenni, rákerestem online interpreterre, és lőn, ezt találtam:


Több, mint 40 programnyelvet ismer, beillesztesz egy kódot, ő meg lefordítja és futtatja szerveroldalon, és kiírja az output-ot. A fent említett progim tesztelésére nagyrészt jó volt, csak parancssori paramétereket nem lehet megadni neki. (Vagy legalábbis nem látom, hol lehetne.)

Bővített euklidészi algoritmus

Korábban volt egy "Diszkrét Matematika I. - II." című cikkem, melyet proginfes sorstársaimnak készítettem. Mivel az egy nagyon hosszú bejegyzés volt (meg munkás is, sok képet kéne feltölteni újra), úgy gondoltam, most szétdarabolom kisebb, elkülönülő bejegyzésekre.

Elsőként a Számelmélet témakörhöz szeretném hozzátenni a bővített euklidészi algoritmus általam írt Python implementációját.

Definíció


Meghatározza az a és b egész számok d legnagyobb közös osztóját, valamint az x és y egész számokat, melyekre d=ax+by teljesül. Az eljárás során végig axn+byn=rn, n=0,1...

Algoritmus

  1. Inicializálás:
    • x[0] := 1
    • y[0] := 0
    • r[0] := a
    • x[1] := 0
    • y[1] := 1
    • r[1] := b
    • n := 0
  2. Vége?
    • Ha r[n+1] = 0, akkor x := x[n], y := y[n], d:= r[n] és az eljárás véget ért
  3. Ciklus:
    • q[n+1] := r[n] div r[n+1]
    • r[n+2] := r[n] mod r[n+1]
    • x[n+2] := x[n] - x[n+1] * q[n+1]
    • y[n+2] := y[n] - y[n+1] * q[n+1]
    • n := n + 1
    • -> 2.
(A definíció és az algoritmus forrása a Járai féle Diszkrét Matematika könyv.)

Python implementáció

import sys

a, b = int(sys.argv[1]), int(sys.argv[2])
x = [ 1, 0 ]
y = [ 0, 1 ]
r = [ a, b ]
q = [ 0 ]
n = 0

while (r[n+1] != 0) :
    q.append(r[n] // r[n+1])
    r.append(r[n] % r[n+1])
    x.append(x[n] - x[n+1] * q[n+1])
    y.append(y[n] - y[n+1] * q[n+1])

    # egyszeru kiiras
    #print r[n], "=", r[n+1], "*", q[n+1], "+", r[n+2]

    # bovitett kiiras
    #print r[n+2], "\t", x[n+2], "\t", y[n+2], "\t",
    #    r[n+2], "=", a, "*", x[n+2], "+", b, "*",
    #    y[n+2]

    n += 1

x, y, d = x[n], y[n], r[n]

print "\n", d, "=", a, "*", x, "+", b, "*", y
A progi két parancssori paramétert vár: az a és b számokat.

2012. május 9., szerda

nanotime

Olykor szükségünk lehet arra, hogy megmérjük, mennyi ideig hajtódott végre egy függvényünk. Erre a System osztályban van 2 hasznos statikus metódus. Egyfelől van a currentTimeMillis(), ami milliszekundumban adja vissza az aktuális időt, illetve van a nanoTime(), ami viszont már nanoszekundumos pontossággal. Csak hogy átlássuk az SI mértékegység-rendszer releváns részét:

milli: 10-3
mikro: 10-6
nano:  10-9

Vagyis 1 nanoszekundum = 10-9 másodperc.

A mérési feladat elég szimpla:
long t = System.nanoTime();
valami();
t = System.nanoTime() - t;

És meg is kapjuk, hogy a függvény hány nanoszekundum alatt futott le. Ezzel csak az a baj, hogy ha kiíratunk egy ilyen számot önmagában, ránézésre nem egyszerű megmondani, hogy most ez hány másodperc vagy esetleg perc volt. Érdemes tehát kreálni egy függvényt, ami szépen megformázza ezt a long-ot, és kiköhög nekünk egy olvasható String-et. :-)

/**
 * Transforms a time in nanoseconsds to a readable text.
 * Output format: MM:SS.MS,mS'nS
 * @param time Time to format.
 * @param showMicro Include microseconds in the text?
 * @param showNano Include nanoseconds in the text?
 * @return The time as text.
 */
public static String formatNanoTime(long time,
                                    boolean showMicro,
                                    boolean showNano) {
    long nanosec = time % 1000;
    long microsec = (time / 1000) % 1000;
    long millisec = (time / 1000 / 1000) % 1000;
    long sec = (time / 1000 / 1000 / 1000) % 60;
    long min = (time / 1000 / 1000 / 1000 / 60);

    String r = lpad(Long.toString(min), 2, '0') + ":"
     + lpad(Long.toString(sec), 2, '0') + "."
     + lpad(Long.toString(millisec), 3, '0');
    if (showMicro) {
        r += "," + lpad(Long.toString(microsec), 3, '0');
    }
    if (showMicro && showNano) {
        r += "`" + lpad(Long.toString(nanosec), 3, '0');
    }
    return r;
}

Nem volt kis meló összerakni az osztásokat, maradékképzéseket... izzadtam vele egy ideig, de sikerült. :-)
Az lpad(String, int, char) függvényem annyit csinál, hogy jobbról kiegészíti a szöveget a megadott karakterrel, a megadott hosszúságra. Ezt nem illesztem be, 3 soros ujjgyakorlat.

2012. április 8., vasárnap

2012. március 29., csütörtök

Angol szótár

A PCFórum-on találtam rá az alábbi cikkre: Kihívója támadt a Sztaki szótárnak

A TopSzótár nevű új oldalról van szó. Egy olyan angol-magyar szótárt kínál, mely áthidalja az általam ismert és eddig használt 2 szótárban - Sztaki és DictZone - tapasztalt nehézségeket, hiányosságokat. A keresőbe beírható ragozott, múltidejű, többes számú alak, a rendszer felismeri és kiadja az alapszót. Ezeket az alakokat ki is írja rendezetten minden szó esetén. Megjeleníti a szófajt, illetve kifejezéseket is, valamint néhol példamondatokat is meg tud jeleníteni. Emellett akasztófázhatunk is az oldalon, ha unjuk a banánt. :-)


2012. március 19., hétfő

Broken

Művelem magam az Evanescence, és csodálatos hangú énekesnője, Amy Lee munkássága terén. Bújom a YouTube-ot, számomra még ismeretlen számok után kutatva, és nyugodtan mondhatom, kincsekre is bukkanok. Az alábbi is egy ilyen: Amy Lee közreműködése a Seether nevű pretoriai bandával, a dal címe Broken.


Nagyon szép a gitárszólam, én libabőrözök végig. A srác hangja kellemes, mély, Amy pedig ebben a dalban sem okoz csalódást. A téma mély, nem éppen vidám. A klipp is egész jó, Amy-n jól állnak a szárnyak! :-)

Kötelező darab.

2012. március 18., vasárnap

URL encode-decode

Ha GET-es form-okkal dolgozunk, szükségünk lehet arra, hogy át tudjunk adni speciális karaktereket is a querystring-ben, például + vagy szóköz. Ebben van segítségünkre a beszédes domain-nel rendelkező alábbi eszköz, mely segít az oda-vissza kódolásban.

Reguláris kifejezésekhez

A szakdolimban elég sok reguláris kifejezést használtam, megfogalmazásukban az alábbi tool volt segítségemre:


Real-time kijelöli a szövegben a mintára illeszkedő részeket, ha pedig az egeret is ráviszed, kiírja az illeszkedés adatait (pl. kezdet, hossz, csoportok illesztett értékei).

2012. március 15., csütörtök

Imaginary verziók

Egyik kedvenc Evanescence számom, az Imaginary több verzióban is kikerült a stúdióból, tegnap találtam még két demót, fantasztikusak! :-)

Demo #1


Itt vannak a verziók YouTube linkekkel, válaszd ki, neked melyik tetszik! :-)


Részletek és dalszövegek: http://evanescencereference.info/wiki/index.php?title=Imaginary


2012. március 13., kedd

Szálak kordában tartása

Előfordul, hogy olyan programot írunk, amely előbb-utóbb 20-30, esetleg 50-100 szálat is indít, ami nem biztos, hogy egészséges. Szükségünk lehet arra, hogy limitáljuk az egy időben futó szálak számát. Ez azonban nem egy triviális feladat.

Első gondolat: statikus counter (a saját szál osztályunkban). Szinkronizált get, inc, dec, és várakoztatás indítás előtt, egy üres while ciklussal. Néhány szálnál ez látszólag működőképes megoldás (ha jól meg van írva). Azonban ez így önmagában nem elég. Elképzelhető, hogy két szál "egyszerre" lép ki a while ciklusból (vagyis "A" szál érzékeli, hogy csökkent a számláló, azaz kiléphet, de nem tudja olyan gyorsan visszanövelni a számlálót, hogy "B" szál ne tudjon szintén kilépni a várakozásból). Ebben az esetben máris limit+1 darab szálunk fut. Minél több szálunk van, annál többen várakoznak, annál nagyobb az esély arra, hogy "egyszerre" indulnak el a várakozás után, és annál több szál indulhat el, vagyis annál jobban meghaladja a limitet a szálak száma. Más megoldás kell: ütemező.

Ma sikerült saját magamtól összeraknom egy ilyet, és működik, nem merészkedik a limit fölé a counter. Igaz: nincs is counter! :-)

Alapötlet: tároljuk a futtatandó, ütemezendő szálakat egy listában, és legyen egy szál, ami menedzsel, ütemez. Folyamatosan figyeli a futó szálakat, és ha valamelyik leállt, akkor törli a listából, és indít egy újat (a legelső még nem futó szálat). Ennek értelmében a futó szálak egymás melletti listaelemek lesznek, mégpedig a lista elején, így elég csak a [0..(limit-1)] intervallumot figyelni. Ha egy szál leállt, töröljük a listából, ekkor a (limit-1)-es indexű listaelem lesz az a szál, amit el kell indítani (persze, ha van egyáltalán annyi elem).

Ezzel a megoldással teljes mértékben felügyeljük a szálak indítását, hiszen csak az ütemező maga indítja azokat. Mivel ciklusba van szervezve a vizsgálat, a szálakat, mint listaelemeket egymás után nézi meg, így konkurencia sincs, nem fordulhat elő, hogy "egyszerre" két szál is elinduljon. :-)

Ezen felül, ha a sok szálat elindító főszálnak szüksége van arra, hogy megvárja, amíg a szálai befejeződnek, elég csak az ütemező szálat figyelni, hogy fut-e még. Persze ez implementáció kérdése, de az én megvalósításom így működik.
import java.util.ArrayList;
import java.util.List;

public class ThreadScheduler extends Thread {

    private int limit = 3;
    private List<Thread> threads = new ArrayList<Thread>();

    public ThreadScheduler() {
        setName("ThreadScheduler");
    }

    public synchronized void add(Thread t) {
        threads.add(t);
    }

    private synchronized boolean manage() {
        for (int i = 0; i < limit && i < threads.size(); i++) {
            if (!threads.get(i).isAlive()) {
                threads.remove(i);
                if (threads.size() >= limit) {
                    threads.get(limit - 1).start();
                }
                break;
            }
        }
        return !threads.isEmpty();
    }

    @Override
    public void run() {
        for (int i = 0; i < limit && i < threads.size(); i++) {
            threads.get(i).start();
        }
        while (manage());
    }
}

A run() metódus először elindítja az első szálakat, a [0..(limit-1)] intervallumban, hogy a menedzselés ne törölje őket.

Használata pedig:
ThreadScheduler sched = new ThreadScheduler();

// szálak hozzáadása
sched.add(t);

// ütemezés indítása
sched.start();

// megvárhatjuk, mikor futott le mindegyik szál
while (sched.isAlive());
System.out.println("The End");

Egy lehetséges kiegészítés lehet még a megszakíthatóság. Ez esetben a run() metódus while ciklusának feltételéhez hozzá kell venni az isInterrupted() vizsgálatát, illetve a ciklus után egy elágazásban: ha megszakítás volt, akkor küldjön megszakítást a futó szálaknak. (És persze megvárni a még futó szálak befejeződését, végül pedig esetleg üríteni a listát.)

2012. március 12., hétfő

Metallica - Beyond Magnetic EP

A tavalyi év végén jelent meg az iTunes-on a Metallica új EP-je, a Beyond Magnetic.

Meghallgattam.

Amit tapasztalok (objektív dolgok): próbálnak új technikákat belevinni a zenéjükbe, Kirk játszik a tremolo karral és wah pedállal, illetve sokszor megtörik az ütemet, eltérnek a 4/4-től, hatásszünetet tartanak, hirtelen stílus-/hangzás-/ritmusváltásokat alkalmaznak track-en belül.


Amit gondolok (szubjektív dolgok): a riffek nem rosszak, a hangzások is el vannak találva. A szólók nekem gyengék, meg a számok is valahogy nekem nyögve-nyelősek, vérszegények. A váltások néhol túl hirtelenek. Nekem úgy tűnik, a Metallica veszített a lendületből. Érzem ezt azóta, hogy láttam egy koncertfelvételt a World Magnetic Tour-ról, ami csalódást okozott. Nem dobtam hátast a Beyond Magnetic-től. Nem fog eszembe jutni, hogy előszedjem ezt az EP-t a jövőben.

(A dalszöveget nem figyeltem, de nem is keltette fel az érdeklődésem.)

Ablak a képernyő közepére

A Swing általában nem foglalkozik azzal, hogy az ablakot hol helyezi el a képernyőn: a bal felső sarokban jeleníti meg az új ablakokat. A JavaFX 2 már valamelyest kiközepeli, de szerintem nem pontos (bár lehet, hogy csak azért, mert a kliens területet nézi a képernyőn, a tálcát levágva).

Pofon egyszerű megoldani az ablak középre igazítását. Le kell tudni kérdezni a képernyő méreteit, az ablak szélességét, és tudni kell állítani a pozíciót.

Swing-ben szükség van a java.awt csomag Dimension és Toolkit osztályára, illetőleg a Window-ra. Mivel ez utóbbiból származik a JFrame és a JDialog is, ha Window-ra oldjuk meg a problémát, az mindkettőhöz használható lesz.
public static void centerizeWindow(Window w) {
    Dimension s = Toolkit.getDefaultToolkit().getScreenSize();
    Dimension d = w.getSize();
    int left = (int) ((s.width - d.width) / 2);
    int top = (int) ((s.height - d.height) / 2);
    w.setLocation(left, top);
}

JavaFX-ben az ablakot a Stage reprezentálja. JavaFX-ben is elérhetjük a képernyő tulajdonságait, ehhez a javafx.stage.Screen, illetve a javafx.geometry.Rectangle2D importokra van szükségünk.
public static void centerizeStage(Stage stage) {
    Rectangle2D screen = Screen.getPrimary().getVisualBounds();
    stage.setX((int) ((screen.getMaxX() - stage.getWidth()) / 2));
    stage.setY((int) ((screen.getMaxY() - stage.getHeight()) / 2));
}

Valójában a Stage a javafx.stage.Window leszármazottja, és a fenti metódusban is a Window gettereit/settereit használjuk, de a Window-nak nincs más olyan származtatása, amit középre igazítanánk a képernyőn, így az egyszerűbb használat érdekében maradhat a Stage típusú paraméter.

2012. március 10., szombat

Runnin' Wild

Nagyon jó zenére programozni, hát még rock-ra! :D

Nemrég találtam az alábbi nótát, első hallásra megtetszett. Jó, hogy azért van 1-2 együttes manapság, amelyik tud zenét csinálni. A Runnin' Wild egy jó kis rock 'n' roll zúzás. Erősen AC/DC-s a zene: a riffek jellege, az effekt és a srác hangja is, de jól tolják - továbbviszik a stílust. Ők is ausztrálok, akárcsak a legendás AC/DC. Érdemes belehallgatni a többi számukba is. :-)

Airbourne - Runnin' Wild

Kódszépítés

A szakdolim fejlesztése során kitaláltam egy kis technikát, hogyan lehetne rövidebb és (számomra) esztétikusabb a kódom. Ott a JavaFX Label osztályával csináltam meg az alábbi trükköt, most általánosan írom le.

Ha van egy ilyen jellegű dolog:
Valami v = new Valami();
v.setA(1);
v.setB("akarmi");
v.setC(true);

Meg lehet csinálni azt, hogy származtatod az osztályt, beburkolod a függvényeket úgy, hogy meghívják az ősben levő függvényt, majd visszaadják az objektumot:
public class ValamiEx extends Valami {

    // konstruktorokat is le kell másolni, bennük super(...); hívással

    public ValamiEx setA(int i) {
        super.setA(i);
        return this;
    }

    public ValamiEx setB(String s) {
        super.setB(s);
        return this;
    }

    public ValamiEx setC(boolean b) {
        super.setC(b);
        return this;
    }
}

Ezzel a megoldással már a fenti kód le is rövidül:
Valami v = new ValamiEx().setA(1).setB("akarmi").setC(true);

Ezt a mintát alkalmazva egy Label objektum esetén akár egy sorban beállítható minden formázás:
Label label1 = new LabelEx("Hello LabelEx!").bold().italic().center(); // stb.

Szerintem legalábbis ez így esztétikusabb. :-)

2012. március 9., péntek

Billentyűkezelés JFrame-ben

Biztos sok Java-s programozótársam gondolkodott már azon, hogy lehetne Swing-es JFrame ablakban lekezelni a billentyűket, ha a KeyListener-es megoldás nem működik. Mert van olyan, hogy az nem működik: például a form-hoz hiába adod hozzá, nem csinál semmit, pláne ha van legalább egy gombod vagy beviteli meződ - mert akkor azok valamelyike lesz fókuszban és kapja el a billentyűleütés eseményét. Játékot ezzel nem lehet írni.

Létezik azonban egy globális billentyűzetkezelő mechanizmus, amihez hozzá lehet adni egy saját osztályt, aminek a metódusa szépen meghívódik minden billentyűzet esemény bekövetkezésekor, amíg a program fut, bármelyik objektum vagy form is legyen fókuszban. A KeyEventDispatcher interfészt kell megvalósítani, majd átadni az objektumot a KeyboardFocusManagernek.

Én minden ablakomba tettem egy saját dispatcher-t, de mivel ezek globálisan kapják el a billentyűeseményeket, írtam a metódusukba egy elágazást, hogy csak akkor kezelje le az eseményt, ha az adott ablak van fókuszban.

Példa:
public class MyWindow extends JFrame implements KeyEventDispatcher {

    public MyWindow() {
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new MyKeyEventDispatcher());  
    }

    @Override
    private boolean dispatchKeyEvent(KeyEvent e) {     
        if (!MyWindow.this.isFocused()) return false;

        if (e.getID() == KeyEvent.KEY_PRESSED) { // lenyomva
            if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                //...
            } // else if ...
        } else if (e.getID() == KeyEvent.KEY_RELEASED) { // felengedve
            // ...
        } else if (e.getID() == KeyEvent.KEY_TYPED) { // gépelve (?)
            // ...
        }
        return false;
    }
}
A RELEASE és TYPE ágakkal én nem nagyon foglalkoztam, nem is igazán tudom mi a különbség a TYPE és a PRESS között, ennek kikísérletezését rátok bízom.

2012. március 8., csütörtök

NetBeans 7.1 - megéri váltani?

Tegnap érdekes problémára derült fény.

A NetBeans 7.1beta-val készített projektet átültettem, hogy a 7.1-ben is fusson, de újabb gond akadt. NB-ből futtatva gyönyörűen megy, viszont az elkészített JAR fájl futtatáskor nem találja a lib-eket. A probléma a jar/META-INF/manifest.mf fájljában leledzik, ami tárolja azt a classpath-t, amit a JAR fájl használ futáskor.

A NB 7.1-es verziója konkrétan elfelejti definiálni a "JavaFX-Class-Path" értéket a manifest fájlban. Voltam olyan eszes, hogy backupoltam a 7.1beta-val készített JAR-t, így azzal össze tudtam hasonlítani, innen derült fény a turpisságra. (És azt, hogy melyik fájlban lehet gond, a témavezetőm mondta, úgyhogy innen is köszönet neki!)

Lehetséges konklúzió: maradjunk meg a NetBeans 7.1beta-nál? (És nézzük el, hogy néha exception-t dob a lassúság-detektora?)

A hibát még a 7.1.1-es verzióban sem javították.

2012. március 5., hétfő

Forráskód színezés Blogger-be

Már korábban is szemeztem ezzel a tool-lal, de azt hiszem egy fő témának a programozást megjelölő blogra illenék is reflexből beépítenem: SyntaxHighlighter. Ez arra jó, hogy szintaktikus színezést tud alkalmazni oldalba illesztett forráskódba. JS-sel dolgozik, és persze bővíthető.

Nagyon egyszerű beépíteni, ez a cikk jól leírja: link. Nem másolom át ide, felesleges, csak néhány kiegészítést tennék hozzá.

A cikkben azt írja, hogy a bejegyzés előnézetében a Blogger nem futtatja le a szkriptet, pedig igen. :-)

Illetve, én még hozzáadtam ezt a CSS sort a blogomhoz:

div .syntaxhighlighter { padding-bottom: 1px; }

Ugyanis a SH egy kicsit bugos: nem jól számítja ki a doboz magasságát, 1 pixellel kisebbre veszi, mint a tartalom, így megjelenik egy oldalsó scrollbar. A fenti CSS kóddal ez kiküszöbölhető.

A SH honlapján (fentebb linkeltem) fent van, milyen nyelveket támogat, és milyen témák vannak (elég gyér választék amúgy, de nyilván pofon egyszerű egyénit hozzáadni), illetve, hogy ezeket hogyan kell hozzáadni a szkripthez. (Pofon egyszerű, csak include-álni kell <link ... /> tag-ekkel.)

Cellaformázás JavaFX 2-ben

A szakdolim felületének építése során előjött egy érdekesség, amiről nem szól a fáma... akarom mondani a JavaFX tutorial: a TableView egyik oszlopában én linkeket szerettem volna látni, azaz kék, aláhúzott kattintható szöveget.

A TableView ugye egy megadott osztályhoz készül, és ennek mezőihez lehet megfeleltetni oszlopokat. A táblázat adatforrása pedig a megadott osztály példányaiból álló lista. (Ebben most nem fogok elmerülni, példakódhoz lásd: TableView tutorial)

Mivel a TableColumn osztályban nincs lehetőség formázásra, oszlop szinten, a cellaépítő függvényt kell kiegészíteni.

Tegyük fel, hogy van egy Link osztályom, aminek van egy url nevű String mezője, egy getterrel, és ehhez készítem az oszlopot. Eképpen sikerült megoldani (utána magyarázom):

TableColumn linkCol = new TableColumn("URL");
linkCol.setPrefWidth(250);
linkCol.setCellValueFactory(new PropertyValueFactory<Link, String>("url"));
final Callback<TableColumn<Link, String>, TableCell<Link, String>> cf
    = linkCol.getCellFactory();
linkCol.setCellFactory(
    new Callback<TableColumn<Link, String>, TableCell<Link, String>>() {

    public TableCell<Link, String> call(TableColumn<Link, String> param) {
        final TableCell<Link, String> cell = cf.call(param);
        cell.setStyle("-fx-text-fill: blue; -fx-underline: true");
        cell.setOnMouseClicked(new EventHandler<MouseEvent>() {

            public void handle(MouseEvent event) {
                System.out.println("LINK: " + cell.getText());
                // avagy: java.awt.Desktop.getDesktop().browse(
                //                          new URI(cell.getText()));
                // (persze a megfelelő előzetes ellenőrzésekkel)
            }
        });
        return cell;
    }
});

Vagyis először létrehozom és beállítom az oszlopot, utána lekérem a függvényt, amivel a JavaFX felépítene egy cellát, majd készítek egy saját cellaépítőt. Ebben az elsődleges dolog: meghívom a default cellaépítőt, amit lekértem az előbb, így már csak a plusz formázást kell hozzáadnom, illetve a kattintás eseménykezelőjét.

2012. március 4., vasárnap

JavaFX 2 - tapasztalatok

Pár napja fejeztem be a szakdolgozatom, aminek a GUI-ját JavaFX-ben dobtam össze, így az elmúlt 2 hónapban gyűjtött tapasztalataimat most megosztom e nagyszerű API-val kapcsolatban.

Mi is a JavaFX 2 ?

Egy API, mellyel GUI-t adhatunk Java projektünkhöz. Olyan, mint a Swing, csak sokkal szebb és funkciógazdagabb. Ha rákeresünk a JavaFX 1.x-es verzióira, láthatjuk, hogy annak külön szintaktikát vezettek be, szerencsére ez a 2.0-ban már nincs így, úgy használható, mint bármely más csomag. Csak telepíteni kell hozzá a fejlesztő kit-et, illetve a célgépen csak a runtime-ot. Emellett Java 7-et követel meg, illetve NetBeans 7.1-et (pontosabban). A NB-ben az új projekt varázslónál ki is lehet választani, hogy egy JavaFX projektet kezdesz, ekkor kapsz egy Hello World-öt.

A JDK telepítőjében a 7u2-es verziótól már megtalálható a JavaFX SDK is, tehát nem kell külön letölteni és installálni.

+ Előnyök

Gyönyörű grafikai elemeket tartalmaz, könnyen és gyorsan össze lehet dobni vele a felületet, a tutorial segít is benne. Emellett új kontrolok is vannak, például többféle grafikonnal is színesíthetjük projektünket (érdemes letölteni a samples csomagot!). Az elemeket CSS alapon lehet formázni, és van lehetőség effektezésre, akár animáltan is, és mivel a végeredmény lazán beágyazható weboldalba is, simán vetélytársa lehet a Flash-nek.

- Hátrányok

A tutorial csak az alapokat mutatja be, ha valami komolyabbat akarsz benne összerakni, bújni kell a doksit és izzadni pár cseppet, mire kitalálod, hogyan is kell. Az univerzalitás néhol a könnyű használat rovására megy. Például nekem nem tetszik az, ahogy a cellaformázást meg lehet oldani: ugyanis egyenként kell, oszloponként nem lehet. (cikkem erről)

Vannak benne bugok is, például a TextArea betűszínét még a legfrissebb 2.0.3-es verzióban sem képes átszínezni.


Hiányosságai is vannak, például nekem hiányzik egy onResize szerű event az ablakot formáló Stage objektumból. A kis méret / teljes méret gombokat sem lehet kikapcsolni, így dialog-ot készíteni benne (mert ugye nincs rá külön class) nehezebb.

Linkek

Minden (tutorial, letöltések) megtalálható itt: http://javafx.com
Érdemes a CSS referenciát könyvjelzőbe tenni, ha komolyabban is fejlesztesz a JavaFX-szel! :-)

2012. március 3., szombat

Megfelelő bélyegkép beállítása Facebook megosztáshoz

Probléma: ha közzé akarom tenni a blogomat a Facebook-on, Picard kapitány facepalm fotóját teszi be bélyegképnek a közösségi portál. De én nem azt a képet szeretném, hanem egy másikat.

Órákig gugliztam, és többször nekifutottam a keresésnek, mire a sok cikk között végre találtam egy normális leírást, hogyan is kell ezt megoldani.

Sok helyen dobálóznak a <link rel="image_src" href="..." /> tag-gel, de ez nem működik.

Utána említik az OpenGraph protokol property-jeit, amit meta tag-ben lehet átadni, ez már a megoldás egyik fele, de önmagában fabatkát sem ért.

A korrekt cikk, ami leírja mit kell csinálni, itt található: link. De én is leírom most.

Megoldás:


  1. Adj hozzá egy <meta property="og:image" content="..." /> tag-et a HTML laphoz (head részbe), ahol a "..." helyére írd be a képfájl URL-jét. (Bloggerben: Sablon -> HTML kód szerkesztése gomb.)
  2. Látogass el ide: Debugger, írd be az oldalad címét, majd ENTER. Ez a tool megmutatja, milyen infókat sikerült a Facebook-nak kinyernie a beírt URL-ről. Ami viszont még fontosabb, hogy nem csak megmutatja, hanem frissíti is a Facebook cache-t! Ez utóbbiért fontos ez a lépés.

(Blogger esetén várj 1-2 percet a 2 lépés között, hogy legyen ideje a Google-nek frissíteni a sablont a szerveren.)

2012. március 2., péntek

JDK, JavaFX és NetBeans upgrade

Ma úgy döntöttem, hogy upgrade-elem a NetBeans-emet 7.1beta-ról a 7.1 stabil változatra, illetve a JavaFX 2.0.2-met a 2.0.3-as verzióra. Közben viszont láttam, hogy a JDK-hoz a 7u2-től már hozzácsapják a JavaFX-et is, úgyhogy leszedtem a legfrissebb JDK 7u3-at is.

Eltávolítottam a régebbi változatokat szép sorjában, majd feltoltam mindent egymás után. Jó dolog egyébként, hogy a JDK-ban már a JFX is benne van, időt és adatforgalmat/helyet is megtakarítok vele, mert így a JDK telepítője csak 5 megával több, míg a külön JFX telepítő 14 körül van.

Viszont a gond ott kezdődött, hogy megnyitottam az új NetBeans-ben a beta verzióval fejlesztett projektemet.  Már megnyitáskor jelezte, hogy valami gond van a függőségekkel: a JavaFX platform neve megváltozott az új verzióban. Jó, ezt még egyszerű átállítani "Default JFX platform"-ról "Default JavaFX platform"-ra.

Ezután build-elés meghiúsult egy hibaüzenettel: Target "jfxsa-run" does not exist in the project <projektem neve>. Éreztem, hogy a build szkriptben lehet valami változtatás, de ehhez nem értek, úgyhogy gugliztam. A NetBeans fórumain redundánsan is jelezték, mint bugot. Valahol azt találtam, hogy instabil->stabil upgrade-hez nem adnak támogatást a fejlesztők. (Szerintem ez mocsokság.) Az egyik hozzászólásban azt írták, hogy új projekt létrehozásával és átpakolgatással megszűnik a gond. Persze én is gondoltam erre, csak reméltem, hogy lesz egyszerűbb megoldás is. Úgyhogy végül ezt csináltam. Létrehoztam másik mappában egy ugyanolyan nevű projektet, átcopy-ztam mindent, beállítottam a lib-eket, majd az nbproject mappa tartalmát áthúztam az eredeti projektmappámba.

Az EclipseLink JPA2.0-val meggyűlt a bajom. Csak úgy tudtam újra hozzáadni, hogy létrehoztam egy új entity class-t, azzal a NB beimportálta a lib-et, majd töröltem az osztályt, ezután pedig felülírtam a saját persistence.xml fájlommal az újonnan generáltat. És ekkor sikerült végre elérni, hogy az újraépített projekt működjön is.

Frissítés, 2012.03.08.

2012. március 1., csütörtök

Azure és a szökőév

Friss hír: a srácok a Microsoft-nál elfelejtették, mi is az a szökőév, így tegnap lehalt az Azure.

Cikk: http://www.hwsw.hu/hirek/48180/microsoft-azure-leallas-cloud-felho.html

Azért most így elgondolkodtam, hogy ha egy szökőnapot képesek kihagyni a számításból, akkor milyen hiányosságok lapulhatnak a biztonsági modulokban...


2012. február 29., szerda

Üdv!

Köszöntelek az új blogomon!

Néhány napja találtam ki, hogy egy új bloggal állok elő, és ma sikerült körvonalaznom, milyen témákat is fog tartalmazni:

  • Az elsődleges téma: programozás. Lesznek kódrészletek (főként Java), egy-egy probléma megoldása, tervezési gondolatmenetek, illetve például le fogom írni a tapasztalataimat a JavaFX 2.0-val kapcsolatban.
  • Tervezem, hogy egyetemmel kapcsolatban is publikálok, például, hogy mi folyik a proginf képzésen, milyen tárgyak vannak, és mégis ezek miről szólnak.
  • Lesznek zenés bejegyzések, mert zene nélkül nincs élet. Felvonultatom majd aktuális és örök kedvenceimet is.
  • Ezen kívül elképzelhetőnek tartom, hogy verseket is kirakok, amelyek valamiért megfogtak, illetve talán poénos képek, képregények, egypercesek is megjelennek majd itt.

Folyamatosan töltöm fel régebbi cikkeimet. Némelyiket egy-az-egyben, némelyiket átírva az új, komolyabb szemlélet jegyében. Mert teljesen új a blog mögött rejlő gondolkodásmód is:

  • Csak mindenki előtt vállalható bejegyzéseket fogok itt közzétenni,
  • melyek akár referenciaként szolgálnak, például kész programjaim is felkerülnek majd (talán),
  • illetve olyan cikkek, amik másokat esetleg előremozdítanak, segítenek.

Remélem, lesz, aki hasznát, esetleg örömét leli majd a bejegyzéseimben. :-)

2012.02.28. @ 17:14

2012. február 28., kedd

Blogger Attribution blokk elrejtése

A Blogger rendszere nagyon bebiztosítja az "Attribution"-nek keresztelt dobozt, ami a blog alján megjelenik. Ez tartalmazza a sablon nevét, és a szöveget, hogy "Működteti a Blogger". Az Elrendezés panelről nem lehet kivenni, ha pedig a HTML kódban kikommentezed, hibát jelez a rendszer, nem engedi elmenteni - mégis akkor hogyan lehet eltüntetni?

A megoldás: CSS-sel.

Irány a Sablontervező, Speciális lap, Stíluslap (CSS) hozzáadása panel, írd be a következő sort:

div .Attribution { visibility: hidden; margin-top: -50px }

És tádá! El is tűnt. Persze a -50-es értéket állítsd be igényed szerint, ez a láthatatlanná tett Attribution doboz tetejét fogja fel/le vonszolni. Én azért tettem bele ezt, hogy ne legyen túl nagy űr a lap alján.

Egyébként érdemes CSS-t tanulni és belepiszkálni itt a sablonba, olyan finomhangolásokat tudsz itt csinálni, amire a Blogger nem biztosít lehetőséget, és amellyel esztétikusabbá teheted a blogod. :-)

2012. február 26., vasárnap

Gyors fejlesztés NetBeans-ben

Nyilván a legtöbb NB felhasználónak nem fogok újat mondani, viszont aki még nem ismeri az alábbiakat, örülni fog! :-) Nekem speciel megváltozott az "életem", vagyis a programozási stílusom, amikor megismertem a következő billentyűkombinációkat:


ALT+SHIFT+F

Megformázza az egész kódot. Az elágazások és ciklusok után kiteszi a kapcsos zárójelet, szóközökkel veszi körbe a műveleti jeleket, minden parancs új sorba kerül, stb. Lehet ezt finomhangolni a beállítások panelen.


CTRL+SPACE

Olyan, mint a konzolban a TAB: megpróbálja kiegészíteni az előzőleg beírtakat. Ha több lehetőség van, kidob egy listát, amiből választhatsz. Rövidíti a változó- és metódusnevek begépelését, illetve kilistázza ismeretlen osztályok metódusait. (Mint ahogy a "." után is.)


"sout" és TAB, "serr" és TAB

System.out.println(""); vagy System.err.println(""); beszúrása gyorsabban.


ALT+ENTER

Ha egy sorban piros aláhúzás van, ezzel a billentyűkombóval kérdezhetjük meg, mit javasol a NetBeans. Ha egyetlen lehetőség van, már alkalmazza is egyből. Például absztrakt osztály példányosításakor az absztrakt metódusok definiálása.


CTRL+SHIFT+I

Hozzáadja a szükséges import-okat, törli a szükségteleneket, ABC-be rendezi őket, illetve ha egy adott csomagból túl sok osztály van egyesével importálva, akkor összevonja *-ra. Ha egy osztály több package-ben megtalálható, megkérdezi, melyiket szeretnénk használni.


ALT+DEL

Konstruktorok, getterek, setterek létrehozása pár gombnyomással, a mezőket is ki lehet választani. Lehetőség van override-olni kívánt metódus kiválasztására is.


CTRL+R

Változó, metódus, osztály átnevezése, refaktorálással.