Technology
 

JavaFX Language

Материал из JavaFX

Главная | Описание языка | API | Примеры | Инструменты Разработки | Новости | Ресурсы | Форум

Внимание! Доступна документация по языку программирования JavaFX Script для версии JavaFX 1.0: Изучаем язык программирования JavaFX Script


Содержание

[править] Установка языка JavaFX Script

[править] Установка JavaFX SDK


В текстовом редакторе создайте файл HelloWorld.fx и скопируйте туда код примера:

import javafx.stage.*;

import javafx.scene.*;
import javafx.scene.text.*;
import javafx.scene.paint.*;
import javafx.scene.effect.*;


Stage {
    title: "Hello Frame"
    width: 250
    height: 80
    scene: Scene {
        content: Text {
            x: 10  y: 30
            font: Font { size: 24 }
            fill: Color.BLUE
            effect: DropShadow{ offsetX: 3 offsetY: 3}
            content: "Hello World!"
        }
    }
}


Чтобы скомпилировать и запустить пример, наберите в командной строке:

    > javafxc HelloWorld.fx
    > javafx  HelloWorld


На экране монитора у вас должно появится окошко с заголовком "Hello Frame" и надписью "Hello World!"

compiler_hello_world

[править] Инструменты Разработки

Для программирования на языке JavaFX Script можно воспользоваться существующими средами разработки:

[править] Краткое введение в язык JavaFX Script

Смотри краткое введение в язык JavaFX Script на примере компании Pond Inc

[править] Особенности языка JavaFX Script

[править] Декларативный синтаксис

В отличие от императивных языков, в которых описывается последовательность исполняемых действий, язык JavaFX Script позволяет описать структуру самой программы.


Создание программы на языке JavaFX Script можно разбить на 2 этапа

описание необходимых компонент (классов)
построение программы из существующих компонент

Сама программа строится по принципу:

пишем имя компонента
в фигурных скобках задаем атрибуты компонента
MyComponent{
   attribute1: value1
   attribute2: value2
   // ...
   attributeN: valueN

}


Атрибуты могут иметь простой тип (число, строка) или сложный.


MyComponent{
   attr1: SubComp1{
             subAttr1: value1
             // ...
          }
   // ...
   attrN: SubComp1{
             subAttr1: value1
             // ...
          }
}


Примеры:

UI интерфейс

Пример использования Картинка
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.text.*;
import javafx.scene.paint.*;
import javafx.scene.control.*;


var name = "";

Stage {
    title : "Hello World!"
    scene: Scene {
        width: 330
        height: 170
        content: [
            Text {
                font: Font{ size: 24 }
                x: 10, y: 30
                fill: Color.BLUE
                content: "Enter Name:"
            }
            TextBox {
                columns: 12
                translateX: 150
                translateY: 10
                font: Font{ size: 16 }
                text: bind name with inverse
            }
            Text {
                font: Font{ size: 24 }
                x: 10, y: 70
                fill: Color.GREEN
                content: bind "Hello {name}!"
            }
        ]
    }
}
Изображение:lang_ui.png


Структура данных


Язык JavaFX Script позволяет описывать данные аналогично тому, как это делается в XML

XML: contacts.xml JavaFX: Contacts.fx
<contact-list>
    <contact>
        <firstName> Mike </firstName>
        <lastName> Wazowski </lastName>
        <eMailAddress> 
              Mike.Wazowski@monster.com 
        </eMailAddress>
    </contact>
    <contact>
        <firstName> Sulley </firstName>
        <lastName> Monster </lastName>
        <eMailAddress> 
            Sulley.Monster@monster.com
        </eMailAddress>
    </contact>
</contact-list>
[ 
    Contact {
        firstName: "Mike"
        lastName: "Wazowski"
        eMailAddress: "Mike.Wazowski@monster.com"
    },
    Contact {
        firstName: "Sulley"
        lastName: "Monster"
        eMailAddress: "Sulley.Monster@monster.com"
    }
]





