鍍金池/ 教程/ Java/ JavaFX綁定
安裝e(fx)clipse到Eclipse (JavaFX工具)
JavaFX屬性
JavaFX文本域(輸入框)
JavaFX切換按鈕
JavaFX曲線
JavaFX教程
JavaFX菜單(Menu)
JavaFX快速入門
JavaFX復(fù)選框
JavaFX ScrollPane布局
JavaFX綁定
JavaFX顏色選擇器(ColorPicker)
JavaFX進(jìn)度指示器
JavaFX按鈕
JavaFX TitledPane布局
JavaFX圓弧
JavaFX開發(fā)環(huán)境安裝配置
在Eclipse安裝JavaFX Scene Builder
JavaFX路徑
JavaFX VBox
JavaFX線條
JavaFX漸變顏色
JavaFX集合
JavaFX BorderPane布局
JavaFX DatePicker
JavaFX單選按鈕
JavaFX滾動條
JavaFX矩形橢圓
JavaFX GridPane布局
JavaFX HBox
JavaFX進(jìn)度條
JavaFX多邊形折線
JavaFX超鏈接
JavaFX密碼字段
JavaFX Accordion布局
JavaFX概述和簡介
JavaFX選擇框
JavaFX文本
JavaFX顏色
JavaFX文件選擇器(FileChooser)
JavaFX標(biāo)簽
JavaFX FlowPane布局

JavaFX綁定

JavaFX綁定同步兩個值:當(dāng)依賴變量更改時,其他變量更改。

要將屬性綁定到另一個屬性,請調(diào)用bind()方法,該方法在一個方向綁定值。 例如,當(dāng)屬性A綁定到屬性B時,屬性B的更改將更新屬性A,但不可以反過來。

綁定選項(xiàng)

JavaFX提供了許多綁定選項(xiàng),以便在域?qū)ο蠛虶UI控件中的屬性之間進(jìn)行同步。

我們可以在JavaFX的Properties API中使用以下三種綁定策略:

  • Java Bean上的雙向綁定
  • Fluent API的高級綁定
  • 使用javafx.beans.binding定義綁定對象進(jìn)行低級綁定。

雙向綁定

雙向綁定綁定相同類型的屬性,并同步兩側(cè)的值。當(dāng)使用bindBidirectional()方法雙向綁定時,需要兩個屬性都必須是可讀/寫的。
以下代碼顯示如何在firstName屬性和字符串屬性變量之間進(jìn)行雙向綁定

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Main {
    public static void main(String[] args) {
        User contact = new User("Jame", "Bind");
        StringProperty fname = new SimpleStringProperty();
        fname.bindBidirectional(contact.firstNameProperty());

        contact.firstNameProperty().set("new value");
        fname.set("新綁定名稱值");

        System.out.println("firstNameProperty = " + contact.firstNameProperty().get());
        System.out.println("fname = " + fname.get());

    }// @ W WW .yI iB  AI.c  o M
}

class User {

    private SimpleStringProperty firstName = new SimpleStringProperty();
    private SimpleStringProperty lastName = new SimpleStringProperty();

    public User(String fn, String ln) {
        firstName.setValue(fn);
        lastName.setValue(ln);
    }

    public final String getFirstName() {
        return firstName.getValue();
    }

    public StringProperty firstNameProperty() {
        return firstName;
    }

    public final void setFirstName(String firstName) {
        this.firstName.setValue(firstName);
    }

    public final String getLastName() {
        return lastName.getValue();
    }

    public StringProperty lastNameProperty() {
        return lastName;
    }

    public final void setLastName(String lastName) {
        this.lastName.setValue(lastName);
    }
}

上面的代碼生成以下結(jié)果。

firstNameProperty = 新綁定名稱值
fname = 新綁定名稱值

高級別綁定

我們也可以使用JavaFX流利的API來綁定屬性。API使用類似英語的方法名稱對屬性執(zhí)行操作。 例如,multiply()divide(),subtract()isEqualTo(),isNotEqualTo(),concat()。 請注意,方法名稱中沒有getset。當(dāng)鏈接API在一起時可以寫代碼,就像類似于寫英文句子,例如,width().multiply(height()).divide(2)

以下代碼顯示如何創(chuàng)建表示計(jì)算矩形面積的公式的屬性。

它通過使用javafx.beans.binding.IntegerExpression接口中的fluent API來執(zhí)行高級綁定。

該代碼使用multiply()方法,該方法返回包含計(jì)算值 - NumberBinding

這個綁定是延遲評估求值的,這意味著乘法不會執(zhí)行計(jì)算,除非通過get()getValue()方法調(diào)用屬性的值。

import javafx.beans.binding.NumberBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;

public class Main {
  public static void main(String[] args) {
    // Area = width * height
    IntegerProperty width = new SimpleIntegerProperty(10);
    IntegerProperty height = new SimpleIntegerProperty(10);
    NumberBinding area = width.multiply(height);
    System.out.println(area.getValue());
  }
}

上面的代碼生成以下結(jié)果。

100

低級別綁定

當(dāng)對NumberBinding類進(jìn)行子類化時,使用低級別綁定,例如Double類型的DoubleBinding類。

