Frage

Ich muss ein Zahlenfeld in meine Benutzeroberfläche einfügen. Daher muss ich die Schlüsselereignisse in einem Textfeld überprüfen, um zu überprüfen, ob das Eingabezeichen eine Zahl ist. Ich habe eine Klasse erstellt, indem ich Textfield erweitert. Wenn in der Textfeldklasse eine Methode vorhanden ist, die KeyEvents verarbeitet, kann ich diese Methode einfach mit Anzügen zu Zahlenfeld übergeben. Irgendwelche Ideen?

Vielen Dank

War es hilfreich?

Lösung 4

Fand eine Lösung. :)

public class NumFieldFX extends TextField {
   public NumFieldFX() {
      this.addEventFilter(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
         public void handle( KeyEvent t ) {
            char ar[] = t.getCharacter().toCharArray();
            char ch = ar[t.getCharacter().toCharArray().length - 1];
            if (!(ch >= '0' && ch <= '9')) {
               System.out.println("The char you entered is not a number");
               t.consume();
            }
         }
      });
   }
}

Andere Tipps

Update 27. Mai 2016

Java 8u40 stellte die vor TextFormatter Klasse, die die empfohlene Methode zur Durchführung dieser Funktionalität ist (obwohl die in dieser Antwort bereitgestellte Lösung weiterhin funktioniert). Weitere Informationen finden Sie unter UWEs Antwort, Hassans Antwort und andere Antworten, in denen TextFormatier der folgenden Frage erwähnt wird:

Es gibt auch diese Lösung aus einer anderen Antwort auf diese Frage, die ich nicht ausprobiert habe, aber gut aussieht und ein Stackoverflow -Moderator gelöscht habe:

TextField numberField = new TextField();
numberField.setTextFormatter(new TextFormatter<>(new NumberStringConverter()));

Der obige Code verfehlt den Unaryoperator -Filter für die Textformatter, die Sie normalerweise auch benötigen ). Um die Lösung für die Verwendung eines Filters zu erweitern, kann der folgende Code wie diesen verwendet werden:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.stage.Stage;
import javafx.util.converter.NumberStringConverter;

import java.text.ParsePosition;
import java.util.function.UnaryOperator;

public class NumberConverterFieldTest extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        TextField numberField = new TextField();
        NumberStringFilteredConverter converter = new NumberStringFilteredConverter();
        final TextFormatter<Number> formatter = new TextFormatter<>(
                converter,
                0,
                converter.getFilter()
        );

        numberField.setTextFormatter(formatter);

        formatter.valueProperty().addListener((observable, oldValue, newValue) ->
                System.out.println(newValue)
        );

        stage.setScene(new Scene(numberField));
        stage.show();
    }

    class NumberStringFilteredConverter extends NumberStringConverter {
        // Note, if needed you can add in appropriate constructors 
        // here to set locale, pattern matching or an explicit
        // type of NumberFormat.
        // 
        // For more information on format control, see 
        //    the NumberStringConverter constructors
        //    DecimalFormat class 
        //    NumberFormat static methods for examples.
        // This solution can instead extend other NumberStringConverters if needed
        //    e.g. CurrencyStringConverter or PercentageStringConverter.

        public UnaryOperator<TextFormatter.Change> getFilter() {
            return change -> {
                String newText = change.getControlNewText();
                if (newText.isEmpty()) {
                    return change;
                }

                ParsePosition parsePosition = new ParsePosition( 0 );
                Object object = getNumberFormat().parse( newText, parsePosition );
                if ( object == null || parsePosition.getIndex() < newText.length()) {
                    return null;
                } else {
                    return change;
                }
            };
        }
    }
}

Bearbeiten Sie beim Ausführen des obigen Beispiels das Eingabebuch und drücken System.out wenn geändert).

Für ein Tutorial siehe:


