JTextField 接受两倍的输入,但为什么呢?
JTextField take twice the input, but why?
我想制作一个可编程计算器,我有基本的 GUI,现在我正在尝试设置按钮和显示器。我的显示文本基本上是“0”,如果用户输入一个数字,应该显示该数字。我试着用 KeyListener 来做,但如果我按下一个键,它会显示两次。为什么?
textField.addKeyListener(new KeyListener(){
boolean newNumber = true;
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode == e.VK_BACK_SPACE && textField.getText().length() == 1){
textField.setText("0");
newNumber = true;
}
if(textField.getText().equals("0") && newNumber){
textField.setText(KeyEvent.getKeyText(keyCode));
newNumber = false;
}
}
public void keyReleased(KeyEvent e) {
}
});
输入前:
输入“1”后:
为此,我像这样导出 PlainDocument:
import java.awt.EventQueue;
import java.util.regex.Pattern;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
public class DigitDocument extends PlainDocument {
private static final long serialVersionUID = 1L;
protected static final Pattern patternStartZero = Pattern.compile("^0.+");
protected final JTextField textField;
private final int limit;
private final Runnable runnableFormat;
public DigitDocument(JTextField textField, int limit) {
super();
this.textField = textField;
this.limit = limit;
runnableFormat = new Runnable() {
@Override
public void run() {
String text = textField.getText();
if (text.length() == 0) {
textField.setText("0");
}
else if (patternStartZero.matcher(text).matches()) {
textField.setText(text.replaceAll("^0+", ""));
}
}
};
}
@Override
public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
str = str.replaceAll("[^0-9]", "");
if (str.length() == 0)
return;
else if ((getLength() + str.length()) <= limit)
super.insertString(offset, str, attr);
EventQueue.invokeLater(runnableFormat);
}
@Override
public void remove(int offs, int len) throws BadLocationException {
if (!"0".equals(textField.getText()))
super.remove(offs, len);
EventQueue.invokeLater(runnableFormat);
}
}
用法是:
textField.setDocument(new DigitDocument(textField, 10));
textField.setText("0");
在数字文档中,
- 第一个参数是 JTextField 本身。
- 第二个arg(10)是最大输入长度,
您只能输入数字。
这里有一个简单的解决方案:
如果你使用 keyPressed
,你必须在 keyReleased
中做一些事情,这就变成了
复杂的。 keyTyped
是一种更简单的方法。
您可以使用 e.consume()
来防止插入两位数。
textField.addKeyListener(new KeyListener() {
int codeDelete = KeyEvent.getExtendedKeyCodeForChar(KeyEvent.VK_DELETE);
int codeBackSpace = KeyEvent.getExtendedKeyCodeForChar(KeyEvent.VK_BACK_SPACE);
@Override
public void keyTyped(KeyEvent e) {
char keyChar = e.getKeyChar();
if (textField.getText().length() == 0) {
textField.setText("0");
}
else if (textField.getText().equals("0") && keyChar != codeDelete && keyChar != codeBackSpace) {
textField.setText(String.valueOf(e.getKeyChar()));
e.consume();
}
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
});
我想制作一个可编程计算器,我有基本的 GUI,现在我正在尝试设置按钮和显示器。我的显示文本基本上是“0”,如果用户输入一个数字,应该显示该数字。我试着用 KeyListener 来做,但如果我按下一个键,它会显示两次。为什么?
textField.addKeyListener(new KeyListener(){
boolean newNumber = true;
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode == e.VK_BACK_SPACE && textField.getText().length() == 1){
textField.setText("0");
newNumber = true;
}
if(textField.getText().equals("0") && newNumber){
textField.setText(KeyEvent.getKeyText(keyCode));
newNumber = false;
}
}
public void keyReleased(KeyEvent e) {
}
});
输入前:
输入“1”后:
为此,我像这样导出 PlainDocument:
import java.awt.EventQueue;
import java.util.regex.Pattern;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
public class DigitDocument extends PlainDocument {
private static final long serialVersionUID = 1L;
protected static final Pattern patternStartZero = Pattern.compile("^0.+");
protected final JTextField textField;
private final int limit;
private final Runnable runnableFormat;
public DigitDocument(JTextField textField, int limit) {
super();
this.textField = textField;
this.limit = limit;
runnableFormat = new Runnable() {
@Override
public void run() {
String text = textField.getText();
if (text.length() == 0) {
textField.setText("0");
}
else if (patternStartZero.matcher(text).matches()) {
textField.setText(text.replaceAll("^0+", ""));
}
}
};
}
@Override
public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
str = str.replaceAll("[^0-9]", "");
if (str.length() == 0)
return;
else if ((getLength() + str.length()) <= limit)
super.insertString(offset, str, attr);
EventQueue.invokeLater(runnableFormat);
}
@Override
public void remove(int offs, int len) throws BadLocationException {
if (!"0".equals(textField.getText()))
super.remove(offs, len);
EventQueue.invokeLater(runnableFormat);
}
}
用法是:
textField.setDocument(new DigitDocument(textField, 10));
textField.setText("0");
在数字文档中,
- 第一个参数是 JTextField 本身。
- 第二个arg(10)是最大输入长度, 您只能输入数字。
这里有一个简单的解决方案:
如果你使用 keyPressed
,你必须在 keyReleased
中做一些事情,这就变成了
复杂的。 keyTyped
是一种更简单的方法。
您可以使用 e.consume()
来防止插入两位数。
textField.addKeyListener(new KeyListener() {
int codeDelete = KeyEvent.getExtendedKeyCodeForChar(KeyEvent.VK_DELETE);
int codeBackSpace = KeyEvent.getExtendedKeyCodeForChar(KeyEvent.VK_BACK_SPACE);
@Override
public void keyTyped(KeyEvent e) {
char keyChar = e.getKeyChar();
if (textField.getText().length() == 0) {
textField.setText("0");
}
else if (textField.getText().equals("0") && keyChar != codeDelete && keyChar != codeBackSpace) {
textField.setText(String.valueOf(e.getKeyChar()));
e.consume();
}
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
});