我正在尝试创建动态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);
}
}
}