Описав класс Contact на языке JavaFX Script вы сможете скомпилировать файл Contacts.fx (компилятор проверит все ошибки), загрузить данные из этого файла в вашу программу и использовать их.

Пример:


class Contact{
    var firstName: String;
    var lastName: String;
    var eMailAddress: String;
}

var contacts = loadFXCode("Contacts");

for(contact in contacts){
    println("{contact.firstName} {contact.lastName} has {contact.eMailAddress} email address");
}

Результат исполнения программы:

 Mike Wazowski has Mike.Wazowski@monster.com email address
 Sulley Monster has Sulley.Monster@monster.com email address



Система, состоящая из компонент


Пример использования Картинка
ElectroScheme{
    var wire1 = Wire{}
    var wire2 = Wire{}
    var wire3 = Wire{}

    components:[
    Lamp{
        pos: XY{ x: 160  y: 25}
        pin1: wire1.pin2
        pin2: wire3.pin1
    },
    Battery{
        pos: XY{ x: 100  y: 120}
        pin1: wire2.pin2
        pin2: wire1.pin1
    },Switch{
        pos: XY{ x: 180  y: 105}
        pin1: wire3.pin2
        pin2: wire2.pin1

    },
  ]
}
Изображение:Electronic_simulator_off.png

[править] Связывние данных

[править] Прямое использование классов языка Java

[править] Программы на JavaFX Script и других языках

[править] Hello World

JavaFX Script


Пример использования Картинка
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;

import javafx.scene.layout.Flow;

Stage {
    title : "Hello World!"
    scene: Scene {
        width: 200
        height: 50
        content: Flow{
            content: Label {
                text: "Hello World!"
            }
        }
    }
}
Изображение:lang_jfx_helloworld.png


Java

Создание Hello World из готовых компонент:

Пример использования Картинка
import java.awt.*;
import javax.swing.*;

public class HelloWorld {

    public static void main(String[] args) {

        JFrame frame = new JFrame("Hello World!");
        frame.setSize(200, 70);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel(new FlowLayout());
        panel.add(new JLabel("Hello World!"));

        frame.getContentPane().add(panel);
        frame.setVisible(true);
        
    }
}

Изображение:Lang_java_helloworld.png

Расширение класса JFrame:

Пример использования Картинка
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class HelloFrame extends JFrame {

    public HelloFrame(){

        setTitle("Hello World!");
        setSize(200, 70);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JPanel panel = new JPanel(new FlowLayout());
        panel.add(new JLabel("Hello World!"));

        getContentPane().add(panel);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new HelloFrame().setVisible(true);
            }
        });
    }

}
Изображение:Lang_java_helloworld.png


[править] Обработка событий

JavaFX Script


Пример использования Картинка
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Flow;
import javafx.scene.control.Button;


Stage {
    title : "Button Example!"
    scene: Scene {
        width: 200
        height: 50
        content: Flow{
            content: Button {
                text: "Press Me!"
                action: function () {
                    println("Button Pressed!");
                }
            }
        }
    }
}
Изображение:lang_jfx_actionevent.png


Java

Пример использования Картинка
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class ButtonExample extends JFrame {

    public ButtonExample(){

        setTitle("Button Example!");
        setSize(250, 70);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JPanel panel = new JPanel(new FlowLayout());
        JButton button = new JButton("Click Me!");

        button.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e) {
                    System.out.println("Button Pressed!");
                }
            }
        );

        panel.add(button);

        getContentPane().add(panel);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ButtonExample().setVisible(true);
            }
        });
    }

}
Изображение:Lang_java_actionevent.png

[править] Описание языка JavaFX Script

Смотри также документацию:


[править] Main файл

 println("Hello World!");


import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;


Stage {
    title: "Hello World!"
    scene: Scene {
        content: Text {
                x: 10, y: 30
                font : Font { size: 24 }
                content: "Hello World!"
            }
    }
}

[править] Метод run

function run(){
    println("Hello world!");
}

[править] Передача параметров

