提问人:AndroidDev 提问时间:6/19/2012 最后编辑:JimmyPenaAndroidDev 更新时间:6/9/2016 访问量:282049
将 JTextField 输入限制为整数 [duplicate]
Restricting JTextField input to Integers [duplicate]
问:
我知道这个问题一定被问过和回答过一百万次,但我就是找不到一个简单的解决方案。我有一个 JTextField,它只接受正整数作为输入。我需要一种方法来确保这里没有其他输入。
我已经将一个 keyListener 附加到此控件。删除此侦听器要处理的其他代码,我有这个:
txtAnswer.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
/* Restrict input to only integers */
if (key < 96 && key > 105) e.setKeyChar('');
};
});
如您所见,我正在尝试使用 KeyCode 来检查刚刚按下的键是否落在整数范围内。这似乎有效。但我想做的是,如果条目超出此范围,请简单地忽略它。该代码旨在处理此问题,但它不起作用。代码将编译,但没有可见的效果。e.setKeyChar('')
谁能告诉我我是否走在正确的轨道上?我可以用什么来代替它?还是我完全走错了方向?e.setKeyChar('')
谢谢。
答:
不要为此使用 KeyListener,因为您会错过很多东西,包括粘贴文本。此外,KeyListener 是一个非常低级的构造,因此在 Swing 应用程序中应避免使用。
该解决方案已在 SO 上多次描述:使用 DocumentFilter。这个网站上有几个这样的例子,有些是我写的。
例如:using-documentfilter-filterbypass
另有关教程帮助,请查看:实现 DocumentFilter。
编辑
例如:
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
import javax.swing.text.PlainDocument;
public class DocFilter {
public static void main(String[] args) {
JTextField textField = new JTextField(10);
JPanel panel = new JPanel();
panel.add(textField);
PlainDocument doc = (PlainDocument) textField.getDocument();
doc.setDocumentFilter(new MyIntFilter());
JOptionPane.showMessageDialog(null, panel);
}
}
class MyIntFilter extends DocumentFilter {
@Override
public void insertString(FilterBypass fb, int offset, String string,
AttributeSet attr) throws BadLocationException {
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder();
sb.append(doc.getText(0, doc.getLength()));
sb.insert(offset, string);
if (test(sb.toString())) {
super.insertString(fb, offset, string, attr);
} else {
// warn the user and don't allow the insert
}
}
private boolean test(String text) {
try {
Integer.parseInt(text);
return true;
} catch (NumberFormatException e) {
return false;
}
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text,
AttributeSet attrs) throws BadLocationException {
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder();
sb.append(doc.getText(0, doc.getLength()));
sb.replace(offset, offset + length, text);
if (test(sb.toString())) {
super.replace(fb, offset, length, text, attrs);
} else {
// warn the user and don't allow the insert
}
}
@Override
public void remove(FilterBypass fb, int offset, int length)
throws BadLocationException {
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder();
sb.append(doc.getText(0, doc.getLength()));
sb.delete(offset, offset + length);
if (test(sb.toString())) {
super.remove(fb, offset, length);
} else {
// warn the user and don't allow the insert
}
}
}
为什么这很重要?
- 如果用户使用复制和粘贴将数据插入到文本组件中,该怎么办?KeyListener 会错过这个吗?
- 您似乎希望检查数据是否可以表示 int。如果他们输入的数值数据不合适怎么办?
- 如果要允许用户稍后输入双重数据,该怎么办?在科学记数法中?
评论
InputVerifier
。
text.trim().isEmpty()
if(sb.toString().length() == 0) { super.replace(fb, offset, length, "0", null); } else { if (test(sb.toString())) { super.remove(fb, offset, length); } else { // warn the user and don't allow the insert } }
"0"
""
下面是一种使用 keylistener 但使用 keyChar(而不是 keyCode)的方法:
http://edenti.deis.unibo.it/utils/Java-tips/Validating%20numerical%20input%20in%20a%20JTextField.txt
keyText.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
if (!((c >= '0') && (c <= '9') ||
(c == KeyEvent.VK_BACK_SPACE) ||
(c == KeyEvent.VK_DELETE))) {
getToolkit().beep();
e.consume();
}
}
});
另一种方法(我个人认为它几乎和 Swing 的 JTree 模型一样过于复杂)是使用格式化文本字段:
http://docs.oracle.com/javase/tutorial/uiswing/components/formattedtextfield.html
评论
我曾经使用过 Key Listener,但这种方法失败了很长时间。如前所述,最佳方法是使用 DocumentFilter。下面是我创建的一个实用方法,用于仅使用数字输入构建文本字段。请注意,它也将采用单个“.”字符,因为它可用于十进制输入。
public static void installNumberCharacters(AbstractDocument document) {
document.setDocumentFilter(new DocumentFilter() {
@Override
public void insertString(FilterBypass fb, int offset,
String string, AttributeSet attr)
throws BadLocationException {
try {
if (string.equals(".")
&& !fb.getDocument()
.getText(0, fb.getDocument().getLength())
.contains(".")) {
super.insertString(fb, offset, string, attr);
return;
}
Double.parseDouble(string);
super.insertString(fb, offset, string, attr);
} catch (Exception e) {
Toolkit.getDefaultToolkit().beep();
}
}
@Override
public void replace(FilterBypass fb, int offset, int length,
String text, AttributeSet attrs)
throws BadLocationException {
try {
if (text.equals(".")
&& !fb.getDocument()
.getText(0, fb.getDocument().getLength())
.contains(".")) {
super.insertString(fb, offset, text, attrs);
return;
}
Double.parseDouble(text);
super.replace(fb, offset, length, text, attrs);
} catch (Exception e) {
Toolkit.getDefaultToolkit().beep();
}
}
});
}
您也可以使用 ,使用起来要简单得多。例:JFormattedTextField
public static void main(String[] args) {
NumberFormat format = NumberFormat.getInstance();
NumberFormatter formatter = new NumberFormatter(format);
formatter.setValueClass(Integer.class);
formatter.setMinimum(0);
formatter.setMaximum(Integer.MAX_VALUE);
formatter.setAllowsInvalid(false);
// If you want the value to be committed on each keystroke instead of focus lost
formatter.setCommitsOnValidEdit(true);
JFormattedTextField field = new JFormattedTextField(formatter);
JOptionPane.showMessageDialog(null, field);
// getValue() always returns something valid
System.out.println(field.getValue());
}
评论
""
我简直不敢相信我还没有在堆栈溢出的任何地方找到这个简单的解决方案,它是迄今为止最有用的。更改 Document 或 DocumentFilter 不适用于 JFormattedTextField。Peter Tseng的回答非常接近。
NumberFormat longFormat = NumberFormat.getIntegerInstance();
NumberFormatter numberFormatter = new NumberFormatter(longFormat);
numberFormatter.setValueClass(Long.class); //optional, ensures you will always get a long value
numberFormatter.setAllowsInvalid(false); //this is the key!!
numberFormatter.setMinimum(0l); //Optional
JFormattedTextField field = new JFormattedTextField(numberFormatter);
评论
NumberFormatter
stringToValue(String text)
null
当您在密钥释放后向 JtextField1 键入整数时,它将转到 inside try ,对于任何其他字符,它将抛出 NumberFormatException。如果在捕获中将空字符串设置为 jTextField1,则用户无法键入除正数之外的任何其他键,因为每次错误尝试都会清除 JTextField1。
//Fields
int x;
JTextField jTextField1;
//Gui Code Here
private void jTextField1KeyReleased(java.awt.event.KeyEvent evt) {
try {
x = Integer.parseInt(jTextField1.getText());
} catch (NumberFormatException nfe) {
jTextField1.setText("");
}
}
上一个:FUSE 错误:传输终结点未连接
下一个:无法将字节转换为 str
评论