JavaFX Language
Материал из JavaFX
Главная | Описание языка | API | Примеры | Инструменты Разработки | Новости | Ресурсы | Вопросы и ответы | Форум
Содержание |
[править] Установка языка JavaFX Script
[править] Установка JavaFX Script компилятора
- Загрузите последнюю версию компилятора archive.zip
- разархивируйте файл archive.zip
- добавьте к переменной PATH путь к директории archive/openjfx-compiler/dist/bin
В текстовом редакторе создайте файл HelloWorld.fx и скопируйте туда код примера:
import javafx.scene.*;
import javafx.scene.text.*;
import javafx.application.*;
Frame {
title: "Hello Frame"
width: 200
height: 100
stage: Stage {
content: Text {
x: 10, y: 30
content: "Hello World!"
font: Font { size: 24 style: FontStyle.PLAIN }
}
}
visible: true
}
Чтобы скомпилировать и запустить пример, наберите в командной строке:
> javafxc HelloWorld.fx
> javafx HelloWorld
На экране монитора у вас должно появится окошко с заголовком "Hello Frame" и надписью "Hello World!"
[править] Инструменты Разработки
Для программирования на языке JavaFX Script можно воспользоваться существующими средами разработки:
[править] Краткое введение в язык JavaFX Script
Рассмотрим возможности языка JavaFX Script на примере маленькой компании "Pond Corporation", которая занимается строительством прудов. Это могут быть пруды для отдыха, для разведения рыбы или для чего-нибудь еще.
[править] Переменные
Итак, компании "Pond Corporation" пришел заказ на изготовление овального пруда длиной 10 метров, шириной 5 метров и глубиной 2 метра. Заказчик сразу же попросил оценить, чему будет равен объем будущего пруда.
Директор компании "Pond Corporation" сразу же вызвал к себе главного программного архитектора и описал ему суть поставленной задачи. После недолгих поисков, программный архтектор нашел документацию по языку JavaFX Script и передал ее вместе с параметрами пруда главному программисту.
Первое, что понял главный программист, это то, что переменные в языке JavaFX Script задаются с помощью ключевого слова var:
var n = 5; // Переменная n имеет тип Integer, потому что 5 задано как целое число var radius = 10.0; // Переменная radius имеет тип Number, потому что 10.0 задано как число с дробной частью
Главный программист сразу взялся за дело, создал файл Main.fx и внес в него параметры пруда в качестве соответсвующих переменных:
var length = 10.0; // переменная length хранит значение длины пруда var width = 5.0; // переменная width хранит значение ширины пруда var depth = 2.0; // переменная depth хранит значение глубины пруда
Для расчета объема пруда, на ежедневном собрании, было предложено воспользоваться формулой, найденной на wikipedia сайте:
На языке JavaFX Script это описывается следующим образом:
var PI = 3.1415;
var radiusX = length / 2;
var radiusY = width / 2;
var h = depth;
var V = PI * radiusX * radiusY * h;
Чтобы распечать значение переменной, надо воспользоваться командой System.out.println(),
причем саму переменную надо заключить в фигурные скобки. Например:
import java.lang.System;
System.out.println("V = {V}");
Тогда конечная программа имеет вид:
import java.lang.System;
var length = 10.0;
var width = 5.0;
var depth = 2.0;
var PI = 3.1415;
var radiusX = length / 2;
var radiusY = width / 2;
var h = depth;
var V = PI * radiusX * radiusY * h;
System.out.println("V = {V}"); // V = 78.53750000000001
И вот конечный результат получен, объем пруда будет равняться 78.54 кубических метров .
[править] Функции
Компании "Pond Corporation" пришел заказ на постройку 2х овальных прудов: с песчаным берегом (sand pond) размерами 7 x 9 x 2 и травяным берегом (grass pond) размерами 8 x 9 x 3.
И опять необходимо посчитать объем каждого пруда.
Используя формулу для объема пруда мы получим следующий результат:
import java.lang.System;
var PI = 3.1415;
var sandPondVolume = PI * 7.0 / 2 * 9.0 / 2 * 2;
var grassPondVolume = PI * 8.0 / 2 * 9.0 / 2 * 3;
System.out.println("sand pond volume: {sandPondVolume}"); // sand pond volume: 98.957
System.out.println("grass pond volume: {grassPondVolume}"); // grass pond volume: 169.641
Вместо того, чтобы каждый раз переписывать формулу для вычисление объема пруда, перепишем ее один раз
в виде функции:
import java.lang.System;
function pondVolume(length: Number, width:Number, depth:Number){
var PI = 3.1415;
return PI * length / 2 * width / 2 * depth;
}
System.out.println("sand pond volume: {pondVolume( 7, 9, 2 )}"); // sand pond volume: 98.957
System.out.println("grass pond volume: {pondVolume( 8, 9, 3 )}"); // grass pond volume: 169.641
[править] Классы
Сразу несколько парков из Петродворца, Пушкина и Павловска заказали постройку прудов. И опять для каждого пруда необходимо вычислить его объем.
Можно поступить как и раньше,для каждого значения длины, ширины и глубины заводить свою переменную, но при этом количество переменных будет быстро возрастать ( 3 переменные для каждого пруда ) и при работе с ними будет очень легко их перепутать:
var petrodvoretsPondLength = 10.0;
var petrodvoretsPondWidth = 5.0;
var petrodvoretsPondDepth = 3.0;
var pushkinPondLength = 8.0;
var pushkinPondWidth = 7.0;
var pushkinPondDepth = 3.0;
var pavlovskPondLength = 9.0;
var pavlovskPondWidth = 5.0;
var pavlovskPondDepth = 3.0;
function pondVolume(length: Number, width:Number, depth:Number){
var PI = 3.1415;
return PI * length / 2 * width / 2 * depth;
}
var petrodvoretsPondVolume = pondVolume(petrodvoretsPondLength, petrodvoretsPondWidth, petrodvoretsPondDepth);
var pushkinPondVolume = pondVolume(pushkinPondLength, pushkinPondWidth, pushkinPondDepth);
var pavlovskPondVolume = pondVolume(pavlovskPondLength, pushkinPondWidth, pavlovskPondDepth);
System.out.println("Petrodvorets pond volume: {petrodvoretsPondVolume}");
System.out.println("Pushkin pond volume: {pushkinPondVolume}");
System.out.println("Pavlovsk pond volume: {pavlovskPondVolume}");
Результат выполнения программы:
Petrodvorets pond volume: 117.80625 Pushkin pond volume: 131.943 Pavlovsk pond volume: 148.435875
Задача: Найди в коде выше опечатку.
Создадим класс Pond, в котором будут храниться аттрибуты длина, ширина и глубина:
class Pond{
public attribute length:Number;
public attribute width :Number;
public attribute depth :Number;
}
Тогда весь код выше можно будет записать в более читабельной форме:
var petrodvoretsPond = Pond{
length: 10
width: 5
depth: 3
}
var pushkinPond = Pond{
length: 8
width: 7
depth: 3
}
var pavlovskPond = Pond{
length: 9
width: 5
depth: 3
}
Но вычисление объема пруда осталось все таким-же громоздким:
var pushkinPondVolume = pondVolume(pushkinPond.length, pushkinPond.width, pushkinPond.depth);
Чтобы этого избежать, добавим фукцию вычисления объема пруда в класс Pond:
class Pond{
public attribute length:Number;
public attribute width :Number;
public attribute depth :Number;
public function getVolume () {
var PI = 3.1415;
return PI * length / 2 * width / 2 * depth;
}
}
И тогда окончательная программа будет выглядеть следующим образом:
class Pond{
public attribute length:Number;
public attribute width :Number;
public attribute depth :Number;
public function getVolume () {
var PI = 3.1415;
return PI * length / 2 * width / 2 * depth;
}
}
var petrodvoretsPond = Pond{
length: 10
width: 5
depth: 3
}
var pushkinPond = Pond{
length: 8
width: 7
depth: 3
}
var pavlovskPond = Pond{
length: 9
width: 5
depth: 3
}
System.out.println("Petrodvorets pond volume: {petrodvoretsPond.getVolume()}");
System.out.println("Pushkin pond volume: {pushkinPond.getVolume()}");
System.out.println("Pavlovsk pond volume: {pavlovskPond.getVolume()}");
Результат выполнения программы:
Petrodvorets pond volume: 117.80625 Pushkin pond volume: 131.943 Pavlovsk pond volume: 106.025625
[править] Рисование Графики
Пакет javafx.scene.geometry содержит классы для рисования графики, такие как линия, окружность, эллипс, дуга, многоугольник и другие.
Чтобы нарисовать окружность, надо для атрибута content класса Stage определить класс Circle и для класса Circle перечислить его атрибуты: координаты цетра окружности, радиус, цвет.
Компания "Pond Corporation" решило создать приложение, которое будет рисовать поверхность пруда по его параметрам. Для этого надо создать объект Pond, нарисовать в приложении эллипс и атрибутам эллипса присвоить соответсвующие аттрибуты пруда:
[править] Создание Пользовательских Графических Компонент
Чтобы создать собственную графическую компоненту, надо расширить класс CustomNode и переопределить у него метод create().
Создадим класс PondNode у которого будут атрибуты scale и pond и который будет рисовать пруд в нашем приложении:
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.geometry.*;
class PondNode extends CustomNode{
public attribute scale:Number;
public attribute pond:Pond;
public function create () {
return Ellipse{
radiusX: pond.length / 2 * scale
radiusY: pond.width / 2 * scale
stroke: Color.DARKBLUE
fill: Color.LIGHTBLUE
}
}
}
Тогда приложение, изображающее пруд, можно будет переписать следующим образом:
[править] Связывание Данных
[править] Описание языка JavaFX Script
Смотри также документацию на английском языке: The JavaFX™ Script Programming Language
[править] Типы данных
[править] Базовые типы
В языке JavaFX Script существуют следующие примитивные типы:
- String
- Boolean
- Number
- Integer
Все они напрямую соотносятся со следующими примитивными типами и классами языка Java:
| JavaFX тип | Описание | Пример |
| String | Строка | "Hello World!" |
| Boolean | Логический тип | true, false |
| Integer | Целое число | 12 |
| Number | Вещественное число | 5.0 |
| Duration | Время | 12s // 12 секунд |
Поэтому можно использовать все те методы, которые есть у этих типов в языке Java
Примеры использования:
var s = "Hello"; // Создаем переменную типа String System.out.println(s.toUpperCase()); // распечатается строка: "HELLO"
var b = true; // Создаем переменную типа Boolean System.out.println(b.equals(true)); //распечатается строка: true System.out.println(b.equals(false)); //распечатается строка: false
var n = 1.5; // Создаем переменную типа Number System.out.println(n.intValue()); // распечатается строка: 1
[править] Последовательности
Последовательность (Sequence) в языке JavaFX Script содержит в себе набор элементов одного и того же типа.
В языке JavaFX Script все последовательности одномерные.
Для того, чтобы задать последовательность, нужно перечислить ее элементы через запятую в квадратных скобках:
var nums = [1,2,3,4,5]; var strings = ["one", "two", "three"];
Квадратные скобки служат указанием, что объявляемый аттрибут является последовательностью:
class List{
attribute 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];
System.out.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];
System.out.println(seq); // [ 1.0, 1.5, 2.0, 2.5 ]
Встроенные операции:
System.out.println( reverse nums ); // [ 5, 4, 3, 2, 1 ]
[править] Операторы
Математические операции:
| Оператор | Описание | Пример Использования |
| + | Сложить | 2 + 3 |
| - | Вычесть | 5 - 2 |
| * | Умножить | 2 * 2 |
| / | Разделить | 10 / 5 |
[править] Константы и переменные
[править] Переменные
Для объявления переменной используется синтаксис:
var имя_переменной[:тип_переменной] [= значение];
Пример использования:
import java.lang.System;
var radius = 10;
System.out.println("radius={radius}"); // результат: radius=10
var angle:Number = 45;
System.out.println("angle={angle}"); // результат: angle=45.0 // т.е angle имеет тип Number, а не Integer
[править] Классы
[править] Объявление класса
public class Animal{
}
[править] Объявление атрибутов и фукций
public class Animal{
public attribute name: String;
public function toString () { return "I am a {name}" }
}
[править] Инициализация объекта
Инициализация атрибутов:
public class Animal{
public attribute name: String = "unknown";
}
Ининциализация объекта с помощью блока init:
import java.lang.System;
public class Animal{
public attribute name: String = "unknown";
public function initAnimal() { System.out.println("[init] animal: {name}"); }
init{
initAnimal();
}
}
var animal = Animal{ name: "cat" }; // [init] animal: cat
Ининциализация объекта с использованием триггеров:
public class Animal{
public attribute name: String = "unknown" on replace{
initAnimal();
};
public function initAnimal() { System.out.println("[init] animal: {name}"); }
}
var animal = Animal{ name: "cat" }; // [init] animal: cat
[править] Абстрактные классы
Чтобы объявить абстрактный класс, нужно использовать ключевое слово abstract
например:
public abstract class Animal{
public attribute name: String;
public abstract function talk(): String;
}
[править] Наследование классов
Чтобы отнаследоваться от уже существующего класса, надо использовать ключевое слово extends
например:
public class Dog extends Animal {
override attribute name = "dog";
public function talk(): String { return "Bark!"; };
}
В языке JavaFX Script разрешено множественное наследование классов.
[править] Полный пример c использованием Классов
import java.lang.System;
public abstract class Animal{
public attribute name: String = "unknown" on replace{ initAnimal(); };
public function initAnimal() { System.out.println("[init] animal: {name}"); }
public abstract function talk(): String;
public function toString () { return name }
}
class Cat extends Animal{
override attribute name= "cat";
public function talk(): String { return "Meow!"; };
}
public class Dog extends Animal {
override attribute name = "dog";
public function talk(): String { return "Bark!"; };
}
var cat = Cat {}; // output: [init] animal: cat
var dog = Dog {}; // output: [init] animal: dog
var mouse = Animal{
name: "mouse"
public function talk() { return "Squeak!"; }
}
// output: [init] animal: mouse
System.out.println("{cat} : {cat.talk()}" ); // output: cat : Meow!
System.out.println("{dog} : {dog.talk()}" ); // output: dog : Bark!
System.out.println("{mouse}: {mouse.talk()}"); // output: mouse: Squeak!
[править] Функции
[править] Объявление функции
Снтаксис объявления функции:
function имя_фукции(список аргументов):тип_возвращаемого_значения { тело_фукции }
Функции в языке JavaFX Script позволяют как вычислить какое-нибудь значение, так и выполнить
определенный набор действий.
Пример объявления функции:
function square(n: Number):Number { return n * n; }
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) }
}
System.out.println("factorial(5) = {factorial(5)}"); // factorial(5) = 120
[править] Функция как самостоятельный тип данных
Функции в языке JavaFX Script являются отдельным типом данных. Их можно присваивать переменным:
var abs = function(x:Number):Number { if (x < 0 ) then -x else x }
System.out.println("abs( -3 ) = {abs( -3)}"); // abs( -3 ) = 3.0
[править] Базовые конструкции
[править] Оператор импорта import
import в JavaFX похож на import в Java, однако есть и сущесвенное отличие: import может встречатся в любом месте кода (не обязательно между package и class. В этом плане import напоминает required_once() из языка PHP. Кроме того есть интересная разновидность этого оператора позволяющая импортировать класс и назначить ему синоним, под которым этот класс будет "виден":
import java.awt.Color as AWTColor;
import javafx.ui.Color;
Таким образом в JavaFX решена проблема использования классов с одинаковыми именами в Java (например, совместное использования java.util.Date и java.sql.Date).
[править] Оператор связывания данных bind
В языке JavaFX определен оператор bind который позволяет связать переменную с определенным выражением. При этом изменение любой переменной из выражения также автоматически влечет изменение связанной с этим выраженим переменной.
Синтаксис оператора:
переменная = bind выражение
Пример использования оператора bind:
import java.lang.System;
function max(a:Number, b:Number):Number { if( a < b ) then b else a }
var a = 3;
var b = 4;
var maxAB = bind max(a,b);
System.out.println("max( {a}, {b} ) = {maxAB}"); // max( 3, 4 ) = 4.0
a = 5;
System.out.println("max( {a}, {b} ) = {maxAB}"); // max( 5, 4 ) = 5.0
b = 7;
System.out.println("max( {a}, {b} ) = {maxAB}"); // max( 5, 7 ) = 7.0
Как видно из примера, при изменении любой из переменных a или b автоматически изменяется и связанная с ними переменная maxAB
[править] Триггеры
Триггеры (triggers) используются для того, чтобы по определенным событиям (например изменение атрибута класса) можно было исполнять необходимые пользователю действия.
Пример:
import java.lang.System;
class A{
attribute hello: String on replace{
System.out.println("Hello {hello}!");
}
}
var a = A{ hello: "World" }; // Hello World!
class B{
attribute num: Number on replace oldValue = newValue{
System.out.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
выполняется последовательность действий, если условие не верно
}
Например фукция, которая вычисляет максимум двух чисел, может выглядеть следующим образом:
import java.lang.System;
function max(a:Number, b:Number):Number{
return if( a < b ) then b else a
}
System.out.println (max(3,5));
[править] Цикл for
Формат оператора:
for( <variable> in <sequence> ){
// Тело цикла
}
Пример цикла, который повторяется 100 раз:
for (i in [1..100]){
System.out.println("Iteration: {i}");
}
Операция indexof позволяет определить индекс итерируемой переменной в теле цикла:
import java.lang.System;
var animals = [ "cat", "dog", "mouse" ];
for(animal in animals){
System.out.println("animals[{indexof animal}] = {animal}");
}
Результат исполнения программы:
animals[0] = cat animals[1] = dog animals[2] = mouse
[править] Интеграция с языком Java
[править] Использование Java классов
В языке JavaFX Script можно напрямую использовать любые классы из языка Java.
Пример использования класса java.util.Date:
[править] Реализация Java интерфейсов
Пример реализации и использования интерфейса Runnable языка Java:
import java.lang.Thread;
import java.lang.Runnable;
import java.lang.System;
var runnable = Runnable{
public function run () {
System.out.println("Run...");
}
}
(new Thread(runnable)).start();
[править] Использование JavaFX UI компонентов в Java коде
Создание собственного JavaFX компонента:
import javafx.ui.*;
public class MyPanel extends CompositeWidget{
public function composeWidget():Widget{
return BorderPanel{
center: Label{ text: "Hello World!"}
}
}
}
Использование JavaFX UI компонентов в Java программе
import javax.swing.*;
public class MyFrame extends JFrame {
public MyFrame() {
setSize(300, 100);
JComponent myPanel = (new MyPanel()).getComponent();
getContentPane().add(myPanel);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() { new MyFrame().setVisible(true); }
});
}
}
[править] Вопросы и ответы
Задайте интересующий вас вопрос на Форуме или на странице Вопросы и Ответы.