Способ 1

function run(args:String[]){
    for(arg in args){
        println("arg: {arg}");
    }
}


Способ 2

http://blogs.sun.com/rakeshmenonp/entry/javafx_passing_arguments


 println("Argument {FX.getArgument( "key" )}");


Передача аргумента из командной строки:

 javafx -cp FXArguments.jar fxarguments.Main key="From Command Line"


Передача аргумента из апплета:

<script src="http://dl.javafx.com/1.2/dtfx.js"></script>
<script>
    javafx(
        {
              archive: "FXArguments.jar",
              draggable: true,
              width: 250,
              height: 80,
              code: "fxarguments.Main",
              name: "FXArguments",
              key: "from Applet"
        }
    );
</script> 


Форум Чтоб грамотно работало во всех браузерах, нужно делать так:

<script src="http://dl.javafx.com/dtfx.js"></script>
<script>
    javafx(
        {
              archive: "MyApplication.jar",
              draggable: true,
              width: 300,
              height: 400,
              code: "mypackage.Main",
              name: "Sample Application"
        },
        {
              test: "test_value"     
        }
    );
</script>

[править] Типы данных

[править] Базовые типы

В языке JavaFX Script существуют следующие примитивные типы:

Логический тип

  • Boolean

Символьный тип

  • Character
  • String

Целые числа

  • Byte
  • Short
  • Integer
  • Long

Числа с плавающей точкой

  • Float (Number)
  • Double

Время

  • Duration


JavaFX тип Описание Пример
Boolean Логический тип true, false
Character Символ
String Строка "Hello World!"
Byte Байт 10
Short Короткое целое число 12
Integer Целое число 12
Long Длиное целое число 12
Float Вещественное число 5.0
Double Вещественное число с двойной точностью 10.0
Duration Время 12s // 12 секунд

Поэтому можно использовать все те методы, которые есть у этих типов в языке Java

Примеры использования:

   var s = "Hello";   // Создаем переменную типа String
   println(s.toUpperCase());  // распечатается строка: "HELLO"
   var b = true;    // Создаем переменную типа Boolean
   println(b.equals(true));  //распечатается строка: true
   println(b.equals(false)); //распечатается строка: false
   var n = 1.5;   // Создаем переменную типа Number
   println(n.intValue());  // распечатается строка: 1

[править] Функции

Объявление функции:

function sqr(x:Number):Number { x * x };

println("sqr(3) = {sqr(3)}"); // output: sqr(3) = 9.0


Функции являются отдельным типом данных.

Например, переменной можно присвоить функцию:

var f = function(x:Number):Number {  x * x };

println("f(3) = {f(3)}"); // output: f(3) = 9.0

Класс может иметь атрибут типа функция:

class TaskManager{
    var task:function();
}


Функцию можно передавать в качестве аргумента другой функции

import java.lang.Math;

function f(x:Number):Number{ Math.cos(x) }

function integral( f: function(Number):Number, a:Number, b: Number, dx: Number):Number{
    var s = 0.0;
    for(x in [a..b step dx]){ 
        s += f(x) * dx;
    }
    s -= 0.5 * f(a) * dx + 0.5 * f(b) * dx;
    return s;
}

println( integral(f, -Math .PI / 2, Math.PI / 2, 0.01) );

[править] Последовательности

Последовательность (Sequence) в языке JavaFX Script содержит в себе набор элементов одного и того же типа.

В языке JavaFX Script все последовательности одномерные.

Для того, чтобы задать последовательность, нужно перечислить ее элементы через запятую в квадратных скобках:

  var nums = [1,2,3,4,5];
  var strings = ["one", "two", "three"];

Квадратные скобки служат указанием, что объявляемый аттрибут является последовательностью:

class List{
    public var  items: String[];
}

var list = List{ items: ["item1", "item2", "item3"]  };


Последовательности можно вкладывать друг в друга, получая при этом один общую последовательность:

  var week_days = ["Mon","Tue","Wed","Thur","Fri"];
  var      days = [week_days, ["Sat","Sun"] ];

