尽管java开发者偶尔用“property”来指java 类中的attributes 。Javafx “properties ” 实际上远远不止“attributes” 。 JAVAfX定义了一个接口 javafx.beans.property.Property,它有一个非常有用的功能:绑定GUI组件(视图层)到java类(MODULE)的“properties”中。当绑定建立后,如果module层的值发生改变,GUI自动会自动接到通知,反之亦然。
说明:绑定本质上就是建立一个双向监听。
假定我们正在发开一个金融软件,它能从服务端接收股票价格化的通知。当java对象接收到新的价格后,我们需要更新对应的UI组件的内容。 但有了javafx之后, 我们可以绑定java类的价格“PROPERTY”到ui组件上(比如说是一个Label),如此便不再需要其他编码工作了。 只要价格发生了变更。Label组件会自动更新。 JAVAFX “property” 极大的简化了数据层和UI层数据同步的问题。
Property 接口当前实现所扮演的角色是对java “attributes”的包裹,并为其添加了改变通知功能。Property interface 里包含了bind(), unbind(), bindBidirectional() , unbindBidirctional(), and isBound()。 说明的是:只有Observable类型的对象才可以绑定到JAVAFX “property”上。
JavaFx property 相关的类位于javafx.beans.property包中。每一种Property类型都有两个类。 read-only 和 read-write ones 。举例来说:我们需要一个String property。 可以用 SimpleStringProperty 或者 ReadOnlyStringWrapper。他们两个都实现了StringProperty 接口。其他数据类型和容器也是如此。
绑定是非直接的,当UI组件发生变化,它能够更新地下module层的值(MVC).当module层的值发生变化,UI层也会被更新。如果想解除绑定,可以使用unbind()。方法
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package mybinding;
import javafx.application.Application; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.event.ActionEvent; import javafx.event.Event; import javafx.event.EventHandler; import javafx.geometry.HPos; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.geometry.VPos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; import javafx.scene.control.PasswordField; import javafx.scene.control.TextField; import javafx.scene.layout.GridPane; import javafx.stage.Stage;
public class GridPaneSampleBinding extends Application {
//Declaring a JavaFX property private StringProperty message = new SimpleStringProperty();
public void start(Stage primaryStage) {
Label userIdLbl = new Label("User ID:"); TextField userIdTxt = new TextField(); Label userPwdLbl = new Label("Password:"); PasswordField userPwdTxt = new PasswordField(); Button signInBtn = new Button("Sign In"); Button cancelBtn = new Button("Cancel"); Hyperlink forgotPwdLink = new Hyperlink("Forgot password");
// A label to display messages using binding Label messageLbl = new Label(); // binding the StringProperty to a GUI component messageLbl.textProperty().bind(message);
GridPane root = new GridPane(); root.setVgap(20); root.setPadding(new Insets(10)); root.setAlignment(Pos.CENTER);
// Using static methods for setting node constraints GridPane.setConstraints(userIdLbl, 0, 0); GridPane.setConstraints(userIdTxt, 1, 0); GridPane.setConstraints(userPwdLbl, 0, 1); GridPane.setConstraints(userPwdTxt, 1, 1); GridPane.setConstraints(signInBtn, 0, 2);
//Cancel button: span 1, right aligned GridPane.setConstraints(cancelBtn, 1, 2, 1, 1, HPos.RIGHT, VPos.CENTER); GridPane.setConstraints(forgotPwdLink, 0, 3, 2, 1);
// Message label: span 2 GridPane.setConstraints(messageLbl, 0, 4, 2, 1);
root.getChildren().addAll(userIdLbl, userIdTxt, userPwdLbl, userPwdTxt, signInBtn, cancelBtn, forgotPwdLink, messageLbl);
// event handlers //1. Anonymous class signInBtn.setOnAction(new EventHandler() {
@Override public void handle(Event event) { message.set("Sign in clicked."); } });
// lambda expression cancelBtn.setOnAction(evt -> message.set("Cancel clicked.") );
// method reference forgotPwdLink.setOnAction(this::forgotPwdHandler);
// Show the window Scene scene = new Scene(root, 250, 220); primaryStage.setScene(scene); primaryStage.show(); }
private void forgotPwdHandler(ActionEvent evt) { message.set("Forgot password clicked"); }
public static void main(String[] args) { launch(args); } }
|