Sun Java Solaris Communities My SDN Account Join SDN
 
Изучаем язык программирования JavaFX Script

Урок 8: Привязка данных и триггеры

Documentation Distribution Policy  
« Предыдущий 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Следующий »
 

Привязка данных, или способность создавать непосредственную связь между двумя переменными, является одной из ключевых возможностей языка программирования JavaFX Script. Этот урок начинается со связывания двух простых переменных и переходит к более сложному связыванию: переменной и значения функции или выражения. Как только вы поймете идею, познакомьтесь с Applying Data Binding to UI Objects, уроком в Building GUI Applications with JavaFX, в котором показано, каким мощным инструментом может быть механизм привязки данных при построении приложений JavaFX.

Триггер замены представляет собой блок кода, который связан с переменной: когда переменная изменяется, код автоматически выполняется. Приводится практический пример триггера замены.

 
Содержание
 
Обзор механизма привязки
Привязка и объекты
Привязка и функции
Привязка данных в последовательностях
Триггеры замены
 
Обзор механизма привязки

Зарезервированное слово bind связывает значение некоторой переменной со значением связываемого выражения. Связывамое выражение может быть простой переменной основного типа, объектом, функцией или каким-либо выражением. В следующих частях приводятся примеры для каждого из них.

Привязка и объекты

В большинстве реальных ситуаций в программировании вы будете использовать привязку данных для синхронизации графического интерфейса пользователя (GUI) приложения с лежащими в его основе данными. (Программирование GUI обсуждается в JavaFX GUI Tutorial; здесь же мы рассматриваем основные принципы с некоторыми примерами.)

Давайте начнем с простого: следующий скрипт привязывает переменную x к переменной y, изменяет значение переменной x, а затем печатает значение y. Поскольку переменные связаны, значение переменной y автоматически обновляется.

var x = 0;
def y = bind x;
x = 1;
println(y); // y now equals 1
x = 47;
println(y); // y now equals 47

Обратите внимание, что мы объявили переменную y как def. Тем самым, никакой код не может прямо присвоить значение переменной y, и в то же время значение y разрешается менять с использованием оператора bind. Используйте точно такое же соглашение, применяя привязку к объекту (напомним, что мы ввели объект Address в уроке Using Objects):

var myStreet = "1 Main Street";
var myCity = "Santa Clara";
var myState = "CA";
var myZip = "95050";

def address = bind Address {
     street: myStreet;
     city: myCity;
     state: myState;
     zip: myZip;
};

println("address.street == {address.street}");
myStreet = "100 Maple Street";
println("address.street == {address.street}");
 

При изменении значения myStreet переменная street объекта address изменяется:

address.street == 1 Main Street
address.street == 100 Maple Street
 

Обратите внимание, что изменение значения myStreet на самом деле вызывает создание нового объекта Address и затем переназначение значения переменной address. Чтобы отслеживать изменения без создания нового объекта Address, следует применить привязку прямо к переменным экземпляра класса:

def address = bind Address {
     street: bind myStreet;
     city: bind myCity;
     state: bind myState;
     zip: bind myZip;
};
 

Первый bind (тот, который стоит непосредственно перед Address) можно опустить, если вы применяете явную привязку к переменным экземпляра класса:

def address = Address {
     street: bind myStreet;
     city: bind myCity;
     state: bind myState;
     zip: bind myZip;
};
 
Привязка и функции

В предыдущих уроках вы познакомились с функциями, но есть еще одно различие, о котором вы должны узнать: bound функции по сравнению с non-bound функциями.

Рассмотрим следующую функцию, которая создает и возвращает объект класса Point:

var scale = 1.0;

bound function makePoint(xPos : Number, yPos : Number) : Point {
     Point {
          x: xPos * scale
          y: yPos * scale
     }
}

class Point { 
     var x : Number;
     var y : Number;
}
 

Такая функция известна как bound функция, т.к. ей предшествует зарезервированное слово bound.


Примечание: Зарезервированное слово bound не замещает слово bind; оба этих слова используются сообща как описано ниже.

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

var scale = 1.0;

bound function makePoint(xPos : Number, yPos : Number) : Point {
     Point {
          x: xPos * scale
          y: yPos * scale
     }
}

class Point {
     var x : Number;
     var y : Number;
}

var myX = 3.0;
var myY = 3.0;
def pt = bind makePoint(myX, myY);
println(pt.x);

myX = 10.0;
println(pt.x);