Результатом будет последовательность: ["Mon","Tue","Wed","Thur","Fri","Sat","Sun"];

Нумерация последовательностей производится от 0.

Получение элемента последовательности по индексу:

  var numbers = ["zero","one", "two", "three"];
  var n1 = numbers[1]; // n1 = "one"
  var n2 = numbers[2]; // n2 = "two"

Получение размера последовательности:

  var numbers = ["zero","one", "two", "three"];
  var size = sizeof numbers;  // size = 4


Выборка элементов последовательности:

var nums = [1,2,3,4,5];
println(nums[n|n > 2]); // [ 3, 4, 5 ]

Вставка и удаление элементов последовательности:

var seq = [1.0, 2.0, 3.0];

insert 1.5 after  seq[0];  // [1.0, 1.5, 2.0, 3.0]
insert 2.5 before seq[3];  // [1.0, 1.5, 2.0, 2.5, 3.0 ]

delete seq[4];

println(seq); // [ 1.0, 1.5, 2.0, 2.5 ]

Встроенные операции:

println( reverse nums ); // [ 5, 4, 3, 2, 1 ]

Итерация последовательности:

var seq = [1, 2, 3, 4, 5];


for(elem in seq){
    println(elem);
}


var sqrSeq = for(n in seq) { n * n };


Сортировка последовательности:

import javafx.util.Sequences;

var sequence = [ 5, 2, 3, 1, 4 ];

var sortedSequence = Sequences.sort(sequence) as Integer[];

println(sortedSequence); // [ 1, 2, 3, 4, 5 ]


Сортировка с помощью Comparator-а:

class Vector{
    public var x:Number;
    public var y:Number;

    public function length () {  Math.sqrt( x * x + y * y) }
    public override function toString ():String { "[ {x}, {y}]" }
}

var vectors = [ Vector{ x: 0 y: 2}, Vector{ x: 1 y: 0}, Vector{ x: 1 y: 1} ];


var sortedVectors = Sequences.sort(vectors, Comparator{
                public override function compare(obj1 : Object, obj2 : Object): Integer{
                    var v1 = (obj1 as Vector);
                    var v2 = (obj2 as Vector);
                    var delta = v2.length() - v1.length();
                    if (delta == 0 ) { 0 } else if ( delta < 0 ) { 1 } else { -1 } ;
                }
            }
        ) as Vector[];


println(sortedVectors); // [ [ 1.0, 0.0], [ 1.0, 1.0], [ 0.0, 2.0] ]

Описние устройства последовательностей:

http://per.bothner.com/blog/2009/JavaFX-sequence-basics
http://per.bothner.com/blog/2009/JavaFX-unboxed-sequences
http://per.bothner.com/blog/2009/JavaFX-sequence-updating
http://per.bothner.com/blog/2009/JavaFX-sequence-triggers


[править] Перечисляемые типы

В языке JavaFX Script нет собственных перечислимых типов данных, но их можно использовать из Java.


Day.java

public enum Day {
    SUNDAY,
    MONDAY,
    // ...        
}


Использование перечислимого типа:

Main.fx

var day = Day.SUNDAY;

var days = Day.values();

for(d in days){
    println("day: {d}");
}

[править] Операторы

Математические операции:

Оператор Описание Пример Использования
+ Сложить 2 + 3
- Вычесть 5 - 2
* Умножить 2 * 2
/ Разделить 10 / 5

[править] Константы и переменные

[править] Константы

Константы задаются с помощью ключевого слова def:

  def PI = 3.1415;


[править] Переменные

Для объявления переменной используется синтаксис:

 var имя_переменной[:тип_переменной] [= значение]; 

Пример использования:

var radius = 10;
println("radius={radius}"); // результат: radius=10

var angle:Number = 45;
println("angle={angle}");  // результат: angle=45.0  // т.е angle имеет тип Number, а не Integer

[править] Классы

[править] Объявление класса

