Mamy już za sobą pierwsze spotkanie z JavaFX. Omówiłem już podstawowe zasady pracy i wdrożenia appletów FX. Dziś popatrzymy dokładniej na kolejne dwa zagadnienia.
Pierwsze z nich to tworzenie własnych komponentów graficznych poprzez rozszerzenie klasy CustomNode. Nasza klasa będzie wyglądała tak:

Listing 1. Kod klasy TimerLabel, rozszerza ona CustomNode

/*
 * TimerLabel.fx
 */

package pl.koziolekweb.fxtimer;

import java.lang.System;
import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.input.MouseEvent;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;

/**
 * @author koziolek
 */

public class TimerLabel extends CustomNode {

    var title : Text = Text{
        content: "Aktualny czas";
        font: Font{
            size: 12;
            name: "Aral";
        }
        fill: Color.web("#DDAA77");
        y: 15;
        x: 10;
    }

    public var time: Text = Text{
        font: Font{
            size: 15;
            name: "Freestyle Script";
        }
        fill: Color.web("#fff");
        y: 35;
        x: 10;
    }

    public override function create() : Node {
        return Group {
            content: [
                Group {
                    content: [
                        title,
                        time
                    ]
                }
            ]
        };
    }
}

Nasz obiekt graficzny będzie zawierał dwa elementy. Pierwszy będzie to prywatny tekst „tytułowy” drugi będzie zawierał dynamicznie generowany tekst. Zdziwić może was brak słowa kluczowego private, ale w JavaFX Script (JFXS) domyślnym poziomem dostępu jest właśnie dostęp prywatny. Kolejną ciekawostka jest słowo kluczowe override, które sygnalizuje nadpisanie danej funkcji w klasie rozszerzającej. Odpowiada ono adnotacji @Override w Javie.
Celem naszej aplikacji będzie, na razie, stworzenie cyfrowego zegarka. Mamy już napisany kod dla „wyświetlacza”, czas zająć się czasem.
JFXS posiada ciekawą funkcjonalność nazywaną linią czasu (ang. Timeline). Działa ona bardzo podobnie jak ta we Flashu. James Weaver opisał to przy okazji tworzenia tetrisa. Odsyłam do tego pana po szczegóły. Sam skrócę o co w tym chodzi. Animacja jest krótko mówiąc funkcją przyporządkowującą pewnej chwili czasu T pewien obraz. Jeżeli Oś czasu uznamy za ciągłą (w rzeczywistości jest ona dyskretna, stąd pojęcie fps – frames per second) to można wyznaczyć na niej pewne punkty. Punkty te nazywamy klatkami kluczowymi. Jeżeli dla danego obiektu graficznego zdefiniujemy stan w klatce kluczowej K1, które to odpowiada pewnej chwili czasu t0, i w klatce kluczowej K2, czas t1, to animacją będzie ciąg obrazów który prowadzi obiekt graficzny ze stanu K1 do stany K2. Proste, prawda? Klatki kluczowe w JFXS mogą występować jako klatki „snapshot”, czyli zawierać stan docelowy obiektu w danej chwili. Mogą też być klatkami „tick”, które odpowiadają tykaniu zegara. Obliczenia w nich zawarte będą wykonywane co pewien czas. Klatki drugiego rodzaju są prostsze w zrozumieniu więc zajmiemy się nimi w tym przykładzie. Tworzenie animacji to kolejny krok. Kod sceny głównej programu oraz kod naszej belki czasu:

Listing 2. Kod programu

/*
 * Main.fx
 */

package pl.koziolekweb.fxtimer;

import java.util.GregorianCalendar;
import javafx.animation.*;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.scene.input.MouseEvent;

/**
 * @author koziolek
 */

var sek: Integer;
var min: Integer;
var godz: Integer;

var timerlabel = new TimerLabel();

var timeline = Timeline{
    repeatCount: Timeline.INDEFINITE
    keyFrames: [
        KeyFrame {
            time: 1s;
            canSkip: true;
            action: function(){
                var date = GregorianCalendar.getInstance();
                sek = date.getTime().getSeconds();
                min = date.getTime().getMinutes();
                godz = date.getTime().getHours();
                if(sek 
<p>W naszym przypadku istotnym elementem jest pole <samp>repeatCount</samp> klasy <samp>Timeline</samp>. Przekazanie mu stałej <samp>INDEFINITE</samp> powoduje, że nasza animacja będzie odtwarzana w nieskończoność. W ten sposób stworzyliśmy też animację typu "tick", jej najważniejszą cechą jest to, że ma jedną klatkę.<br></br>
Po prawej stronie przykład. </p>