Rośnie popularność aplikacji RIA. Powstaje coraz więcej narzędzi i języków do tworzenia takich aplikacji. W tym artykule postaram się przedstawić podstawy JavaFX – języka skryptowego ze stajni SUNa.
JavaFX na początku zniechęcała mnie od siebie reklamując się jako język skryptowy – miałem zbyt dużo złych skojarzeń z Javasciptem, a konkretnie z brakiem statycznego typowania argumentów. Jednak już po lekturze paru artykułów i pierwszej prostej aplikacji okazuje się, że nie jest tak źle – powiedziałbym nawet, że jest całkiem nieźle.
Jako narzędzie do developmentu wybrałem NetBeans IDE for JavaFX – wtyczka do eclipse jest również dostępna, jednak dopiero dla wersji 3.5.
Przejdźmy do konkretów. Stwórzmy prosty kalkulator by poznać semantykę języka. Uruchamiamy NetBeans, i wybieramy New Project
Z kategorii wybieramy JavaFX, klikamy next
Uzupełniamy nazwę projektu, zaznaczamy „Empty Project”, „Set as Main Project” oraz odznaczamy „Create Main File”. Klikamy Finish – NetBeans wygeneruje dla nas projekt kalkulatora.
Po utworzeniu projektu dodajemy naszą klasę „Calculator”. Klikamy prawym na projekcie, wybieramy „New” -> „Empty JavaFX File” i uzupełniamy nazwę klasy. Opcjonalnie można uzupełnić nazwę pakietu, ale w tym przykładzie nie jest to konieczne. Następnie uzupełniamy ciało klasy – aby było to bardziej czytelne. pozwolę sobie nieco skrócić opis. Cały projekt można pobrać tutaj
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.control.TextBox; import javafx.scene.control.Button; import javafx.scene.input.MouseEvent; var currResult:Number = 0; var firstElem:Number; var secondElem:Number; var funcToRun:function(); var funcDefined = false; Stage { title: "JavaFX quick calculator!" scene: Scene { width: 130 height: 150 content: [ ...... ] //Content } //Scene } |
Pierwsze co rzuca się w oczy to
1 | import |
, który znany jest wszystkim programistom Javy i nie tylko. Okazuje się, że JavaFX mimo że jest językiem skryptowym jest kompilowana do bytecode maszyny wirtualnej i tam uruchamiana. Dalej mamy definicje zmiennych, gdzie obserwujemy ciekawą właściwość JavyFX, a mianowicie możliwość (ale nie konieczność!) określenia typu danych jakie reprezentuje dana zmienna. Kompilator sam domyślnie jest w stanie nadać typ na podstawie pierwszej przypisanej zmiennej. A zatem obie konstrukcje -
1 2 |
- są jak najbardziej poprawne i akceptowane przez kompilator. JavaFX udostępnia sporo wbudowanych typów danych jednak na potrzeby kalkulatora wystarczy nam Boolean, Number (liczby zmiennoprzecinkowe) i function(). Function() nie jest w ścisłym znaczeniu typem danych, ale pozwala zdefiniować zmienną, której użyjemy w dość ciekawy sposób później.
Stage definiuje nam nasze „okno robocze”, czyli obszar w którym będziemy dodawać i wyświetlać nasze komponenty. Scena to element właściwy w którym pojawia się zawartość.
Struktura elementów w JavaFX nieodzownie kojarzy się mi z DOM – chodzi o rozrastające się ku dołowi drzewo. W każdym elemencie możemy definiować kolejne elementy coraz bardziej rozgałęziając drzewo. Dodajmy parę gałęzi do sceny – niech to będzie pole tekstowe, w którym będą pojawiać się wyniki oraz przyciski funkcyjne kalkulatora.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | var currResult:Number = 0; var firstElem:Number; var secondElem:Number; var funcToRun:function(); var funcDefined = false; Stage { title: "JavaFX quick calculator!" scene: Scene { width: 130 height: 150 content: [ TextBox{ layoutX:2; layoutY:2; height:20; width:120; text: bind currResult.toString(); editable:false; }, … Button{ layoutX:2; layoutY:75; text:"+"; width:55; height:20; onMouseClicked:function (e:MouseEvent){ if(funcDefined){ funcToRun(); } funcToRun=function(){ currResult=firstElem+secondElem; firstElem=currResult; secondElem = 0; } funcDefined = true; } }, //... kolejne przyciski dla -, *, /, = ] //Content } //Scene } |
Każdy element jak widać jest dość mocno zbliżony do siebie w definicji – posiada koordynaty położenia, dane dotyczące wymiaru i tekst jaki ma się pojawiać.
Warte zauważenia jest słówko
1 | bind |
- określna ono wiązanie pomiędzy naszą zmienną currResult a polem tekstowym TextBox. Wykorzystanie bind
pozwala nam nie martwić się o aktualizowanie pola tekstowego gdy zmieni się wynik przechowywany w zmiennej currResult – bind
sprawia, że zmiana currResult jest automatycznie propagowana do elementu
1 | text |
TextBoxa. Drugą istotną rzeczą jest element
1 | onMousceClicked |
JavaFX pozwala definiować funkcje listenerów na dane zdarzenia (tu kliknięcie myszką na przycisk) w prosty sposób. W naszym przykładzie nadpisujemy zdefiniowaną wcześniej zmienną:
1 | funcToRun |
przez podanie nowego ciała metody. Zostaje dodać nam przyciski cyfr, przycisk CE i „=”, by kalkulator mógł zacząć działać
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | var currResult:Number = 0; var firstElem:Number; var secondElem:Number; var funcToRun:function(); var funcDefined = true; Stage { title: "JavaFX quick calculator!" scene: Scene { width: 130 height: 150 content: [ TextBox{ layoutX:2; layoutY:2; height:20; width:120; text: bind currResult.toString(); editable:false; }, Button{ layoutX:2; layoutY:25; text:"1"; width:20; height:20; onMouseClicked:function (e:MouseEvent){ if(not funcDefined){ firstElem=firstElem*10+1; currResult=firstElem; }else{ secondElem=secondElem*10+1; } } },//... kolejne przyciski dla pozostałych cyfr Button{ layoutX:2; layoutY:75; text:"+"; width:55; height:20; onMouseClicked:function (e:MouseEvent){ if(funcDefined){ funcToRun(); } funcToRun=function(){ currResult=firstElem+secondElem; firstElem=currResult; secondElem = 0; } funcDefined = true; } }, //... kolejne przyciski dla -, *, / Button{ layoutX:2; layoutY:125; text:"CE"; width:55; height:20; onMouseClicked:function (e:MouseEvent){ funcToRun=function(){} funcDefined = false; currResult = 0; firstElem = 0; secondElem = 0; } }, Button{ layoutX:67; layoutY:125; text:"="; width:55; height:20; onMouseClicked:function (e:MouseEvent){ if(funcDefined){ funcToRun(); } funcToRun=function(){} funcDefined = false; firstElem = 0; secondElem = 0; } } ] //Content } //Scene } |
Jak widać struktura przycisków z cyframi niczym nie różni się od przycisków funkcyjnych. W ramach eventu onMouseClicked ustawiamy parametry i ewentualnie wywołujemy funkcję zdefiniowaną w przycisku funkcyjnym. I to już cały kod – wystarczy uruchomić projekt klikając F6 w IDE. W efekcie dostajemy okienko w którym możemy przetestować nasz kalkulator

To tyle jeżeli chodzi o pierwsze wprawki w JavaFX.
Podsumowując – czego dziś dowiedziałem się o JavaFX?
• Jest językiem skryptowym który umożliwia, ale nie wymusza określanie typu zmiennych
• Struktura budowanego widoku opiera się na drzewie
• Najważniejsze elementy tego drzewa to Stage i Scene
• Pozwala tworzyć wiązania między zmiennymi a elementami GUI
• Umożliwia proste zarządzanie zdarzeniami (zwane eventami)
Język rozwija się dynamicznie – kolejne jego wersje wzbogacane są nie tylko o nowe komponenty lecz także o konstrukcje składniowe języka, a wszystko po to, by maksymalnie uprościć pisanie aplikacji z efektownym GUI.
Biorąc pod uwagę możliwość uruchamiania aplikacji JavaFX zarówno jako aplikacji desktopowych, serwerowych oraz mobilnych wróżę temu językowi dość jasną przyszłość.
Pozostaje zgłębiać dostępne klasy i mechanizmy, a gdy uda mi się stworzyć prostą aplikację web i uruchomić ją na serwerze nie omieszkam podzielić się tym doświadczeniem
Materiały dodatkowe:
Autor: Adam Andrzejewski


Dobry przykład na początek.
Technologia mało popularna, ale zapowiada się ciekawie. Mam nadzieję że Oracle jejj nie porzuci, bo zamierzam się w nia wdrozyć.
Należy mieć na uwadze, że w czasie tworzenia tego przykadu JavaFX była w wersji 1.2.1. Obecnie jest już 1.3 i nowsza wersja NetBeans, więc sam proces może wyglądać ciut inaczej. Sam program najprawdopodobniej też nie zadziała bez przekompilowania i być może jakiegoś refaktoringu na JavaFX1.3 – nie ma tu kompatybilności wstecz niestety…