如何将自定义 属性 双向绑定到文本字段?
How do I bind a custom property to a textfield bidirectionally?
我有一个复杂的对象,我想在文本字段中显示。这与 stringBinding
一起工作正常。但我不知道如何使它成为双向的,以便文本字段是可编辑的。
package com.example.demo.view
import javafx.beans.property.SimpleObjectProperty
import javafx.beans.property.SimpleStringProperty
import tornadofx.*
class MainView : View("Hello TornadoFX") {
val complexThing: Int = 1
val complexProperty = SimpleObjectProperty<Int>(complexThing)
val complexString = complexProperty.stringBinding { complexProperty.toString() }
val plainString = "asdf"
val plainProperty = SimpleStringProperty(plainString)
override val root = vbox {
textfield(complexString)
label(plainProperty)
textfield(plainProperty)
}
}
当我 运行 这样做时,plainString
是可编辑的,我看到标签发生变化,因为编辑将返回到 属性。
我如何编写自定义处理程序或者我需要使用什么class来使 stringBinding 被读取和写入?我查看了很多 属性 和绑定文档,但没有看到任何明显的内容。
这或许可以做得更干净。我敢打赌有办法绕过额外的 属性。该示例很脆弱,因为为了保持简单,它没有进行输入检查。但它可以证明解决方案:
class Point(x: Int, y: Int) {
val x: Int = x
val y: Int = y
}
class PointConverter: StringConverter<Point?>() {
override fun fromString(string: String?): Point? {
val xy = string?.split(",")
return Point(xy[0].toInt(), xy[1].toInt())
}
override fun toString(point: Point?): String {
return "${point?.x},${point?.y}"
}
}
class MainView : View("Hello TornadoFX") {
val point = Point(5, 6)
val pointProperty = SimpleObjectProperty<Point>(point)
val pointDisplayProperty = SimpleStringProperty()
val pointStringProperty = SimpleStringProperty()
val pc = PointConverter()
init {
pointDisplayProperty.set(pc.toString(pointProperty.value))
pointStringProperty.set(pc.toString(pointProperty.value))
pointStringProperty.addListener { observable, oldValue, newValue ->
pointProperty.set(pc.fromString(newValue))
pointDisplayProperty.set(pc.toString(pointProperty.value))
}
}
override val root = vbox {
label(pointDisplayProperty)
textfield(pointStringProperty)
}
}
他-达
class Point(val x: Int, val y: Int) //You can put properties in constructor
class PointConverter: StringConverter<Point?>() {
override fun fromString(string: String?): Point? {
if(string.isNullOrBlank()) return null //Empty strings aren't valid
val xy = string.split(",", limit = 2) //Only using 2 coordinate values so max is 2
if(xy.size < 2) return null //Min values is also 2
val x = xy[0].trim().toIntOrNull() //Trim white space, try to convert
val y = xy[1].trim().toIntOrNull()
return if(x == null || y == null) null //If either conversion fails, count as invalid
else Point(x, y)
}
override fun toString(point: Point?): String {
return "${point?.x},${point?.y}"
}
}
class MainView : View("Hello TornadoFX") {
val point = Point(5, 6) //Probably doesn't need to be its own member
val pointProperty = SimpleObjectProperty<Point>(point)
val pc = PointConverter()
override val root = vbox {
label(pointProperty, converter = pc) //Avoid extra properties, put converter in construction
textfield(pointProperty, pc)
}
}
我将您的转换器编辑为 "account" 以通过仅返回 null 进行无效输入。这只是一个简单的创可贴解决方案,不会强制输入正确的内容,但它会拒绝在您的 属性.
中输入错误的值
我有一个复杂的对象,我想在文本字段中显示。这与 stringBinding
一起工作正常。但我不知道如何使它成为双向的,以便文本字段是可编辑的。
package com.example.demo.view
import javafx.beans.property.SimpleObjectProperty
import javafx.beans.property.SimpleStringProperty
import tornadofx.*
class MainView : View("Hello TornadoFX") {
val complexThing: Int = 1
val complexProperty = SimpleObjectProperty<Int>(complexThing)
val complexString = complexProperty.stringBinding { complexProperty.toString() }
val plainString = "asdf"
val plainProperty = SimpleStringProperty(plainString)
override val root = vbox {
textfield(complexString)
label(plainProperty)
textfield(plainProperty)
}
}
当我 运行 这样做时,plainString
是可编辑的,我看到标签发生变化,因为编辑将返回到 属性。
我如何编写自定义处理程序或者我需要使用什么class来使 stringBinding 被读取和写入?我查看了很多 属性 和绑定文档,但没有看到任何明显的内容。
这或许可以做得更干净。我敢打赌有办法绕过额外的 属性。该示例很脆弱,因为为了保持简单,它没有进行输入检查。但它可以证明解决方案:
class Point(x: Int, y: Int) {
val x: Int = x
val y: Int = y
}
class PointConverter: StringConverter<Point?>() {
override fun fromString(string: String?): Point? {
val xy = string?.split(",")
return Point(xy[0].toInt(), xy[1].toInt())
}
override fun toString(point: Point?): String {
return "${point?.x},${point?.y}"
}
}
class MainView : View("Hello TornadoFX") {
val point = Point(5, 6)
val pointProperty = SimpleObjectProperty<Point>(point)
val pointDisplayProperty = SimpleStringProperty()
val pointStringProperty = SimpleStringProperty()
val pc = PointConverter()
init {
pointDisplayProperty.set(pc.toString(pointProperty.value))
pointStringProperty.set(pc.toString(pointProperty.value))
pointStringProperty.addListener { observable, oldValue, newValue ->
pointProperty.set(pc.fromString(newValue))
pointDisplayProperty.set(pc.toString(pointProperty.value))
}
}
override val root = vbox {
label(pointDisplayProperty)
textfield(pointStringProperty)
}
}
他-达
class Point(val x: Int, val y: Int) //You can put properties in constructor
class PointConverter: StringConverter<Point?>() {
override fun fromString(string: String?): Point? {
if(string.isNullOrBlank()) return null //Empty strings aren't valid
val xy = string.split(",", limit = 2) //Only using 2 coordinate values so max is 2
if(xy.size < 2) return null //Min values is also 2
val x = xy[0].trim().toIntOrNull() //Trim white space, try to convert
val y = xy[1].trim().toIntOrNull()
return if(x == null || y == null) null //If either conversion fails, count as invalid
else Point(x, y)
}
override fun toString(point: Point?): String {
return "${point?.x},${point?.y}"
}
}
class MainView : View("Hello TornadoFX") {
val point = Point(5, 6) //Probably doesn't need to be its own member
val pointProperty = SimpleObjectProperty<Point>(point)
val pc = PointConverter()
override val root = vbox {
label(pointProperty, converter = pc) //Avoid extra properties, put converter in construction
textfield(pointProperty, pc)
}
}
我将您的转换器编辑为 "account" 以通过仅返回 null 进行无效输入。这只是一个简单的创可贴解决方案,不会强制输入正确的内容,但它会拒绝在您的 属性.
中输入错误的值