2015-02-09 115 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