DoubleBinding類的子類中,我們覆蓋它的computeValue()方法,以便可以使用運(yùn)算符(例如*- )來制定復(fù)雜的數(shù)學(xué)方程計(jì)算。
高級綁定使用如multiply(),subtract()等方法,而低級綁定使用諸如*- 等運(yùn)算符。

以下代碼顯示如何為公式創(chuàng)建低級別綁定,來計(jì)算矩形的面積。

import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;

public class Main {
  public static void main(String[] args) {
    DoubleProperty width = new SimpleDoubleProperty(2);
    DoubleProperty height = new SimpleDoubleProperty(2);
    DoubleBinding area = new DoubleBinding() {
      {
        super.bind(width, height); // initial bind
      }

      @Override
      protected double computeValue() {
        return width.get() * height.get();
      }
    };
    System.out.println(area.get());
  }
}

上面的代碼生成以下結(jié)果。

4.0

UI控件和域模型之間的綁定

在JavaFX中,UI控件和域模型之間的數(shù)據(jù)綁定很容易。以下代碼顯示如何創(chuàng)建登錄對話框并綁定用戶域?qū)ο蟆?br>首先,我們定義域?qū)ο螅敲枋鲇脩裘兔艽a的JavaFX JavaBean。

class User {
   private final ReadOnlyStringWrapper userName;
   private StringProperty password;
   public User() {
       userName = new ReadOnlyStringWrapper(this, "userName", "ABC");
       password = new SimpleStringProperty(this, "password", "");
   }

   public final String getUserName() {
       return userName.get();
   }
   public ReadOnlyStringProperty userNameProperty() {
       return userName.getReadOnlyProperty();
   }

   public final String getPassword() {
       return password.get();
   }
   public StringProperty passwordProperty() {
       return password;
   }
}

我們創(chuàng)建了兩個UI控件,一個用于使用Text控件顯示用戶名,另一個是 PasswordField 字段控件,它將輸入值綁定到域?qū)ο?User)中的 password 字段。

Text userName = new Text();
userName.textProperty().bind(user.userNameProperty());

PasswordField passwordField = new PasswordField();
passwordField.setPromptText("Password");
user.passwordProperty().bind(passwordField.textProperty());

在更改偵聽器中為passwordField字段文本值屬性設(shè)置BooleanProperty訪問權(quán)限。

passwordField.textProperty().addListener((obs, ov, nv) -> {
    boolean granted = passwordField.getText().equals(MY_PASS);
    accessGranted.set(granted);
    if (granted) {
        primaryStage.setTitle("");
    }
});

enter鍵點(diǎn)擊事件中訪問BooleanProperty accessGranted。

        // user hits the enter key
        passwordField.setOnAction(actionEvent -> {
            if (accessGranted.get()) {
                System.out.println("granted access:"+ user.getUserName());
                System.out.println("password:"+ user.getPassword());
                Platform.exit();
            } else {
              primaryStage.setTitle("no access"); 
            }
        });

完整的源代碼如下所示。

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.PasswordField;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;

// @  w  Ww .yi  iB  A i. C o M
public class Main extends Application {
    private final static String MY_PASS = "passwd";// 初始密碼
    private final static BooleanProperty accessGranted = new SimpleBooleanProperty(false);

    @Override
    public void start(Stage primaryStage) {
        User user = new User();
        Group root = new Group();
        Scene scene = new Scene(root, 320, 100);
        primaryStage.setScene(scene);

        Text userName = new Text();
        userName.textProperty().bind(user.userNameProperty());

        PasswordField passwordField = new PasswordField();
        passwordField.setPromptText("Password");
        user.passwordProperty().bind(passwordField.textProperty());

        // user hits the enter key
        passwordField.setOnAction(actionEvent -> {
            if (accessGranted.get()) {
                System.out.println("granted access:" + user.getUserName());
                System.out.println("password:" + user.getPassword());
                Platform.exit();
            } else {// @  WW  w .yIIB  A  i.c OM
                primaryStage.setTitle("no access");
            }
        });

        passwordField.textProperty().addListener((obs, ov, nv) -> {
            boolean granted = passwordField.getText().equals(MY_PASS);
            accessGranted.set(granted);
            if (granted) {
                primaryStage.setTitle("");
            }
        });
        VBox formLayout = new VBox(4);
        formLayout.getChildren().addAll(userName, passwordField);
        formLayout.setLayoutX(12);
        formLayout.setLayoutY(12);

        root.getChildren().addAll(formLayout);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

class User {
    private final ReadOnlyStringWrapper userName;
    private StringProperty password;

    public User() {
        userName = new ReadOnlyStringWrapper(this, "userName", "ABC");
        password = new SimpleStringProperty(this, "password", "");
    }

    public final String getUserName() {
        return userName.get();
    }

    public ReadOnlyStringProperty userNameProperty() {
        return userName.getReadOnlyProperty();
    }

    public final String getPassword() {
        return password.get();
    }

    public StringProperty passwordProperty() {
        return password;
    }
}

上面的代碼生成以下結(jié)果。

在上面的輸入框中輸入密碼:passwd 完成后,得到以下輸出結(jié)果 -

granted access:ABC
password:passwd

上一篇:JavaFX快速入門下一篇:JavaFX集合