如何将通配符附加到JTextField,然后在填充时删除?

时间:2017-04-17 14:37:10

标签: java swing jtextfield documentfilter

我正在尝试创建动态JTextField。此JTextField在未填充其最大字符时附加通配符('*')。我想删除这个通配符,当它有最大字符时,但是如果用户退格,我希望再次附加通配符。通配符也应该是“永久的”,因为它不能被删除或退格,并且插入位置应该在通配符之前开始。

TLDR; JTextField中附加的动态通配符

我到目前为止(2017年4月17日)
Program initalizes
JTextField with max characters

此JTextField是字母数字,其最大字符数为10.我希望它能够在达到10时删除通配符。如果我退格,它应该再次附加。

问题是通配符永久存在。每当我输入任何东西时,如果它是最大字符。

AlphaNumericTextField.java

public class AlphaNumericTextField extends DocumentFilter{
    int maxDigits;

    public AlphaNumericTextField(int maxDigits) {
        this.maxDigits = maxDigits;
    }

    public void AlphaNumericTextField(){
        this.maxDigits = Integer.MAX_VALUE;
    }

    @Override
    public void insertString(FilterBypass fb, int off, String str, AttributeSet attr) throws BadLocationException {
        if(str == null)
            return;
        if ((fb.getDocument().getLength() + str.length()-1) <= maxDigits) {
            fb.insertString(off, str.replaceAll("[^\\w*]", ""), attr);
        }
    } 

    @Override
    public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr) throws BadLocationException {
        if(str == null)
            return;
        if ((fb.getDocument().getLength() + str.length()-1 - len) <= maxDigits) {
            fb.replace(off, len, str.replaceAll("[^\\w*]", ""), attr);
        }
    }
}

WildCard.java(NavigationFilter)
NavigationFilter是我令人难以置信的临时尝试,使通配符“永久”或“不可编辑”。

public class WildCard extends NavigationFilter
{
    private Action deletePrevious;
    private Action deleteNext;
    public JTextComponent component;

    public WildCard(JTextComponent component)
    {
        this.component = component;
        deletePrevious = component.getActionMap().get("delete-previous");
        deleteNext = component.getActionMap().get("delete-next");
        component.getActionMap().put("delete-previous", new BackspaceAction());
        component.getActionMap().put("delete-next", new DeleteAction());
        component.setCaretPosition(0);
    }

    public void setDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
    {
        if(dot < component.getText().length()) {
            fb.setDot(Math.min(dot, component.getText().length()), bias);
        }
    }

    public void moveDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
    {
        if(dot < component.getText().length()) 
            fb.moveDot(Math.min(dot, component.getText().length()), bias);
    }

    class BackspaceAction extends AbstractAction
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            JTextComponent component = (JTextComponent)e.getSource();
            if (component.getCaretPosition() > 0)
                deletePrevious.actionPerformed( null );
        }
    }

    class DeleteAction extends AbstractAction
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            JTextComponent component = (JTextComponent)e.getSource();
            if (component.getCaretPosition() < component.getText().length()-1)
                deleteNext.actionPerformed( null );
        }
    }
}

资源和我看过的地方:
Limited selection in a JTextField/JTextComponent?
How to implement in Java ( JTextField class ) to allow entering only digits?
remove last character from jtextfield

由于复制和粘贴信息,我看到许多地方阻止了keyListeners。我也看到了一个处理propertyChangeListener的解决方案,但是我无法解决这个问题。

我也试过了两个:

setText(getText().substring(0, getText().length() - 1)) 
setText(getText.replaceAll("*", ""))

然而,这是一个奇怪的问题,插入符号一直重新开始索引0然后我开始向后输入我的JTextField。另一个问题是由于我的NavigationFilter。删除通配符后,我无法编辑最后一位数字。

当前环境
- NetBeans IDE 8.2(用于GUI生成器)
- Java 1.8.0_111

附加说明
我希望实施的一个粗略的例子......
'|'符号是插入符号,本例中的最大字符为6:

a|*  
ab|* 
abc|*
abc1|*
abc12|*
abc123| (NO WILDCARD)
abc12|* (Backspaced, so there is a wildcard) 
OR
ab|123* (Deleted some character so the length is less than 6)

非常感谢你!

修改 这是解决方案。非常感谢你!

public class AlphaNumericTextField extends DocumentFilter{
    int maxChar;
    JTextComponent field;

    public AlphaNumericTextField(int maxChar, JTextComponent field) {
        this.maxChar = maxChar;
        this.field = field;
    }

    public void AlphaNumericTextField(){
        this.maxChar = Integer.MAX_VALUE;
    }

    @Override
    public void insertString(FilterBypass fb, int off, String str, AttributeSet attr) 
        throws BadLocationException {
        if(str == null)
            return;
        fb.insertString(off, str.replaceAll("[^\\w*]", ""), attr);
    } 
    @Override
    public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr) 
        throws BadLocationException {
        if(str == null)
            return;
        if ((fb.getDocument().getLength() + str.length()-1 - len) < maxChar) {
            if(fb.getDocument().getText(0, fb.getDocument().getLength()).indexOf("*") == -1) {
                fb.replace(off, len, str.replaceAll("[^\\w*]", "") + "*", attr);
                field.setCaretPosition(off+str.length());
            }
            else {
                fb.replace(off, len, str.replaceAll("[^\\w*]", ""), attr);
            }            
        }
        else if ((fb.getDocument().getLength() + str.length()-1 - len) == maxChar) {
            fb.replace(off, len+1, str, attr);
        }
    }

    @Override
    public void remove(DocumentFilter.FilterBypass fb, int off, int len) throws BadLocationException{
        fb.remove(off, len);
        if (off == maxChar - 1) {
            // Not really sure why this works... Adds 2 asterisks if field.getText() + "*"
            field.setText(field.getText());
            field.setCaretPosition(off);
        }
    }

}

0 个答案:

没有答案