Dies ist dieselbe Lösung, die sich verweist. Ich habe sie jedoch gerade in ein vollständig ausführbares Programm platziert, um ein Beispiel im Kontext anzugeben, und den regulären Ausdruck geändert (durch Hinzufügen * am Ende), damit das Kopieren und Einfügen funktioniert und nicht das Problem hat, auf das Uluk bezieht. Die Lösung scheint ziemlich einfach und wird wahrscheinlich für die meisten Zwecke ausreichen:

import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

public class NumericTextFieldTest extends Application {
  public static void main(String[] args) { launch(args); }

  @Override public void start(Stage stage) {
    TextField numberField = new TextField() {
      @Override public void replaceText(int start, int end, String text) {
        if (text.matches("[0-9]*")) {
          super.replaceText(start, end, text);
        }
      }

      @Override public void replaceSelection(String text) {
        if (text.matches("[0-9]*")) {
          super.replaceSelection(text);
        }
      }
    };

    stage.setScene(new Scene(numberField));
    stage.show();
  }
}

Alternative Lösungen

Möglicherweise interessieren Sie sich auch für meine alternative Lösung in Javafx Beispiel für die Bindung eines Schiebereglerwerts an ein bearbeitbares Textfeld. In dieser Lösung erweitere ich das Textfeld, um eine IntegerProperty auf dem Feld für einfache Bindungszwecke aufzudecken. Die alternative Lösung ähnelt dem, das durch das ursprüngliche Poster in ihrer aktualisierten Frage beschrieben wurde (dh ein Ereignisfilter wird hinzugefügt, um Eingabedaten aus Schlüsselereignissen einzuschränken), aber zusätzlich wird ein ChangeListener auf der Texteigenschaft des Textfield hinzugefügt, um sicherzustellen werden nur akzeptiert, wenn sie numerisch sind.

Es gibt einige andere Lösungen für diese Frage im Javafx Forum -Thread Numerisches Textfeld in Javafx 2.0? welches einen Verweis auf die enthält Zahlenfelder von FXExperience -Steuerelementen.

Es gibt ein Tipp an Fxexperience Das befasst sich einfach mit einem solchen Problem. Um zu paraphrasieren, erweitern Sie die TextField und überschreiben die replaceText() und replaceSelection() Methoden, filtern alle Eingaben, die keine Zahl sind.

Nach der Implementierung sollten beide Methoden dieser Vorlage folgen:

if (!newText.matches("[0-9]")) {
    super.call(allParams)
}

Hier ist das benutzerdefinierte Feld, das ich geschrieben habe. Es behandelt beide Zahlen nur Eingabe und auch maximal. Es ist eine benutzerdefinierte Steuerung, die in FXML verwendet werden kann, und auch die Eigenschaften können in FXML selbst eingestellt werden.

package fxml;

import javafx.beans.property.BooleanProperty; 
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.IntegerPropertyBase;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.TextField;

public class CustomTextField extends TextField {

/**
 * numericOnly property if set, will allow accept only numeric input.
 */
private BooleanProperty numericOnly = new SimpleBooleanProperty(this,
        "numericOnly", false);

public final boolean isNumericOnly() {
    return numericOnly.getValue();
}

public final void setNumericOnly(boolean value) {
    numericOnly.setValue(value);
}

public final BooleanProperty numericOnlyProperty() {
    return numericOnly;
}

/**
 * maxSize property , determines the maximum size of the text that can be
 * input.
 */
public IntegerProperty maxSize = new IntegerPropertyBase(1000) {

    @Override
    public String getName() {
        return "maxSize";
    }

    @Override
    public Object getBean() {
        return CustomTextField.this;
    }
};

public final IntegerProperty maxSizeProperty() {
    return maxSize;
};

public final int getMaxSize() {
    return maxSize.getValue();
}

public final void setMaxSize(int value) {
    maxSize.setValue(value);
}

/**
 * this method is called when user inputs text into the textField
 */
@Override
public void replaceText(int start, int end, String text) {
    if (numericOnly.getValue() && !text.equals("")) {
        if (!text.matches("[0-9]")) {
            return;
        }
    }
    if (getText().length() < getMaxSize() || text.equals("")) {
        super.replaceText(start, end, text);
    }
}

/**
 * this method is called when user pastes text into the textField
 */
@Override
public void replaceSelection(String text) {
    if (numericOnly.getValue() && !text.equals("")) {
        if (!text.matches("[0-9]+")) {
            return;
        }
    }
    super.replaceSelection(text);
    if (getText().length() > getMaxSize()) {
        String maxSubString = getText().substring(0, getMaxSize());
        setText(maxSubString);
        positionCaret(getMaxSize());
    }
}

}