public class Cat{
}

[править] Объявление атрибутов и функций

public class Cat {
    var name:String;
    public function talk(): String { return "Meow!"; };
}


Статические атрибуты и функции объявляются вне класса:

public var quantity = 0;

public class Animal {
    init{ quantity++ }
}

[править] Инициализация объекта

Инициализация атрибутов:

class Cat {
    var name:String = "Pushok";
}


Ининциализация объекта с помощью блока init:

class Cat {
    var name:String;

    init{
        name = "Pushok"
    }
}

var cat = Cat{ };
println("Cat name is {cat.name}"); // Cat name is Pushok

Ининциализация объекта с использованием триггеров:

class Cat{

    public var name: String on replace{
        if(name == null){ name = "unknown" }
    };

}

Cat{ };  // name: unknown

[править] Абстрактные классы

Чтобы объявить абстрактный класс, нужно использовать ключевое слово abstract

например:

public abstract class Animal{
    public var name: String;
    public abstract function talk(): String;
}

[править] Наследование классов

Чтобы отнаследоваться от уже существующего класса, надо использовать ключевое слово extends

например:

public  class Dog extends Animal {
    override var name = "dog";
    public override function talk(): String { "Bark!"; };
}

В языке JavaFX Script разрешено множественное наследование классов.

[править] Полный пример c использованием Классов

abstract class Animal{

    public var name: String = "unknown";

    public abstract function talk(): String;
    public override function toString () { name }

    init{
        println("[init] animal: {this}");
    }

}


class Cat extends Animal{
    override var name= "cat";
    override function talk(): String {  "Meow!"; };
}

class Dog extends Animal {
    override var  name = "dog";
    override function talk(): String {  "Bark!"; };
}


var cat = Cat {};  // output: [init]  animal: cat
var dog = Dog {};  // output: [init]  animal: dog



var mouse = Animal{
    name: "mouse"
    override function talk() {  return "Squeak!"; }
}
// output: [init]  animal: mouse


println("{cat}  : {cat.talk()}"  ); // output: cat  : Meow!
println("{dog}  : {dog.talk()}"  ); // output: dog  : Bark!
println("{mouse}: {mouse.talk()}"); // output: mouse: Squeak!

[править] Функции

[править] Объявление функции

Снтаксис объявления функции:

 function имя_фукции(список аргументов):тип_возвращаемого_значения { тело_фукции }


Функции в языке JavaFX Script позволяют как вычислить какое-нибудь значение, так и выполнить определенный набор действий.

Пример объявления функции:

  function square(x: Number):Number { x * x }
  function hello(name: String){
     System.out.println("Hello {name}!");
  }

Пример вызова функций:

  var a = square(2);
  println("square(3)={square(3)}"); // square(3)=9.0
  hello("Peter");  //  Hello Peter!

[править] Рекурсивные функции

Так же можно определять рекурсивные функции:

 function factorial(n: Integer):Integer{
   return if ( n == 0 ) then { 1 } else { n * factorial(n - 1) }
 }
 println("factorial(5) = {factorial(5)}"); // factorial(5) = 120

[править] Функция как самостоятельный тип данных

Функции в языке JavaFX Script являются отдельным типом данных. Их можно присваивать переменным:

var abs = function(x:Number):Number { if (x < 0 ) then -x else x }

println("abs( -3 ) = {abs( -3)}"); // abs( -3 ) = 3.0

[править] Базовые конструкции

[править] Оператор импорта import

