第三百四十六节 JavaFX教程 - JavaFX绑定
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 * heightIntegerProperty 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}@Overrideprotected 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 keypasswordField.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);@Overridepublic 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 keypasswordField.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;} }
上面的代码生成以下结果。
相关文章:

第三百四十六节 JavaFX教程 - JavaFX绑定
JavaFX教程 - JavaFX绑定 JavaFX绑定同步两个值:当因变量更改时,其他变量更改。 要将属性绑定到另一个属性,请调用bind()方法,该方法在一个方向绑定值。例如,当属性A绑定到属性B时,属性B的更改将更新属性A…...

IDEA+Docker一键部署项目SpringBoot项目
文章目录 1. 部署项目的传统方式2. 前置工作3. SSH配置4. 连接Docker守护进程5. 创建简单的SpringBoot应用程序6. 编写Dockerfile文件7. 配置远程部署 7.1 创建配置7.2 绑定端口7.3 添加执行前要运行的任务 8. 部署项目9. 开放防火墙的 11020 端口10. 访问项目11. 可能遇到的问…...
vue Promise使用
new Promise((resolve, reject) > { ... }) 是 JavaScript 中创建 Promise 实例的语法。Promise 是一种用于处理异步操作的对象,它代表了一个异步操作的最终完成(或失败)及其结果值。 Promise 的基本结构 javascript 深色版本 const my…...
Tomcat调优相关理解
什么是QPS? 是Queries Per Second 的缩写,是指服务器每秒查询数,比如定义一个a接口,该接口是10QPS,那么就是指该接口每秒可以处理10个请求 springboot默认并发处理数是多少? springboot并发处理要看serv…...
uni-app开发-识图小程序-主要功能以及首页实现
目录 一:功能介绍 二:代码实现 一:功能介绍 识图小程序首页主要是识图类型的展示列表,目前只有四种类型的图像识别,分别是车牌,发票,电表,身份证。可以分别识别车牌号码,身份证号码,发票号码,和电表度数。点击对应的类型图标会跳转到识图页面,每个分类上面展示该…...
vue3 ref reactive响应式数据,赋值的问题、解构失去响应式问题
在 Vue3 中,使用 ref 和 reactive 创建响应式数据时,赋值操作和解构赋值存在一些需要注意的事项。以下是对这些问题的详细解答以及代码示例: ref 和 reactive 的基本用法 ref:主要用于基本数据类型(如 Number、String、…...
算法常用库函数——C++篇
前言 本文主要记录、整理、回顾在算法考试中常用的一些库函数,技巧等,不断更新中~ list 常用方法 在一般c编程中,对于数组这样的数据结构,一般都使用vector居多,貌似list用的很少。但实际list也十分强大,…...

怎么把多个PDF合并到一起-免费实用PDF编辑处理工具分享
>>更多PDF文件处理应用技巧请前往 96缔盟PDF处理器 主页 查阅! 序言 我之前的文章也有介绍过如何使用96缔盟PDF处理器对PDF文件合并或者批量合并的介绍,但是当时是使用DMPDFUtilTool1.0版本进行的,当时的功能尚不完善,还不支…...
RFC协议简要介绍——有关TCP拥塞控制的RFC
1.RFC Request For Comments(RFC),是一系列以编号排定的文件。文件收集了有关互联网相关信息,以及UNIX和互联网社区的软件文件。RFC文件是由Internet Society(ISOC)赞助发行。基本的互联网通信协议都有在R…...

Speckly:基于Speckle文档的RAG智能问答机器人
前言 Speckly 是一个基于 检索增强生成 (RAG) 技术的智能问答机器人,它能像一位经验丰富的工程师,理解你的问题,并从 Speckle 文档中精准地找到答案。更厉害的是,它甚至可以帮你生成代码片段!🚀 本文将详…...

香橙派5Plus启动报错bug: spinlock bad magic on cpu#6, systemd-udevd/443
一、问题 如图: 接上调试串口,每次启动都会报错。不过使用过程中没有发现有什么影响。 百度查阅,有一位博主提到,但是没有细说解决方案: spinlock变量没有初始化_spinlock bad magic on-CSDN博客https://blog.csdn.n…...

电子应用设计方案74:智能家庭对讲系统设计
智能家庭对讲系统设计 一、引言 智能家庭对讲系统作为智能家居的重要组成部分,为家庭成员之间以及与访客的沟通提供了便捷、高效的方式。本设计方案旨在打造一个功能强大、稳定可靠、操作简便且具有良好扩展性的智能家庭对讲系统。 二、系统概述 1. 系统目标 - 实…...
node js 过滤空白行
data.trim().split(\n).filter(user > user); 只过滤文件开头和结尾的空白行。 data.split(\n).map(token > token.trim()).filter(token > token); 这种方法不仅移除了文件开头和结尾的空白行,还确保了每一行内部的多余空白也被清理掉。此外,…...

武泳樽携手AI AD Manager荣获红点奖,智能广告管理系统备受瞩目
近日,由著名设计师武泳樽主导设计的AI AD Manager在2024年红点奖评选中荣获大奖,这一殊荣不仅彰显了他在创新设计领域的卓越实力,更巩固了AI AD Manager作为智能广告技术标杆的地位。凭借独特的用户体验设计、尖端的AI驱动功能和出色的技术融合,AI AD Manager在激烈的国际竞争中…...
Express.js 有哪些常用的中间件?
在使用 Express.js 开发应用程序时,中间件(Middleware)是处理请求和响应的关键组件。它们可以执行各种任务,如解析请求体、添加HTTP头部、记录日志等。以下是一些常用的中间件: body-parser 用于解析传入的请求体。它…...
WordPress File Upload插件 任意文件读取漏洞复现(CVE-2024-9047)(附脚本)
0x01 产品描述: File Upload插件是一款功能强大的WordPress站点文件上传插件,它允许用户在WordPress站点中的文章、页面、侧边栏或表单中轻松上传文件到wp-contents目录中的任何位置。该插件使用最新的HTML5技术,确保在现代浏览器和移动设备上都能流畅运行,同时也兼容旧的浏…...

qt QZipReader详解
1、概述 QZipReader 是 Qt 中用于从 .zip 文件中读取和提取文件内容的类。它提供了便捷的方法来访问压缩包中的文件和目录,并允许你解压缩单个或多个文件。通过 QZipReader,你可以以编程方式读取 .zip 文件中的内容,并提取它们到目标目录中。…...

C# 超高速高性能写日志
原理 使用列队先缓存到内存,独立线程从列队中使用log4net写到磁盘上。 日志写入列队 public void EnqueueMessage(string message, FlashLogLevel level, Exception ex null) {if ((level FlashLogLevel.Debug && _log.IsDebugEnabled)|| (level Flas…...

阿里云人工智能ACA(五)——深度学习基础
一、深度学习概述 1. 深度学习概念 1-1. 深度学习基本概念 深度学习是机器学习的一个分支基于人工神经网络(模仿人脑结构)通过多层网络自动学习特征能够处理复杂的模式识别问题 1-2. 深度学习的优点与缺点 优点 强大的特征学习能力可以处理复杂问题…...

入职体检尿潜血3+能通过吗,什么原因引起
在许多行业入职体检中,尿液检测是一个重要的组成部分。尿潜血(也称为尿中血红蛋白)是尿液常规检查中一种常见的指标,其结果可以反映出身体的健康状况。当检测结果为“尿潜血3”时,很多人会感到困惑,尤其是在…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...