2015-02-09 93 views
0

如何为JavaFX文本字段编写ChangeListener,仅对userinput作出反应,但不对setText方法作出反应?JavaFX TextField对userinput作出反应,但不对setText()作出反应

textField.textProperty().addListener(new ChangeListener<String>() { 
    @Override 
    public void changed(ObservableValue<? extends String> observable, 
      String oldValue, String newValue) { 

     // code is executed, when user changes text, 
     // but also, when setText(..) is called 
    } 
}); 
+0

有趣的是,因为我正在寻找一种方法来使事件触发,如果文本被用户更改或setText()被调用,所以你的问题实际上回答了我的XD。谢谢! – Hatefiend 2016-01-05 22:54:45

回答

0

这样的问题总是让我觉得你的设计有些不对。文本代表一些数据;你正在注册一个监听器,因为你对数据改变感兴趣 - 它应该不是真的很重要为什么它改变了。如果确实如此,则可能需要一个属性来表示与文本字段固有属性不同的数据。

最后一点给出了一个可能的解决方案,也:

final TextField textField = new TextField(); // or injected from FXML, etc 

final StringProperty text = new SimpleStringProperty(textField.getText()); 
text.addListener(new ChangeListener<String>() { 
    @Override 
    public void changed(ObservableValue<? extends String> obs, String oldValue, String newValue) { 
     textField.setText(newValue); 
    } 
}); 

textField.textProperty().addListener(new ChangeListener<String>() { 
    @Override 
    public void changed(ObservableValue<? extends String> obs, String oldValue, String newValue) { 
     if (! newValue.equals(text.get())) { // textField's text was changed directly (i.e. by user) 
      // perform whatever action you need... 

      // update the text property so the two remain equal: 
      text.set(newValue); 
     } 
    } 
}); 

现在最重要的事情是,你永远不会调用textField.setText(...),但总是叫text.set(...)代替。这导致通过第一个监听器对textField.setText(...)进行编程式调用。这将调用第二个侦听器,但此时文本字段的新值将与自定义属性的值相同。

另一方面,如果用户键入文本字段,则会创建一个调用(在文本字段内部)调用您的侦听器的textField.textProperty().set(...)。这里新的文本字段值与您的自定义属性值不同,因此调用了代码的主要部分。

+0

谢谢你的回答。我认为你说得对,我的“设计有些不对”。 – 2015-02-24 08:06:55