Für eine Reihe von Textfilmen (Dezimalpunkt enthalten)

Arrays.asList(txtLongitude, txtLatitude, txtAltitude, txtSpeed, txtOrientation).forEach(textField ->
            textField.textProperty().addListener((observable, oldValue, newValue) ->
                    textField.setText(newValue.matches("^[0-9]*\\.?[0-9]*$") ? newValue : oldValue)
            ));

Kombinierte Baijifeilong- und Ajay Prakash -Lösung zur Unterstützung von Dezimaleingaben

package com.mazeworks.cloudhms.view.components;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.IntegerPropertyBase;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.TextField;

public class NumericTextField extends TextField {

    /**
     * numericOnly property if set, will allow accept only numeric input.
     */
    private BooleanProperty numericOnly = new SimpleBooleanProperty(this,
            "numericOnly", false);

    public final boolean isNumericOnly() {
        return numericOnly.getValue();
    }

    public final void setNumericOnly(boolean value) {
        numericOnly.setValue(value);
    }

    public final BooleanProperty numericOnlyProperty() {
        return numericOnly;
    }

    /**
     * maxSize property, determines the maximum size of the text that 
     can be
     * input.
     */
    public IntegerProperty maxSize = new IntegerPropertyBase(1000) {

        @Override
        public String getName() {
            return "maxSize";
        }

        @Override
        public Object getBean() {
            return NumericTextField.this;
        }
    };

    public final IntegerProperty maxSizeProperty() {
        return maxSize;
    }

    ;

    public final int getMaxSize() {
        return maxSize.getValue();
    }

    public final void setMaxSize(int value) {
        maxSize.setValue(value);
    }

    /**
     * this method is called when user inputs text into the textField
     */
    @Override
    public void replaceText(int start, int end, String text) {
        if (numericOnly.getValue() && !text.equals("")) {
            if (!text.matches("^[0-9]*\\.?[0-9]*$")) {
                return;
            }
        }
        if (getText().length() < getMaxSize() || text.equals("")) {
            super.replaceText(start, end, text);
        }
    }

    /**
     * this method is called when user pastes text into the textField
     */
    @Override
    public void replaceSelection(String text) {
        if (numericOnly.getValue() && !text.equals("")) {
            if (!text.matches("^[0-9]*\\.?[0-9]*$")) {
                return;
            }
        }
        super.replaceSelection(text);
        if (getText().length() > getMaxSize()) {
            String maxSubString = getText().substring(0, getMaxSize());
            setText(maxSubString);
            positionCaret(getMaxSize());
        }
    }
}

Geerbt von Textfeld und überschreiben Austausch Um einen Doppelwerte nur für Textfeld zu erhalten:

@Override
public void replaceText(int start, int end, String text) {
    String preText = getText(0, start);
    String afterText = getText(end, getLength());
    String toBeEnteredText = preText + text + afterText;

    // Treat the case where the user inputs proper text and is not inputting backspaces or other control characters
    // which would be represented by an empty text argument:
    if (!text.isEmpty() && text.matches("\\d|\\.")) {
        Logger.getAnonymousLogger().info("Paring non-empty.");
        try {
            Logger.getAnonymousLogger().info("Parsing " + toBeEnteredText);
            Double.parseDouble(toBeEnteredText);
            super.replaceText(start, end, text);
        } catch (Exception ignored) {
        }
    }

    // If the user used backspace or del, the result text is impossible to not parse as a Double/Integer so just
    // enter that text right ahead:
    if (text.isEmpty()) {
        super.replaceText(start, end, text);
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top