scale = 2.0;
println(pt.x);
 

Получим следующий результат:

3.0
10.0
20.0
 

Проанализируем этот скрипт небольшими фрагментами.

Следующий код:

var myX = 3.0;
var myY = 3.0;
def pt = bind makePoint(myX, myY);
println(pt.x);
 

инициализирует переменные скрипта myX и myY значениями 3.0. Эти значения затем передаются в качестве параметров функции makePoint, которая создает и возвращает новый объект класса Point. Зарезервированное слово bind, помещенное прямо перед вызовом функции makePoint, привязывает только что созданный объект класса Point (pt) к результату функции makePoint.

Затем код:

myX = 10.0;
println(pt.x);
 

меняет значение myX на 10.0 и выводит значение pt.x. Вывод показывает, что значение pt.x теперь также равно 10.0.

Наконец, следующий код:

scale = 2.0;
println(pt.x);
 

меняет значение scale и снова выводит значение pt.x. Значение pt.x теперь равно 20.0. Однако, если мы уберем зарезервированное слово bound от этой функции (тем самым сделав ее non-bound функцией), результат будет следующий:

3.0
10.0
10.0
 

Причина этого заключается в том, что non-bound функции вызываются повторно только тогда, когда один из их параметров меняется. Поскольку scale не является параметром функции, изменение его значения не приводит к новому вызову функции.

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

Оператор bind можно также использовать с выражениями for. Рассмотрим этот случай подробнее. Для начала определим две последовательности и выведем значения их элементов:

var seq1 = [1..10];
def seq2 = bind for (item in seq1) item*2;
printSeqs();

function printSeqs() {
     println("First Sequence:");
     for (i in seq1){println(i);}
     println("Second Sequence:");
     for (i in seq2){println(i);}
}
 

Последовательность seq1 содержит 10 элементов (числа от 1 до 10). Последовательность seq2 также содержит 10 элементов; эти элементы имели бы те же самые значения, что и элементы seq1, но мы применили к каждому элементу выражение item*2, так что их значения удвоились.

Следовательно, результат такой:

First Sequence:
1
2
3
4
5
6
7
8
9
10
Second Sequence:
2
4
6
8
10
12
14
16
18
20
 

Мы можем привязать две последовательности при помощи слова bind, помещенного непосредственно перед словом for.

def seq2 = bind for (item in seq1) item*2;
 

Возникает вопрос: если последовательность seq1 каким-либо образом изменится, все ли элементы последовательности seq2 изменятся или только некоторые из них? Мы можем протестировать это, если добавим один элемент со значением 11 в конец seq1, а затем напечатаем значения обеих последовательностей и посмотрим, что изменилось.

var seq1 = [1..10];
def seq2 = bind for (item in seq1) item*2;
insert 11 into seq1;
printSeqs();

function printSeqs() {
     println("First Sequence:");
     for (i in seq1){println(i);}
     println("Second Sequence:");
     for (i in seq2){println(i);}
}
 

Результат следующий:

First Sequence:
1
2
3
4
5
6
7
8
9
10
11
Second Sequence:
2
4
6
8
10
12
14
16
18
20
22
 

Вывод показывает, что добавление значения 11 в конец seq1 не влияет на первые 10 элементов последовательности seq2; новый элемент автоматически добавляется в конец seq2 и имеет значение 22.

Триггеры замены

Триггеры замены представляют собой произвольные блоки кода, которые ассоциируются с переменной и выполняются всякий раз, когда значение переменной меняется. Основной синтаксис показан в следующем примере: определяется значение переменной password и к переменной присоединяется триггер; когда значение password меняется, триггер распечатывает сообщение с новым значением этой переменной:

var password = "foo" on replace oldValue {
     println("\nALERT! Password has changed!");
     println("Old Value: {oldValue}");
     println("New Value: {password}");
};

password = "bar";
 

Результат этого примера показан ниже:

ALERT! Password has changed!
Old Value: 
New Value: foo

ALERT! Password has changed!
Old Value: foo
New Value: bar
 

В этом примере триггер срабатывает два раза: первый раз, когда переменная password инициализируется значением "foo", и второй раз, когда ее значение становится "bar". Обратите внимание, что в переменной oldValue сохраняется значение переменной до срабатывания триггера. Вы можете назвать эту переменную любым именем; мы использовали oldValue для наглядности.

 
« Предыдущий 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Следующий »
 
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.

Оглавление