import в JavaFX похож на import в Java, однако есть и сущесвенное отличие: import может встречатся в любом месте кода (не обязательно между package и class. В этом плане import напоминает required_once() из языка PHP.

  import javafx.scene.shape.Circle;

Кроме того, в интепретируемой версии языка JavaFX Script была интересная разновидность этого оператора, позволяющая импортировать класс и назначить ему синоним, под которым этот класс будет "виден":

  import java.awt.Color as AWTColor;
  import javafx.scene.paint.Color;

Таким образом в JavaFX решалась проблема использования классов с одинаковыми именами в Java (например, совместное использования java.util.Date и java.sql.Date). Такую же возможность планируется реализовать и в компилируемой версии языка JavaFX Script.

[править] Оператор связывания данных bind

В языке JavaFX определен оператор bind который позволяет связать переменную с определенным выражением. При этом изменение любой переменной из выражения также автоматически влечет изменение связанной с этим выраженим переменной.

Синтаксис оператора:

 переменная = bind выражение 

Пример использования оператора bind:

function max(x:Number, y:Number):Number { if( x < y ) then y else x }

var a = 3;
var b = 4;
var maxAB = bind max(a,b);

println("max( {a}, {b} ) = {maxAB}"); // max( 3, 4 ) = 4.0

a = 5;

println("max( {a}, {b} ) = {maxAB}"); // max( 5, 4 ) = 5.0

b = 7;

println("max( {a}, {b} ) = {maxAB}"); // max( 5, 7 ) = 7.0

Как видно из примера, при изменении любой из переменных a или b автоматически изменяется и связанная с ними переменная maxAB

[править] Триггеры

Триггеры (triggers) используются для того, чтобы по определенным событиям (например изменение атрибута класса) можно было исполнять необходимые пользователю действия.


Пример:

class A{
    var hello: String on replace{
        println("Hello {hello}!");
    }
}

var a = A{ hello: "World" }; //  Hello World!

class B{
    var num: Number on replace oldValue = newValue{
        println("old value {oldValue} has been changed to new value {newValue}");
    }
}


var b = B{ num: 10 }; // old value 0.0 has been changed to new value 10.0
b.num = 20;           // old value 10.0 has been changed to new value 20.0

[править] Условная конструкция if

Формат конструкции:

  if (<условие>) then {
     выполняется последовательность действий, если условие верно
  } else 
    выполняется последовательность действий, если условие не верно
  }

Например фукция, которая вычисляет максимум двух чисел, может выглядеть следующим образом:

function max(x:Number, y:Number):Number{
    if( x < y ) then y else x
}

println (max(3,5));

[править] Цикл for

Формат оператора:

for( <variable> in <sequence> ){
    // Тело цикла
}


Пример цикла, который повторяется 100 раз:

 for (i in [1..100]){
   println("Iteration: {i}");
 }


Операция indexof позволяет определить индекс итерируемой переменной в теле цикла:

var animals = [ "cat", "dog", "mouse" ];

for(animal in animals){
    println("animals[{indexof animal}] = {animal}");
}

Результат исполнения программы:

  animals[0] = cat
  animals[1] = dog
  animals[2] = mouse

[править] Асинхронный вызов методов

[править] Асинхронный вызов Java методов

http://blogs.sun.com/clarkeman/entry/javafx_async_task

MyRunnableFuture.java

import javafx.async.RunnableFuture;

public class MyRunnableFuture implements RunnableFuture{

    public void run() throws Exception {
        System.out.println("Call Java Methods!");
    }

}

Main.fx

import javafx.async.JavaTaskBase;
import javafx.async.RunnableFuture;


var task = JavaTaskBase{
    
    override function create():RunnableFuture{
        new MyRunnableFuture();
    }

}

task.start();

[править] Асинхронный вызов JavaFX кода I

JavaRunnableFuture.java

import javafx.async.RunnableFuture;

public class JavaRunnableFuture implements RunnableFuture {

    RunnableFuture runnable;

    public JavaRunnableFuture(RunnableFuture runnable){
        this.runnable = runnable;
    }

    @Override
    public void run() throws Exception {
        System.out.println("Call Java Methods!");
        runnable.run();
    }
    
}


Main.fx

JavaTaskBase{
    override function create():RunnableFuture{
        new JavaRunnableFuture(
            RunnableFuture{
                override function run():Void  {
                    println("Call Java Methods!");
                }
            }
        );
    }

}.start();

[править] Асинхронный вызов JavaFX кода II

