第三百四十六节 JavaFX教程 - JavaFX绑定

news2025/2/6 18:21:38

JavaFX教程 - JavaFX绑定

JavaFX绑定同步两个值:当因变量更改时,其他变量更改。

要将属性绑定到另一个属性,请调用bind()方法,该方法在一个方向绑定值。例如,当属性A绑定到属性B时,属性B的更改将更新属性A,但不是相反。

绑定选项

JavaFX提供了许多绑定选项,以便在域对象和GUI控件中的属性之间进行同步。

我们可以在JavaFX的属性API中使用以下三种绑定策略:

  • Java Bean上的双向绑定
  • 与Fluent API的高级绑定
  • 使用javafx.beans.binding.*中定义的绑定对象进行低级绑定。

双向绑定

双向绑定绑定相同类型的属性,并同步两侧的a值。

当与bindBidirectional()方法双向绑定时,需要两个属性都必须是可读/可写的。

以下代码显示如何在firstName属性和字符串属性变量之间进行双向绑定

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("New First Name");

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

  }
}
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);
  }
}

上面的代码生成以下结果。

高级绑定

我们还可以使用JavaFX fluent API来绑定属性。流利的API使用类似英语的方法名称对属性执行操作。

例如,multiply(),divide(),subtract(),isEqualTo(),isNotEqualTo(),concat()。请注意,方法名称中没有get或set。当链接流畅的API在一起,我们可以编写代码,如同我们正在写句子,例如 width().multiply(height()).divide(2)

以下代码显示如何创建表示计算矩形面积的公式的属性。

它通过使用 javafx.beans.binding.IntegerExpression 接口中的fluent API来执行高级绑定。

该代码使用 multiply()方法,该方法返回包含计算值的NumberBinding。

这种绑定是延迟评估的,这意味着乘法不会发生,除非我们通过 get() getValue()方法调用属性的值。

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());
  }
}

上面的代码生成以下结果。

低级绑定

当对 NumberBinding 类进行子类化时,我们使用低级绑定,例如Double类型的DoubleBinding类。

在DoubleBinding类的子类中,我们重写其 computeValue()方法,以便我们可以使用运算符(如 - )来制定复杂的数学方程。

高级绑定使用诸如multiply(),subtract()等方法低级绑定使用诸如*和 - 之类的运算符。

以下代码显示如何为公式创建低级别绑定以计算矩形的面积。

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());
  }
}

上面的代码生成以下结果。

UI控件和域模型之间的绑定

在JavaFX中,UI控件和域模型之间的数据绑定很容易。以下代码显示如何创建登录对话框并绑定用户域对象。

首先,我们定义域对象,它是描述用户名和密码的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;
   }
}

我们创建了两个UI控件,一个是用Text控件显示用户名,另一个是PasswordField控件,它将输入值绑定到域对象中的密码字段。

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

BooleanProperty accessGranted在passwordField的文本值属性的更改侦听器中设置。

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

在enter键hit事件中访问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;

public class Main extends Application {
    private final static String MY_PASS = "asdf";
    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 {
              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;
   }
}

上面的代码生成以下结果。

null

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2267560.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

慧集通客户案例:致远OA与熵基考勤机集成方案

本原型公司是一家专注大健康产业的综合性高新科技形实体企业,按照单位的战略业务布局,围绕“做强做优、世界一流”的目标,加快内外部资源整合、加强业务协同、优化资源配置,有序推进大健康及相关产业的有机融合,加快构…

SCSA: Exploring the Synergistic Effects Between Spatial and Channel Attention

摘要 https://arxiv.org/pdf/2407.05128 通道注意力和空间注意力分别为各种下游视觉任务在提取特征依赖性和空间结构关系方面带来了显著改进。通道注意力和空间注意力的结合使用被广泛认为有利于进一步提升性能;然而,通道注意力和空间注意力之间的协同作…

UE5在蓝图中使用VarestX插件访问API

在Fab中安装好VarestX免费插件 这个插件可以用来远程请求http和api等,返回json等格式内容 插件网址 https://www.fab.com/zh-cn/listings/d283e40c-4ee5-4e73-8110-cc7253cbeaab 虚幻里开启插件 然后网上随便搜个免费api测试一下,这里我找了个微博热搜…

碰一碰发视频矩阵系统源码搭建,支持OEM

一、引言 随着短视频的火爆发展,碰一碰发视频的矩阵系统逐渐受到关注。这种系统能够实现用户通过碰一碰设备(如 NFC 标签)快速触发视频的发布,在营销推广、互动体验等领域有着广泛的应用前景。本文将详细介绍碰一碰发视频矩阵系统…

Pandas01

