JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » JavaFX 討論區  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友   
reply to topicthreaded modego to previous topicgo to next topic
本主題所含的標籤
作者 JavaFX 2.0中的綁定機制 (Binding)
UndeadJ

UX & UI Design



發文: 384
積分: 3
於 2011-06-09 22:55 user profilesend a private message to usersend email to UndeadJreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
文章參考:Using JavaFX Properties and Binding

JavaFX中的綁定機制(Binding)是基於JavaBean的,而且更強大。
在此之前,Java應用程式如果要用類似這樣的綁定機制,則必須借助第三方library,像是JGoodies Binding: Swing Data Binding FrameworkBeans Binding (JSR 295)
此外,綁定機制在動畫或動態的效果中也是很有用,就像是使用Timing FrameworkTrident 中裡的屬性綁定(property binding)一樣。我們可以利用綁定機制(Binding)來完成很好的互動式UI。

在JavaFX中,properties通常結合Binding來使用,用來直接表示2個變數之間的關係(變化)。
當物件加入綁定機制時,只要有所變化時,就會自動反映到另一個物件身上,也可以稱為依賴關係(dependencies)。

簡單來說,就是當2個屬性值被綁在一起的時候(binding),如果其中一個值被改變,另一個的值也會跟著被改變

Binding可以分成二大類:
The High-Level API: 語法易學易用。主要為一般常見的案例,提供一個簡單的方式來建立綁定機制。
The Low-Level API:提供了額外的彈性,主要用於The High-Level API不足以使用的情況下。另外,Low-Level API在執行上會比較快速而且暫用的記憶體會較小。

在使用JavaFX properties時,需先了解一些新的API與命名規則。下面就用例子來說明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
import javafx.beans.property.DoubleProperty;
 
class Bill {
 
    // Define a variable to store the property
    private DoubleProperty amountDue = new DoubleProperty();
 
    // Define a getter for the property's value
    public final double getAmountDue(){return amountDue.get();}
 
    // Define a setter for the property's value
    public final void setAmountDue(double value){amountDue.set(value);}
 
     // Define a getter for the property itself
    public DoubleProperty amountDueProperty() {return amountDue;} 
}


在這個例子中,利用javafx.beans.property.DoubleProperty做為Double的properties binding,名稱為amountDue。
當訂定好property名稱後,就必須準備(實作)binding所需要的項目:setter()、 getter() 、 propertyName+Propetry()。其中setter為非必要項目。

以此例來說:
getAmountDue()為標準的getter,它會回傳當前amountDue屬性值。通常,這個方法會加上final。要注意的是,這個方法回傳的型別是double,而不是DoubleProperty。
setAmountDue()為標準的setter,通常,也有final。主要用來設定amountDue屬性值。參數的型態和getter一樣(此為double),而不是DoubleProperty。

最後amountDueProperty(),則是回傳它自己(amountDue),來取得屬性的型別(此為DoubleProperty)。
它採用新的命名規則,方法名稱是由屬性名稱再加上"Property"所組合而成的。
在propetry binding中一定要採用這樣的命名規則,才可以實現綁定機制(binding)。
除此之外,這裡的amountDue物件型別並不是標準的Java基本型別(int, doulbe, float...etc)。而是重新封裝Java基本型別後的一個新類別,裡面也加了一些額外的功能。

在JavaFX應用程式中,有部分的API已經實作了屬性綁定機制(properties binding),可以直接拿來使用。
舉例來說,在javafx.scene.shape.Rectangle API中,有arcHeight、arcWidth、height、width、x、y。
而這些屬性,都已經實作好綁定機制中所需要的方法,以arcHeight為例,就是getArcHeight(), setArcHeight(double), arcHeightProperty()。

也可以加入change事件來監聽屬性值是否有被改變,如下例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import javafx.beans.value.ObservableValue;
import javafx.beans.value.ChangeListener;
 
public class Main {
 
    public static void main(String[] args) {
 
      Bill electricBill = new Bill();
 
       electricBill.amountDueProperty().addListener(new ChangeListener(){
        @Override public void changed(ObservableValue o,Object oldVal, 
                 Object newVal){
             System.out.println("Electric bill has changed!");
        }
      });
     
      electricBill.setAmountDue(100.00);
     
    }
}


Reference
Using JavaFX Properties and Binding
JGoodies Binding: Swing Data Binding Framework
Beans Binding (JSR 295)
Timing Framework
Trident
Introducing Trident – animation library for Java applications
使用JavaFX2.0的屬性和綁定


