2016-06-16 12 views
2

BeiJavaFX TextField- OnKeyTyped nicht ordnungsgemäß funktioniert

JavaFX App, Input TextField und Absenden Button

Es gibt eine EventHandler an die TextField angebracht, so dass, wenn kein Text eingegeben wird, sollte die Button deaktiviert und umge werden versa.

Hier ist mein Code:

button.setDisable(true); // initially disabled 
textField.setOnKeyTyped(new EventHandler<KeyEvent>() { 
     @Override 
     public void handle(KeyEvent event) { 
      if (textField.getText().trim().isEmpty()) { // if blank textfield 
       button.setDisable(true); 
      } else { 
       button.setDisable(false); 
      } 
     } 
}); 

Beide Steuerungen richtig initialisiert werden. Und soweit ich weiß, besteht der Unterschied zwischen KeyTyped und KeyPressed/Released darin, dass Typed für Zeichen steht, die tatsächlich eingegeben und angezeigt werden können. während Pressed/freigegeben ist für jede Tastaturtaste mit Ctrl, Alt ...

Problem

Ich tippe in die textField ein Zeichen ist die button noch deaktiviert! Wenn ich 2 Zeichen und mehr eintippe, wird es aktiviert!

Wenn jedoch, wenn ich wie folgt vorgehen:

button.setDisable(true); 
textField.setOnKeyReleased(
    /* 
    exact same code as above 
    */ 
); 

mein Problem gelöst werden.

Frage

WARUM? Wo ist der Fehler in meinem Code? Warum funktioniert KeyTyped nicht wie erwartet?

Antwort

3

Das Problem ist: in der Zeit, wenn Sie die KeyEvent behandeln, ist es nicht sicher, dass die textProperty Ihrer TextField aktualisiert wurde oder nicht.

Cleaner und sicherer Ansatz zum Hinzufügen eines Hörers für die textProperty der TextField benachrichtigt werden, wenn der Text der TextField ändert. Stellen Sie sich auch den Anwendungsfall vor, dass der Benutzer etwas Inhalt eingefügt hat: In diesem Fall gibt es überhaupt keine KeyEvent, daher bleibt Ihre Button deaktiviert.

einen Zuhörer auf Textproperty Verwendung()

button.setDisable(true); 
textField.textProperty().addListener((obj, oldVal, newVal) -> { 

    if (newVal.trim().isEmpty()) { // if blank textfield 
     button.setDisable(true); 
    } else { 
     button.setDisable(false); 
    } 
}); 

... oder noch kürzer ...

button.setDisable(true); 
textField.textProperty().addListener((obj, oldVal, newVal) -> button.setDisable(newVal.trim().isEmpty())); 

Aber die viel sauberere Lösung zwischen dem disableProperty der Bindung zu verwenden, Button und die textProperty der TextField.

eine Verwendung zwischen disableProperty und textProperty

BooleanBinding textIsEmpty = Bindings.createBooleanBinding(() -> textField.getText().trim().isEmpty(), textField.textProperty()); 
button.disableProperty().bind(textIsEmpty); 
+1

In Ihrem ersten aproach verbindlich, wenn Sie einen 'ChangeListener' wie' (obj, oldVal, newVal) -> {...} 'Sie auch Holen Sie sich den neuen Wert automatisch, ohne auf das 'textField' zurückgreifen zu müssen. Wie auch immer, +1 ... –

+0

in Ordnung.Danke, auch wenn ich immer noch nicht verstehe, warum es bei einem Charakter nicht funktioniert, aber mit mehr Charakteren! –

+2

@ rz3r0 Einfach: Der Text wurde noch nicht im 'TextField' zum Zeitpunkt des Aufrufs von' setOnKeyTyped() 'aktualisiert. Daher lesen Sie immer noch den alten (leeren) Wert. Das Steuerelement aktualisiert dann seinen Text und ruft später 'setOnKeyReleased()' auf - dort ist der neue Wert verfügbar. –