JavaFX 2.2 TextField maxlength

2019-01-18 13:53发布

I am working with a JavaFX 2.2 project and I have a problem using the TextField control. I want to limit the characters that users will enter to each TextField but I can't find a property or something like maxlength. The same problem was existing to swing and was solved with this way. How to solve it for JavaFX 2.2?

8条回答
三岁会撩人
2楼-- · 2019-01-18 14:03

I'm using a simpler way to both limit the number of characters and force numeric input:

public TextField data;
public static final int maxLength = 5;

data.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable,
            String oldValue, String newValue) {
        try {
            // force numeric value by resetting to old value if exception is thrown
            Integer.parseInt(newValue);
            // force correct length by resetting to old value if longer than maxLength
            if(newValue.length() > maxLength)
                data.setText(oldValue);
        } catch (Exception e) {
            data.setText(oldValue);
        }
    }
});
查看更多
戒情不戒烟
3楼-- · 2019-01-18 14:05

The code below will re-position the cursor so the user doesn't accidentally overwrite their input.

public static void setTextLimit(TextField textField, int length) {
    textField.setOnKeyTyped(event -> {
        String string = textField.getText();

        if (string.length() > length) {
            textField.setText(string.substring(0, length));
            textField.positionCaret(string.length());
        }
    });
}
查看更多
孤傲高冷的网名
4楼-- · 2019-01-18 14:09

The full code i used to solve my problem is the code below. I extend the TextField class like Sergey Grinev done and i added an empty constructor. To set the maxlength i added a setter method. I first check and then replace the text in the TextField because i want to disable inserting more than maxlength characters, otherwise the maxlength + 1 character will be inserted at the end of the TextField and the first charcter of the TextField will be deleted.

package fx.mycontrols;

public class TextFieldLimited extends TextField {  
    private int maxlength;
    public TextFieldLimited() {
        this.maxlength = 10;
    }
    public void setMaxlength(int maxlength) {
        this.maxlength = maxlength;
    }
    @Override
    public void replaceText(int start, int end, String text) {
        // Delete or backspace user input.
        if (text.equals("")) {
            super.replaceText(start, end, text);
        } else if (getText().length() < maxlength) {
            super.replaceText(start, end, text);
        }
    }

    @Override
    public void replaceSelection(String text) {
        // Delete or backspace user input.
        if (text.equals("")) {
            super.replaceSelection(text);
        } else if (getText().length() < maxlength) {
            // Add characters, but don't exceed maxlength.
            if (text.length() > maxlength - getText().length()) {
                text = text.substring(0, maxlength- getText().length());
            }
            super.replaceSelection(text);
        }
    }
}

Inside the fxml file i added the import (of the package that the TextFieldLimited class is existing) on the top of the file and replace the TextField tag with the custom TextFieldLimited.

<?import fx.mycontrols.*?>
.  
.  
. 
<TextFieldLimited fx:id="usernameTxtField" promptText="username" />

Inside the controller class,

on the top (property declaration),
@FXML
private TextFieldLimited usernameTxtField;

inside the initialize method,
usernameTxtField.setLimit(40);

That's all.

查看更多
别忘想泡老子
5楼-- · 2019-01-18 14:12

You can do something similar to approach described here: http://fxexperience.com/2012/02/restricting-input-on-a-textfield/

class LimitedTextField extends TextField {

    private final int limit;

    public LimitedTextField(int limit) {
        this.limit = limit;
    }

    @Override
    public void replaceText(int start, int end, String text) {
        super.replaceText(start, end, text);
        verify();
    }

    @Override
    public void replaceSelection(String text) {
        super.replaceSelection(text);
        verify();
    }

    private void verify() {
        if (getText().length() > limit) {
            setText(getText().substring(0, limit));
        }

    }
};
查看更多
男人必须洒脱
6楼-- · 2019-01-18 14:16

With java8u40 we got a new class TextFormatter: one of its main responsibilities is to provide a hook into any change of text input before it gets comitted to the content. In that hook we can accept/reject or even change the proposed change.

The requirement solved in the OP's self-answer is

  • the rule: restrict the length of text to shorter than n chars
  • the modification: if the rule is violated, keep the last n chars as the input text and remove the excess chars at its start

Using a TextFormatter, this could be implemented like:

// here we adjust the new text 
TextField adjust = new TextField("scrolling: " + len);
UnaryOperator<Change> modifyChange = c -> {
    if (c.isContentChange()) {
        int newLength = c.getControlNewText().length();
        if (newLength > len) {
            // replace the input text with the last len chars
            String tail = c.getControlNewText().substring(newLength - len, newLength);
            c.setText(tail);
            // replace the range to complete text
            // valid coordinates for range is in terms of old text
            int oldLength = c.getControlText().length();
            c.setRange(0, oldLength);
        }
    }
    return c;
};
adjust.setTextFormatter(new TextFormatter(modifyChange));

Asides:

  • modifying a property while listening to its change might lead to unexpected side-effects
  • all suggested solutions on the key-level events are broken (they can't handle paste/programatic changes
查看更多
祖国的老花朵
7楼-- · 2019-01-18 14:20

I have this bit of code that only allows numbers and limits the input length on a text field in Javafx.

// Event handler for inputPrice
     inputPrice.setOnAction(event2 -> {

            // Obtain input as a String from text field
            String inputPriceStr = inputPrice.getText();

            // Get length of the String to compare with max length
            int length = inputPrice.getText().length();

            final int MAX = 10; // limit number of characters

            // Validate user input allowing only numbers and limit input size
            if (inputPriceStr.matches("[0-9]*") && length < MAX ) {

                 // your code here
             }});
查看更多
登录 后发表回答