我根据此处发布的此前代码(Filter users values on TextField input after a BindDirectional strategy betwen a Slider and min/max TextField)
发布了新问题我的目标很简单,在用户在我的值上丢失焦点事件后,撤消错误TextField
值(基于自定义验证)的最佳方法是什么。
唯一的方法是在用户用另一个焦点事件覆盖之前访问oldValue吗?
其实我有这个简单的代码:
val myTextField = new TextField ()
def parseDouble(s: String) = try {
Some(s.toDouble)
} catch {
case _ ⇒ None
}
myTextField.focusedProperty().addListener(
new ChangeListener[java.lang.Boolean]() {
override def changed(observable: ObservableValue[_ <: java.lang.Boolean], oldValue: java.lang.Boolean, newValue: java.lang.Boolean) {
if (!newValue) {
parseDouble(myTextField.textProperty().get()) match {
case Some(d: Double) ⇒ // test on the double value entered by user
case _ ⇒ // code to reset to old value ??
}
}
}
})
更新1:
我在此处找到讨论:https://forums.oracle.com/forums/thread.jspa?threadID=2382472关于撤消textField / TextArea的功能以及其他有关TextInputControlBehavior
的源代码:https://forums.oracle.com/forums/thread.jspa?threadID=2438759&tstart=45
我在javafx 2.2中找到了对javafx 2.2实现的撤消行为的描述http://javafx-jira.kenai.com/browse/RT-7547,但我找不到示例代码......
更新2:
我在TextInputControl
找到了针对公共撤消控制API(针对2.2.6固定的路线图)的帖子:http://javafx-jira.kenai.com/browse/RT-26575
TextInputBehaviorControl
可以在这里看到:https://bitbucket.org/shemnon/openjfx-rt/src/6696e9cea59c401d2637d82f9cf96a515d210203/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextInputControlBehavior.java
更新3:
Tadam!
最后我发现了一种可怕的方法,我希望公共API适用于2.2.6版本的javaFX ......
val myTextField = new TextField ()
def parseDouble(s: String) = try {
Some(s.toDouble)
} catch {
case _ ⇒ None
}
myTextField.focusedProperty().addListener(
new ChangeListener[java.lang.Boolean]() { db ⇒
override def changed(observable: ObservableValue[_ <: java.lang.Boolean], oldValue: java.lang.Boolean, newValue: java.lang.Boolean) {
if (!newValue) {
parseDouble(myTextField.textProperty().get()) match {
case Some(d: Double) ⇒
if (myTextField.minValue > d || d > myTextField.maxValue) {
doubleField.getSkin.asInstanceOf[TextInputControlSkin[_, _]].getBehavior.asInstanceOf[TextInputControlBehavior[_]].callAction("Undo")
} else {
// Here you change value property of textField
}
case _ ⇒ myTextField.getSkin.asInstanceOf[TextInputControlSkin[_, _]].getBehavior.asInstanceOf[TextInputControlBehavior[_]].callAction("Undo")
}
}
}
})
如果有人找到更好的方法,我会验证答案:)
答案 0 :(得分:1)
由于我目前正在使用Scala解决方案开发JavaFX,我想尝试一下您的示例,但我无法编译它。具体来说,doubleField
和value.set
未知!
我有一些提示 - 第一:有明显的代码重复,可以通过在案例中添加条件来轻松解决 - 第一种情况仅在条件(范围内的d)满足时才成立
case Some(d: Double) if (doubleField.minValue <= d && d <= doubleField.maxValue) ⇒
value.set(d)
case _ ⇒
doubleField.getSkin.asInstanceOf[TextInputControlSkin[_, _]].getBehavior.asInstanceOf[TextInputControlBehavior[_]].callAction("Undo")
第二:为Java中的匿名内部类提供一个包装器 - 例如,上面的ChangeListener可以像这样包装:
implicit def unit2ChangeListener[T](f: (ObservableValue[_ <: T], T, T) => Unit) =
new ChangeListener[T] {
override def changed(observable: ObservableValue[_ <: T], oldValue: T, newValue: T) {
f(observable, oldValue, newValue)
}
}
这些隐式转换可以隐藏在util类中(以及一个不错的unit2EventHandler)并导入到您的应用程序中。 这会导致更具可读性(但仍然有点痛苦):
myTextField.focusedProperty().addListener(
(observable: ObservableValue[_ <: java.lang.Boolean],
oldValue: java.lang.Boolean, newValue: java.lang.Boolean) =>
if (!newValue) { ... }
)
可能ScalaFx已经提供了类似的内容,但我还没有尝试过。