UndeadJ edited on 2011-06-10 00:29
reply to postreply to post
我們是懷抱各自的夢想,買了車票的乘客,不過就像列車一定會有終點,人生有時會碰到必須換車的時候...

我們站在名為「今天」的車站,在名為「昨天」的列車下車,轉搭為「明天」的列車

不過,若沒及時搭上的話....
作者 Re:JavaFX 2.0中的綁定機制 (Binding) [Re:UndeadJ]
UndeadJ

UX & UI Design



發文: 384
積分: 3
於 2011-06-10 00:29 user profilesend a private message to usersend email to UndeadJreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
High-Level Binding API
在JavaFX應用程式中要使用Binding的話,最快速也最容易的方法,就是利用使用High-Level Binding API。
它包含了2個部分:Fluent API 及 Bindings 類別。

Fluent API是提供各種公開方法實現綁定機制,而Bindings則是提供靜態工廠方法(static factory methods)。

Fluent API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import javafx.beans.property.IntegerProperty;
import javafx.beans.binding.NumberBinding; 
 
public class Main {
 
    public static void main(String[] args) {
        IntegerProperty num1 = new IntegerProperty(1);
        IntegerProperty num2 = new IntegerProperty(2);
        NumberBinding sum = num1.add(num2); //Fluent API
        System.out.println(sum.getValue());
        num1.set(2);  // or num.setValue(2);
        System.out.println(sum.getValue());
    }
}


Static Factory Methods (Bindings)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import javafx.beans.property.IntegerProperty;
import javafx.beans.binding.NumberBinding; 
import javafx.beans.binding.Bindings;      
 
public class Main {
 
    public static void main(String[] args) {
       IntegerProperty num1 = new IntegerProperty(1);
       IntegerProperty num2 = new IntegerProperty(2);
       NumberBinding sum = Bindings.add(num1,num2); //static factory method
       System.out.println(sum.getValue());
       num2.setValue(4);
       System.err.println(sum.getValue());
    }
}


也可以合在一起使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import javafx.beans.property.IntegerProperty;
import javafx.beans.binding.NumberBinding;
import javafx.beans.binding.Bindings;
 
public class Main {
 
    public static void main(String[] args) {
       IntegerProperty num1 = new IntegerProperty(1);
       IntegerProperty num2 = new IntegerProperty(2);
       IntegerProperty num3 = new IntegerProperty(3);
       IntegerProperty num4 = new IntegerProperty(4);
       NumberBinding total =  Bindings.add(num1.multiply(num2),num3.multiply(num4)); //static factory method & Fluent API
       System.out.println(total.getValue());
       num1.setValue(2);
       System.err.println(total.getValue());
    }
}


reply to postreply to post
我們是懷抱各自的夢想,買了車票的乘客,不過就像列車一定會有終點,人生有時會碰到必須換車的時候...

我們站在名為「今天」的車站,在名為「昨天」的列車下車,轉搭為「明天」的列車

不過,若沒及時搭上的話....
作者 Re:JavaFX 2.0中的綁定機制 (Binding) [Re:UndeadJ]
UndeadJ

UX & UI Design



發文: 384
積分: 3
於 2011-06-10 00:29 user profilesend a private message to usersend email to UndeadJreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
深入了解ObservableValue、InvalidationListener、ChangeListener

在javafx.beans.property與javafx.beans.binding下的所有類別都實作了ObservableValue<T>介面。ObservableValue包裝了一個值讓它能夠觀察其變化。
一般來說不會直接去實作這個介面,而是透過子類別來實作它(ex. ObservableBooleanValue)。
一個ObservableValue物件會產生2個事件:當某個值被改變時會觸發change事件,而當某個值無效了則會產生invalidation事件。
在JavaFX中,綁定機制是支援lazy evaluation的。也就是說,當某個值被改變時,另一個與它綁定的值並不會馬上做改變,而且等到要使用時,才會做計算與改變。
不過要注意的是,如果是在change事件中的話,即使實作ObservableValue<T>的子類別已支援lazy evaluation,也會強制立刻計算。

在綁定機制中,只要依賴關係中的成員一被改變,"當下"這個綁定是無效的,在設定或取得值後,就馬上回變成有效的。另外,如果有增加ChangeListenr的話,也會觸發。
但是,當要"改變的值"和"先前的值"是一樣的時候,二者都不會被觸發。

以下是個例子:
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
import javafx.beans.property.DoubleProperty;
import javafx.beans.binding.NumberBinding;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.InvalidationListener;
import javafx.beans.value.ObservableValue;
 