文章目录 内容简介1 常用数据分析三方库2 Jupyter notebook3 Series的创建3.1 通过Numpy的Ndarray 创建一个Series3.2 通过列表创建Series 4 Series的属性和方法4.1 常用属性4.2 常用方法4.3 布尔值列表筛选部分数据4.4 Series 的运算 5 DataFrame的创建通过字典创建通过列表[元…

WebPack3项目升级webpack5的配置调试记录

文章目录 前言一、webpack3环境1.1、知识点记录1.1.1、配置解释1.1.2、webpack与sass版本对应关系1.1.3、CommonJS与ESModule1.1.4、node版本管理nvm1.1.5、sass-loader、sass与node-sass 1.2、其他1.2.1、.d.ts是什么文件1.2.2、react与types/react版本对应关系1.2.3、webpack…

plsql :用户system通过sysdba连接数据库--报错ora-01031

一、winR cmd通过命令窗口登录sys用户 sql sys/[password]//localhost:1521/[service_name] as sysdba二、输入用户名:sys as sysdba 三、输入密码:自己设的 四、执行grant sysdba to system; 再去PL/SQL连接就可以了

Quo Vadis, Anomaly Detection? LLMs and VLMs in the Spotlight 论文阅读

文章信息: 原文链接:https://arxiv.org/abs/2412.18298 Abstract 视频异常检测(VAD)通过整合大语言模型(LLMs)和视觉语言模型(VLMs)取得了显著进展,解决了动态开放世界…

药片缺陷检测数据集,8625张图片,使用YOLO,PASICAL VOC XML,COCO JSON格式标注,可识别药品是否有缺陷,是否完整

药片缺陷检测数据集,8625张图片,使用YOLO,PASICAL VOC XML,COCO JSON格式标注,可识别药品是否有缺陷,是否完整 有缺陷的标注信息: 无缺陷的标注信息 数据集下载: yolov11:https://d…

蓝桥杯速成教程{三}(adc,i2c,uart)

目录 一、adc 原理图​编辑引脚配置 Adc通道使能配置 实例测试 ​编辑效果显示 案例程序 badc 按键相关函数 测量频率占空比 main 按键的过程 显示界面的过程 二、IIC通信-eeprom 原理图AT24C02 引脚配置 不可用状态,用的软件IIC 官方库移植 At24c02手册 ​编辑…

第6章 图论

2024年12月25日一稿 🐰6.1 图的基本概念 6.1.1 图的定义和表示 6.1.2 图的同构 6.1.3 完全图与正则图 6.1.4 子图与补图 6.1.5 通路与回路 6.2 图的连通性 6.2.1 无向图的连通性 6.2.2 有向图的连通性 6.3 图的矩阵表示 6.3.1 关联矩阵 6.3.2 有向图的邻接矩阵…

数据库原理及应用(MySQL版-李月军)-习题参考答案

数据库原理及应用(MySQL版)-微课视频版 习题参考答案 习 题一 一.选择题 1、D 2、C 3、C 4、B 5、D 6、B 7、A 8、B 9、C 10、A 11、B 12、C 13、①A②B③C 14、①E②B 15、①B②C③B 16、B 17、A 18、D 二.填空题 1、文件…

从家谱的层级结构 - 组合模式(Composite Pattern)

组合模式(Composite Pattern) 组合模式(Composite Pattern)组合模式概述组合模式涉及的角色talk is cheap, show you my code总结 组合模式(Composite Pattern) 组合模式(Composite…

路由器刷机TP-Link tp-link-WDR5660 路由器升级宽带速度

何在路由器上设置代理服务器? 如何在路由器上设置代理服务器? 让所有连接到该路由器的设备都能够享受代理服务器的好处是一个不错的选择,特别是当需要访问特定的网站或加速网络连接的时候。下面是一些您可以跟随的步骤,使用路由器…

免费干净!付费软件的平替款!

今天给大家介绍一个非常好用的电脑录屏软件,完全没有广告界面,非常的干净简洁。 电脑录屏 无广告的录屏软件 这个软件不需要安装,打开就能看到界面直接使用了。 软件可以全屏录制,也可以自定义尺寸进行录制。 录制的声音选择也非…

Pandas03

Pandas01 Pandas02 文章目录 内容回顾1 排序和统计函数2 缺失值处理2.1 认识缺失值2.2 缺失值处理- 删除2.3 缺失值处理- 填充非时序数据时序数据 3 Pandas数据类型3.1 数值类型和字符串类型之间的转换3.2 日期时间类型3.3 日期时间索引 4 分组聚合4.1 分组聚合的API使用4.2 分…

vue3使用element-plus,解决 el-table 多选框,选中后翻页再回来选中失效问题

问题&#xff1a;勾选的数据分页再回来回消失 1.在el-table中加 :row-key"getRowKey" const getRowKey (row) > { return row.id; // id必须是唯一的 }; 2.给type为selection的el-table-column添加上reserve-selection属性 <el-tableref"multipleTab…

BUU BRUTE 1

BUU BRUTE 1 启动靶机 让我们输入账户和密码&#xff0c;这里我们什么也不知道就随便输入一个试试 账户adimin密码1234 告诉我们密码错误&#xff0c;为四位数字&#xff0c;在这里没有说账号错误&#xff0c;说明账号就是admin 密码的话爆破一下从0000到9999 这里选择默认的…

Maple软件的安装和使用

文章目录 1.前言说明2.我为什么要学习Maple3.软件的安装4.如何使用4.1基本的赋值语句4.2函数的定义4.3三个类型的书写介质 5.指数运算5.1使用面板5.2自己输入 6.对数的使用 1.前言说明 众所周知&#xff0c;我虽然是一名这个计算机专业的学生&#xff0c;但是我对于数学&#…

vue之axios基本使用

文章目录 1. axios 网络请求库2. axiosvue 1. axios 网络请求库 <body> <input type"button" value"get请求" class"get"> <input type"button" value"post请求" class"post"> <!-- 官网提供…