JavaFX Property与绑定/监听

绑定本质上就是建立一个双向监听。

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()。

/*
*GridPaneSampleBinding.java(测试例子)
 * 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);
    }
}

JavaFX可通过Property监听,做出自己的操作,在图形的Property监听中应用较多。

// Double监听
方式一(可知详细变化):
        DoubleProperty doubleProperty = new SimpleDoubleProperty(初始化的double值);
        doubleProperty.addListener(this::doublePropertyChange);
        private void doublePropertyChange(ObservableValue<? extends Number>                                     observable, Number oldValue, Number newValue){
        double value = (double)newValue;
        }
        // 坑 最小值变化不触发改变的监听事件
        doubleProperty.set(doubleProperty.get() + Double.MIN_VALUE); 


方式二(可知详细变化):
doubleProperty.addListener(new ChangeListener<Number>() {
    @Override
    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
    //操作
    }
});
可简化为
doubleProperty.addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
	double value = (double)newValue;
});


方式三(可知变化了):		
ReadOnlyDoubleWrapper doubleProperty = new ReadOnlyDoubleWrapper(初始化的double值);
doubleProperty.getReadOnlyProperty().addListener(o -> doSomething());
private void doSomething(){
}

图形的属性可绑定一个Property,在Property变化时,属性也跟着变化,可广泛应用于动画。

Button myButton = new Button();
myButton.setText("Test");
SimpleDoubleProperty simpleDoubleProperty = new SimpleDoubleProperty(100);
myButton.translateXProperty().bind(simpleDoubleProperty);
simpleDoubleProperty.set(0);
// 想通过setTranslateX方式改变translateX属性,必须解绑
myButton.unbind();
myButton.setTranslateX(50);

JavaFX重点案例
1、接口类

import javafx.application.Application; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage;
public class Main extends Application implements EventHandler{
	Button button;
	@Override
	public void start(Stage primaryStage) {
    	primaryStage.setTitle("set the title");
    	button=new Button();
    	button.setText("Click me");
    	//button.setOnAction(this);
    	StackPane layout=new StackPane();
    	layout.getChildren().add(button);
    	Scene scene=new Scene(layout,300,300);
    	primaryStage.setScene(scene);
    	primaryStage.show();
	}
	public static void main(String[] args) {
    	launch(args);
	}
	/*@Override
	public void handle(ActionEvent event) {
    	System.out.println("Wow ! I am clicked !");
	}*/
}

2.anonymous 匿名类

import javafx.application.Application; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage;
public class Main extends Application{
	Button button;
	@Override
	public void start(Stage primaryStage) {
    	primaryStage.setTitle("set the title");
    	button=new Button();
    	button.setText("Click me");
    	/*button.setOnAction(new EventHandler<ActionEvent>(){
        	@Override
        	public void handle(ActionEvent event) {
            	System.out.println("Today is traditional lovers day in China !");
            	System.out.println("I am a single dog !");
        	}
    	});*/
    	StackPane layout=new StackPane();
    	layout.getChildren().add(button);
    	Scene scene=new Scene(layout,300,300);
    	primaryStage.setScene(scene);
    	primaryStage.show();
	}
	public static void main(String[] args) {
    	launch(args);
	}
}

3.lambda表达式

import javafx.application.Application; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage;
public class Main extends Application{
	Button button;
	@Override
	public void start(Stage primaryStage) {
    	primaryStage.setTitle("set the title");
    	button=new Button();
    	button.setText("Click me");
    	/*button.setOnAction(e -> {
        	System.out.println("I love u !");
        	System.out.println("Do u love me ?");
    	});*/
    	StackPane layout=new StackPane();
    	layout.getChildren().add(button);
    	Scene scene=new Scene(layout,300,300);
    	primaryStage.setScene(scene);
    	primaryStage.show();
	}
	public static void main(String[] args) {
    	launch(args);
	}
}

友情链接:
code.makery——JavaFX 教程 (中文)
https://code.makery.ch/zh-cn/library/javafx-tutorial/

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值