问题
So I have this to convert String
from JTextField
to int
. It says Exception in thread "main" java.lang.NumberFormatException: For input string: ""
. Please help.
JTextField amountfld = new JTextField(15);
gbc.gridx = 1; // Probably not affecting anything
gbc.gridy = 3; //
add(amountfld, gbc);
String amountString = amountfld.getText();
int amount = Integer.parseInt(amountString);
回答1:
From docs:
Throws: NumberFormatException - if the string does not contain a parsable integer.
The empty String ""
is not a parsable integer, so your code will always produce a NumberFormatException
if no value is entered.
There are many ways in which you can avoid this. You can simply check if the String
value you got from amountField.getText()
is actually populated. You can create a custom IntegerField
, which only allows integers as input, but adding Document to a JTextField
. Create a Document to only allow integers an input:
public static class IntegerDocument extends PlainDocument {
@Override
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
StringBuilder sb = new StringBuilder(str.length());
for (char c:str.toCharArray()) {
if (!Character.isDigit(c)) {
sb.append(c);
}
}
super.insertString(offs, sb.toString(), a);
}
}
Now create a IntergerField
with a convenient getInt
method, which returns zero if nothing is entered:
public static class IntegerField extends JTextField {
public IntegerField(String txt) {
super(txt);
setDocument(new IntegerDocument());
}
public int getInt() {
return this.getText().equals("") ? 0 : Integer.parseInt(this.getText());
}
}
Now you can retrieve the integer value from amountField
without doing any checks:
JTextField amountField = new IntegerField("15");
...
//amount will be zero if nothing is entered
int amount = amountField.getInt();
回答2:
Your biggest problem is that you're parsing the text field contents immediately after creating the field, and this makes no sense. Wouldn't it make much more sense to parse the data after allowing the user the opportunity to enter data, preferably within a listener of some sort, often an ActionListener?
And so my recommendations are two-fold
- Don't try to extract data immediately on JTextField creation, but instead do so within an appropriate listener. The type can only be known to you, but often we use ActionListeners for this sort of thing so that we can parse when the user presses a JButton.
- Do your parsing within a try / catch block where you catch for
NumberFormatException
. If an exception occurs, you then clear the JTextField by callingsetText()
, and then warn the user that they're entering invalid data, often done with a JOptionPane. - OK a 3rd recommendation: if possible, try to make your GUI totally idiot-proof by 1) giving the user a default value, and 2) not even allowing the user to enter invalid data. A JSlicer or JSpinner or JComobBox could work nicely for this as they would limit allowed input.
For example:
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class GetNumericData extends JPanel {
private JTextField amountfld = new JTextField(15);
private JSpinner amountSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 40, 1));
private JButton submitButton = new JButton(new SubmitAction("Submit"));
private JButton exitButton = new JButton(new ExitAction("Exit", KeyEvent.VK_X));
public GetNumericData() {
add(new JLabel("Amount 1:"));
add(amountfld);
add(new JLabel("Amount 2: $"));
add(amountSpinner);
add(submitButton);
add(exitButton);
}
// do all your parsing within a listener such as this ActionListener
private class SubmitAction extends AbstractAction {
public SubmitAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
String amountTxt = amountfld.getText().trim();
try {
int amount1 = Integer.parseInt(amountTxt);
// if this parse fails we go immediately to the catch block
int amount2 = (Integer) amountSpinner.getValue();
String message = String.format("Your two amounts are %d and %d", amount1, amount2);
String title = "Amounts";
int messageType = JOptionPane.INFORMATION_MESSAGE;
JOptionPane.showMessageDialog(GetNumericData.this, message, title, messageType);
} catch (NumberFormatException e1) {
String message = "You can only enter numeric data within the amount field";
String title = "Invalid Data Entered";
int messageType = JOptionPane.ERROR_MESSAGE;
JOptionPane.showMessageDialog(GetNumericData.this, message, title, messageType);
amountfld.setText("");
}
}
}
private class ExitAction extends AbstractAction {
public ExitAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Get Data");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new GetNumericData());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
来源:https://stackoverflow.com/questions/37459857/parsing-jtextfield-string-into-integer