class Bill {
 
    // Define the property
    private DoubleProperty amountDue = new DoubleProperty();
 
    // Define a getter for the property's value
    public final double getAmountDue() {
        return amountDue.get();
    }
 
    // Define a setter for the property's value
    public final void setAmountDue(double value) {
        amountDue.set(value);
    }
 
    // Define a getter for the property itself
    public DoubleProperty amountDueProperty() {
        return amountDue;
    }
}
 
public class Main {
 
    static NumberBinding total;
 
    public static void main(String[] args) {
        Bill bill1 = new Bill();
        Bill bill2 = new Bill();
        Bill bill3 = new Bill();
 
        total =
                Bindings.add(bill1.amountDueProperty().add(bill2.amountDueProperty()),
                bill3.amountDueProperty());
 
        total.addListener(new InvalidationListener() {
            @Override
            public void invalidated(ObservableValue o) {
                System.out.println("The binding is now invalid. total binding is: " + total.isValid());
            }
        });
 
        total.addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                System.out.println("The binding is now invalid. total binding is: " + total.isValid());
            }
        });
 
        System.out.println("binding is: " + total.isValid());
        
        // First call makes the binding invalid
        bill1.setAmountDue(200.00);        
        System.out.println("binding is: " + total.isValid());
        
        bill1.setAmountDue(200.00);  //設定的值和先前相同不會觸發InvalidationListener、ChangeListener
        System.out.println("binding is: " + total.isValid());
        
        // The binding is now invalid
        bill2.setAmountDue(100.00);
        System.out.println("binding is: " + total.isValid());
        
        bill3.setAmountDue(75.00);
        System.out.println("binding is: " + total.isValid());
 
        // Make the binding valid...
        System.out.println(total.getValue());
        System.out.println("binding is: " + total.isValid());
        
        // Make invalid... 
        bill3.setAmountDue(150.00);
        System.out.println("binding is: " + total.isValid());
 
        // Make valid...
        System.out.println(total.getValue());
        System.out.println("binding is: " + total.isValid());
    }
}


reply to postreply to post
我們是懷抱各自的夢想,買了車票的乘客,不過就像列車一定會有終點,人生有時會碰到必須換車的時候...

我們站在名為「今天」的車站,在名為「昨天」的列車下車,轉搭為「明天」的列車

不過,若沒及時搭上的話....
作者 Re:JavaFX 2.0中的綁定機制 (Binding) [Re:UndeadJ]
UndeadJ

UX & UI Design



發文: 384
積分: 3
於 2011-06-10 00:29 user profilesend a private message to usersend email to UndeadJreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
Low-Level Binding API

如果High-Level Binding API不足應付需求的話,可以使用Low-Level Binding API。
相較於High-Level Binding API,Low-Level Binding API有更好的彈性與效能。

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
 
import javafx.beans.property.DoubleProperty;
import javafx.beans.binding.DoubleBinding;
 
public class Main {
 
    public static void main(String[] args) {
 
        final DoubleProperty a = new DoubleProperty(1);
        final DoubleProperty b = new DoubleProperty(2);
        final DoubleProperty c = new DoubleProperty(3);
        final DoubleProperty d = new DoubleProperty(4);
 
        DoubleBinding db = new DoubleBinding() { 
            {
                bind(a, b, c, d);               
            }
 
            @Override
            protected double computeValue() {
                return (a.get() * b.get()) + (c.get() * d.get());
            }
        };
        System.out.println("binding is: " + db.isValid());// 無效
        System.out.println(db.get());
        System.out.println("binding is: " + db.isValid());// 有效 
        b.set(3);
        System.out.println("binding is: " + db.isValid());// 無效  
        System.out.println(db.get());
        System.out.println("binding is: " + db.isValid());// 有效
    }
}


使用Low-Level Binding API 時,必須覆寫(Override)computeValue方法,來取得當前所綁定的值。
以這個例子來說,利用super.bind()來綁定所有有相依關係的元素(a,b,c,d),此時綁定是無效的,只有在"被要求的時候",才會生效,也就是所謂的lazy evaluation。
通常來說不用特地的去檢查綁定否失效,這個檢查會由父類別來完成。


reply to postreply to post
我們是懷抱各自的夢想,買了車票的乘客,不過就像列車一定會有終點,人生有時會碰到必須換車的時候...

我們站在名為「今天」的車站,在名為「昨天」的列車下車,轉搭為「明天」的列車

不過,若沒及時搭上的話....
» JWorld@TW »  JavaFX 討論區

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8