AsyncProgramMoveImpl.java

import javafx.async.*;
import com.sun.javafx.runtime.async.*;


public class AsyncProgramMoveImpl extends AbstractAsyncOperation{
    RunnableFuture runnable;

    AsyncProgramMoveImpl(RunnableFuture runnable, AsyncOperationListener listener) {
        super(listener);
        this.runnable = runnable;
    }

    @Override
    public Object call() throws Exception {
        runnable.run();
        return null;
    }
}


JavaFXTaskBase.fx

import javafx.async.Task;
import javafx.async.RunnableFuture;
import com.sun.javafx.runtime.async.AsyncOperationListener;

import java.lang.Exception;


public class JavaFXTaskBase extends Task {

    var peer: AsyncProgramMoveImpl;

    public var action:function();

    public override function start() : Void{
     if (peer == null) {
          peer = new AsyncProgramMoveImpl(RunnableFuture{ override function run(){ action() } }, asyncListener );
          peer.start();
        }
    }

    public override function stop() : Void{
    }

    var asyncListener = AsyncOperationListener {
        public override function onProgress(progressValue:Integer, progressMax:Integer):Void {}
        public override function onCompletion(value:Object):Void {}
        public override function onCancel():Void {}
        public override function onException(e:Exception):Void{}
   }
}


Main.fx

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;

Stage {
    title: "Application title"
    scene: Scene {
        content: Button {
            text: "Asynch Operation"
            action: function() {
                JavaFXTaskBase{
                    action: function(){
                        while(true){
                            println("infinty loop!");
                        }
                    }
                }.start();
            }
        }
    }
}

[править] Интеграция с языком Java

[править] Использование Java классов

В языке JavaFX Script можно напрямую использовать любые классы из языка Java.

Пример использования класса java.util.Date:

Пример использования Картинка
import java.util.Date;
import javafx.ext.swing.*;


var date = new Date();

SwingFrame {
    title: "Calendar"
    width: 200
    height: 70
    content: FlowPanel {
        content: Label{ text: "Date: {%tF date}"  }
    }
    visible: true
}
Изображение:Calendar.png

[править] Реализация Java интерфейсов

Пример реализации и использования интерфейса FileFilter языка Java:

import java.io.*;

var imagesDir: File = new File ("resources");

var imageFiles: File[] = imagesDir.listFiles( FileFilter{
        override function accept(pathname:File){
            not pathname.getName().endsWith("Thumbs.db");
        }
    }
);


Пример реализации и использования интерфейса Runnable языка Java:

import java.lang.Thread;
import java.lang.Runnable;

var runnable = Runnable{
    public override function run () {
        println("Run...");
    }
}

new Thread(runnable).start();

[править] Декларативный синтаксис

[править] Дерево программы

import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;


Stage {
    title: "JavaFX Tree"
    scene: Scene {
        width: 300
        height: 300
        content: [
            Group{
                translateX: 50
                translateY: 100
                content:[
                    Rectangle{
                        width: 100
                        height: 100
                        fill: Color.BLUE
                    }
                    Circle{
                        radius: 50
                        fill: Color.GREEN
                    }
                ]
            }
            Group{
                translateX: 150
                translateY: 100
                rotate: 45
                content: [
                    Polygon {
                            points : [ 0,0, 100,0, 100,100 ]
                            fill: Color.ORANGE
                    }

                ]
            }

        ]
    }
}

[править] Получение доступа к элементу в дереве программы

[править] Связывание данных

import javafx.scene.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.control.*;


var radius = 50.0;

Scene {
    width: 200
    height: 200
    content: [
        Slider {
            min: 10
            max: 100
            value: bind radius with inverse
        }
        Circle {
            centerX: 100, centerY: 100
            radius: bind radius
            fill: Color.ORANGE
        }
    ]
}

[править] Получение объекта по имени переменной

import javafx.scene.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.input.*;
import javafx.scene.control.*;


var circle:Circle;

