我希望在JavaFX中实现类似于函数响应式编程的东西,我认为由于JavaFX已经支持属性之间的监听和绑定,所以这应该很容易实现。因此,我创建了一个小型的绑定转换框架,例如,我现在能够做到像下面这样(虽然这是Scala的示例,但应该可以理解我的意思):
val property1: Property[String]
val property2: Property[Path]
Bindings.Conversions
.bindUni(property1).to(property2)
.using(p => p.getFileName.toString)
.connect()
我这里绑定了
property2
的值(它是一个java.nio.file.Path
),通过一个转换函数将路径的最后一部分转换为字符串并赋值给property1
;实现真的很简单(即使是双向绑定也是如此;我只是从openjfx的BidirectionalBinding
类中取了一些代码,将其翻译成Scala并进行了适当的转换),令人惊讶的是,为什么JavaFX中没有这样的功能。这一切都很好地运作,我甚至可以创建这种绑定的复杂链条。 除非转换函数依赖于一些外部状态,否则一切都正常。
例如,假设您有以下绑定链:
Text field value -1-> intermediate java.nio.file.Path -2-> another String --> Label
当文本字段发生变化时,Path
和String
会自动重新计算,并将String属性的值写入标签。一切都很好。但是假设-2->
转换应该取决于某个复选框的切换状态:
Checkbox state ---+
|
Text field value -1-> intermediate java.nio.file.Path -2-> another String --> Label
即当复选框被选中时,变换应该稍有不同。直接实现这样的构造显然行不通,因为复选框状态的更改不会切换转换链的重新计算。然而,我发现JavaFX没有提供任何强制更改事件的方法。例如,我尝试重写SimpleStringProperty,并公开其fireValueChangedEvent()方法,但这没有帮助。目前,我做的是像textField.setText(""); textField.setText(oldValue); 但这非常丑陋,显然不是正确的方法。我是否遗漏了什么,真的可以做到我想要的事情,或者根本没有这样的东西,我完全被困在这里?如果回答是否定的,那么我认为这严重损害了整个框架的表达能力。我理解我确实可以通过一些监听器来完成想要的操作,但这将非常丑陋,我想让整个过程尽可能通用。