1.Scene Graph體系結構淺析
javafx以tree的形式組織nodes,每一個node就是一個control,即UI組件。
node分爲leaf node與branch node, root node。
scene體系中最關鍵的類:
Scene:代表包含所有UI組件的頂級容器
Node:是一個抽象類,代表UI組件的基類
Parent:是一個抽象類,代表branch node的基類。
類層次結構:
Group用於爲child nodes集合統一應用effects and transfroms
Region則是包含layout,及css樣式的Controls
2.Properties與Binding
秒懂javafx中property的規範:
package propertydemo;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
class Bill {
// Define a variable to store the property
private DoubleProperty amountDue = new SimpleDoubleProperty();
// 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;}
}
理解監聽機制:
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);
Bindings與property的關係
IntegerProperty num1 = new SimpleIntegerProperty(1);
IntegerProperty num2 = new SimpleIntegerProperty(2);
NumberBinding sum = num1.add(num2);
//也可以是這種方式:NumberBinding sum = Bindings.add(num1,num2);
System.out.println(sum.getValue());
num1.set(2);
System.out.println(sum.getValue());
Observable,ObservableValue,InvacationListener,ChangeListener
Observable與ObservableValue接口負責fire觸發property改變通知。Observable觸發InvacationListener,而ObservableValue負責觸發ChangeListener.NumberBinding total = Bindings.add(bill1.amountDueProperty().add(bill2.amountDueProperty()), bill3.amountDueProperty()); total.addListener(new InvalidationListener() { @Override public void invalidated(Observable o) { System.out.println("The binding is now invalid."); } }); // First call makes the binding invalid bill1.setAmountDue(200.00); // The binding is now invalid bill2.setAmountDue(100.00); bill3.setAmountDue(75.00); // Make the binding valid... System.out.println(total.getValue());
自定義Bindings:
final DoubleProperty a = new SimpleDoubleProperty(1);
final DoubleProperty b = new SimpleDoubleProperty(2);
final DoubleProperty c = new SimpleDoubleProperty(3);
final DoubleProperty d = new SimpleDoubleProperty(4);
DoubleBinding db = new DoubleBinding() {
{
super.bind(a, b, c, d);
}
@Override
protected double computeValue() {
return (a.get() * b.get()) + (c.get() * d.get());
}
};
System.out.println(db.get());
b.set(3);
3.javaFx Collections
javafx Collections是基於java基礎類庫中的集合框架的,只不過是結合了javafx中的Observable,使之成爲可以觀察變化的集合。便於javafx的模型數據維護。
javafx.collections包中的主要類:
接口:
ObservableList, ObservableMap :被監聽者集合
ListChangeListener MapChangeListener 監聽器集合
類:
FXCollections:它是一個基於java.util.Collections的一比一複製品。只不過是做了一層javafx的本地化。但是它是最重要的類了,一切ObservableList/Map均由它的工廠方法產生。
ListChangeListener.Change MapChangeListener.Change:包含者列表或map中的所有變化。可以進行迭代操作。
Change類包含的變化種類有:排序變化,添加刪除變化,更新變化。並有對應的判斷方法。
// Use Java Collections to create the List.
List<String> list = new ArrayList<String>();
// Now add observability by wrapping it with ObservableList.
ObservableList<String> observableList = FXCollections.observableList(list);
observableList.addListener(new ListChangeListener() {
@Override
public void onChanged(ListChangeListener.Change change) {
System.out.println("Detected a change! ");
}
});
// Changes to the observableList WILL be reported.
// This line will print out "Detected a change!"
observableList.add("item one");
// This code will work with any of the previous ObservableList examples
observableList.addListener(new ListChangeListener() {
@Override
public void onChanged(ListChangeListener.Change change) {
System.out.println("Detected a change! ");
while (change.next()) {
System.out.println("Was added? " + change.wasAdded());
System.out.println("Was removed? " + change.wasRemoved());
System.out.println("Was replaced? " + change.wasReplaced());
System.out.println("Was permutated? " + change.wasPermutated());
}
}
});
ObservableList theList = ...;
theList.addListener(new ListChangeListener<Item>() {
public void onChanged(Change<tem> c) {
while (c.next()) {
if (c.wasPermutated()) {
for (int i = c.getFrom(); i < c.getTo(); ++i) {
//permutate
}
} else if (c.wasUpdated()) {
//update item
} else {
for (Item remitem : c.getRemoved()) {
remitem.remove(Outer.this);
}
for (Item additem : c.getAddedSubList()) {
additem.add(Outer.this);
}
但你要注意的是對這些集合的操作並不是線程安全的。所以你需要在必要時確保線程安全性。