Scene {
    width: 200
    height: 200
    content: [
        circle = Circle {
            centerX: 100
            centerY: 100
            radius: 40
            fill: Color.GREEN
            onMouseEntered: function( e: MouseEvent ):Void {
                circle.fill = Color.ORANGE;
            }
            onMouseExited: function( e: MouseEvent ):Void {
                circle.fill = Color.GREEN;
            }
         }
         Button{
            text: "Set Blue color"
            action: function(){
                circle.fill = Color.BLUE;
            }

         }

    ]
}

[править] Получение объекта по id в дереве

import javafx.scene.*;
import javafx.stage.*;
import javafx.scene.layout.*;
import javafx.scene.control.*;

def stage : Stage = Stage {
    title: "Application title"
    width: 300
    height: 300
    scene: Scene {
        content: VBox {
            content: [
                Button {
                    text: "Set default text"
                    action: function() {
                        var t : TextBox = stage.scene.lookup("textBoxID") as TextBox;
                        t.text = t.promptText;
                    }

                }
                TextBox {
                    id: "textBoxID"
                    promptText: "First name"
                }

            ]
        }
    }
}

[править] Каскадные Таблицы стилей

Более подробно о каскадных таблицах стилей можно узнать на страничке: Каскадные Таблицы Стилей


Язык JavaFX Script позволяет изменять свойства компонент программы не изменяя при этом саму программу. Для этого надо создать файл с расширение css и в нем описать имя компонента и его новое занчение свойства.

Например JavaFX Script программа рисует круг:

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

Stage {
    title: "Application title"
    scene: Scene {
        width: 200
        height: 200
        stylesheets: ["{__DIR__}Style.css"]
        content: Circle {
            centerX: 100
            centerY: 100
            radius: 50
            fill: Color.ORANGE
            stroke: Color.GREEN
        }
    }
} 

С помощью css файла можно поменять свойства этого круга, например прозрачность и цвет (файл Style.css):

Circle {
    opacity: 0.5;
    fill: yellow;
}

[править] Локализация

[править] Локализационные файлы

Файл: Main.fx

import java.util.Locale;
import javafx.ext.swing.SwingLabel;
import javafx.scene.Scene;
import javafx.stage.Stage;

Locale.setDefault(new Locale("ru"));

Stage{
    title: ##"Frame"
    scene: Scene{
        content: SwingLabel{
            text: ##"Hello"
        }
    }
    visible: true
}

Файл: Main_ru.fxproperties

 "Frame"="Окно"
 "Hello"="Привет"

[править] Порядок слов в локализированной строке

Пусть нелокализованная строка в коде использует переменные:

var name1 = ##"Peter";
var name2 = ##"John";

var hello = ##"Hello {name1} and {name2}";

тогда строка в локализационном файле будет выглядеть следующим образом:

 "Peter"="Петр"
 "John"="Джон"
 "Hello %s and %s" = "Привет %s и %s"


Где "s" обозначает, что переменная передается в виде строки.

Если надо переменные вывести в другом порядке, тогда можно использовать номер переменной:

 "Hello %s and %s" = "Привет %2$s и %1$s"

Подробнее о способах форматированния данных можно изнать из документации по файлу java.util.Formatter


[править] Storage API

import javafx.io.Storage;
import java.lang.StringBuffer;
import java.io.DataInputStream;
import java.io.DataOutputStream;


var entry = Storage {
    source: "myresource"
}

var resource = entry.resource;



var dataOutputStream = new  DataOutputStream(resource.openOutputStream(true));
dataOutputStream.writeChars("name = Petr");
dataOutputStream.close();

var buff = new StringBuffer();

var dataInputStream = new DataInputStream(resource.openInputStream());

var line = dataInputStream.readLine();

while(line != null){
    buff.append(line);
    line = dataInputStream.readLine();
}

dataInputStream.close();

var content = buff.toString();

println("content: {content}");

println(entry.list());

[править] Вопросы и ответы

Задайте интересующий вас вопрос по языку JavaFX Script