DocumentListener Java,如何防止JTextBox中的空string?

在这里输入图像描述 我一直在做一个个人项目,以更好地编程。 我的目标是让它更健壮,我刚刚开始。 我是目前的计算机科学专业的学生。 无论如何,我正在制作如图所示的程序的一部分。 我计算小时工资,并提供了一些我还没有实施的产出。 我正在使用DocumentListener,所以它会自动计算。 我得到一个错误,当文本从盒子里完全删除。我试图解决它与if语句:

if (tipMon.equals("") || tipMon == null) { tipMon.setText("0"); } 

这是我迄今为止。 这还没有完成,我为noob代码道歉。 我在2个月前开始实际编码。

  import java.awt.GridLayout; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.KeyListener; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.JOptionPane; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.Document; import javax.swing.text.FieldView; public class deliveryDocListener extends JFrame implements ActionListener, DocumentListener{ private JLabel mon, tues, wed, thurs, fri, sat, sun, hourlyWage, blank, row2, monWage, tuesWage,wedWage,thursWage, friWage, satWage, sunWage, total, totalTips, totalHours, totalHourlyEarnings, totalPay, weekPay; private JTextField hourlyWageInput, tipMon, tipTues, tipWed, tipThurs, tipFri, tipSat, tipSun, hourMon, hourTues, hourWed, hourThurs, hourFri, hourSat, hourSun; public deliveryDocListener(){ super("Delivery Helper v0.1 Alpha"); setLayout(new GridLayout(0,4)); hourlyWage = new JLabel("Hourly Wage: "); add(hourlyWage); hourlyWageInput = new JTextField("7.25", 5); add(hourlyWageInput); blank = new JLabel(); add(blank); blank = new JLabel(); add(blank); row2 = new JLabel("Day of the Week"); add(row2); row2 = new JLabel("Tips"); add(row2); row2 = new JLabel("Hours Worked"); add(row2); row2 = new JLabel("Hourly Earnings"); add(row2); mon = new JLabel("Monday"); add(mon); tipMon = new JTextField("0"); Document tipMonListener = tipMon.getDocument(); //Document class doc variable stores what happens in the getDocument() //method, getDocument() i think is what checked it real time we shall see tipMonListener.addDocumentListener(this); //add listener to he text field, this refers to most recent object (tipMon = new JTextField("0");" //notice how its purple is the same as new where the object got made? add(tipMon); hourMon = new JTextField("0"); Document hourMonListener = hourMon.getDocument(); hourMonListener.addDocumentListener(this); add(hourMon); monWage = new JLabel("0"); add(monWage); tues = new JLabel("Tuesday"); add(tues); tipTues = new JTextField("0"); add(tipTues); hourTues = new JTextField("0"); add(hourTues); tuesWage = new JLabel("0"); add(tuesWage); wed = new JLabel("Wednesday"); add(wed); tipWed = new JTextField("0"); add(tipWed); hourWed = new JTextField("0"); add(hourWed); wedWage = new JLabel("0"); add(wedWage); thurs = new JLabel("Thursday"); add(thurs); tipThurs = new JTextField("0"); add(tipThurs); hourThurs = new JTextField("0"); add(hourThurs); thursWage = new JLabel("0"); add(thursWage); fri = new JLabel("Friday"); add(fri); tipFri = new JTextField("0"); add(tipFri); hourFri = new JTextField("0"); add(hourFri); friWage = new JLabel("0"); add(friWage); sat = new JLabel("Saturday"); add(sat); tipSat = new JTextField("0"); add(tipSat); hourSat = new JTextField("0"); add(hourSat); satWage = new JLabel("0"); add(satWage); sun = new JLabel("Sunday"); add(sun); tipSun = new JTextField("0"); add(tipSun); hourSun = new JTextField("0"); add(hourSun); sunWage = new JLabel("0"); add(sunWage); blank = new JLabel(); add(blank); blank = new JLabel(); add(blank); blank = new JLabel(); add(blank); blank = new JLabel(); add(blank); total = new JLabel("Total: "); add(total); totalTips = new JLabel("totalTipsOutput"); add(totalTips); totalHours = new JLabel("totalHoursOutput"); add(totalHours); totalHourlyEarnings = new JLabel("totalHourlyEarningsOutput"); add(totalHourlyEarnings); blank = new JLabel(); add(blank); blank = new JLabel(); add(blank); blank = new JLabel(); add(blank); blank = new JLabel(); add(blank); blank = new JLabel(); add(blank); blank = new JLabel(); add(blank); totalPay = new JLabel("Gross Income: "); add(totalPay); weekPay = new JLabel("totalPayOutput"); add(weekPay); } @Override public void changedUpdate(DocumentEvent e) { // TODO Auto-generated method stub } @Override public void insertUpdate(DocumentEvent e) { //executes when someone enters text into input String tipMonStr = tipMon.getText(); //monWage.setText(tipMonStr); String hourMonStr = hourMon.getText(); double x = Double.parseDouble(tipMonStr); double y = Double.parseDouble(hourMonStr); double z = Double.parseDouble(hourlyWageInput.getText()); if (tipMonStr.length() == 0) { tipMon.setText("0"); } if (hourMonStr.length() == 0) { y = 0; hourMonStr = "0"; } if (hourlyWageInput.getText().length() == 0) { z = 0; //String z = "0"; } monWage.setText(Double.toString((z*y+x)/y)); //bug when nothing in cell because no number (0) to use in math } @Override public void removeUpdate(DocumentEvent e) { //executes when someone enters text into input String tipMonStr = tipMon.getText(); //monWage.setText(tipMonStr); String hourMonStr = hourMon.getText(); double x = Double.parseDouble(tipMonStr); double y = Double.parseDouble(hourMonStr); double z = Double.parseDouble(hourlyWageInput.getText()); monWage.setText(Double.toString((z*y+x)/y)); if (tipMon.equals("") || tipMon == null) { tipMon.setText("0"); } } public void updateLog(DocumentEvent e, String action) { monWage.setText(Double.toString(5)); } @Override public void actionPerformed(ActionEvent arg0) { monWage.setText(Double.toString(5)); } 

}

我会做出这个答案:我不会使用DocumentListener来达到这个目的,因为在我看来这是一个错误的工具。 首先,当用户仍在input数据,但尚未完成的数据时,它会不断地收听和更新结果到JTextField中。 使用添加到JButton或JTextField的ActionListener会更好。

我想你可以使用一个FocusListener,但即使这也是关注我,因为它是相当低级的。

另外:考虑使用InputVerifier来validation你的input。

另外:考虑在第一列和第二列可编辑但其他列不可用的JTable中显示表格数据。

编辑
我不确定这是不是犹太教,但如果你从validation者内部进行计算,它可以工作。 例如,更新为普遍性:

 import javax.swing.*; /** * @see http://stackoverflow.com/a/11818183/522444 */ public class VerifierEg { private static final String ZERO = "0.0"; private JTextField field1 = new JTextField(ZERO, 5); private JTextField field2 = new JTextField(ZERO, 5); private JTextField resultField = new JTextField(ZERO, 10); private void createAndShowGui() { resultField.setEditable(false); resultField.setFocusable(false); JPanel mainPanel = new JPanel(); final JTextField[] fields = {field1, field2}; mainPanel.add(field1); mainPanel.add(new JLabel(" x ")); mainPanel.add(field2); mainPanel.add(new JLabel(" = ")); mainPanel.add(resultField); for (JTextField field : fields) { field.setInputVerifier(new MyInputVerifier(field)); } JFrame frame = new JFrame("VerifierEg"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(mainPanel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } private void calcProduct() { double d1 = Double.parseDouble(field1.getText()); double d2 = Double.parseDouble(field2.getText()); double prod = d1 * d2; resultField.setText(String.valueOf(prod)); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { VerifierEg eg = new VerifierEg(); eg.createAndShowGui(); } }); } /** * @see http://stackoverflow.com/a/11818946/230513 */ private class MyInputVerifier extends InputVerifier { private JTextField field; private double value; public MyInputVerifier(JTextField field) { this.field = field; } @Override public boolean shouldYieldFocus(JComponent input) { if (verify(input)) { field.setText(String.valueOf(value)); calcProduct(); return true; } else { field.setText(ZERO); field.selectAll(); return false; } } @Override public boolean verify(JComponent input) { try { value = Double.parseDouble(field.getText()); return true; } catch (NumberFormatException e) { return false; } } } } 

正如@HFOE所说, InputVerifier是正确的select,但是verify() “应该没有副作用”。 相反,调用calcProduct()中的shouldYieldFocus()

  /** * @see http://stackoverflow.com/a/11818946/230513 */ private class MyInputVerifier extends InputVerifier { private JTextField field; private double value; public MyInputVerifier(JTextField field) { this.field = field; } @Override public boolean shouldYieldFocus(JComponent input) { if (verify(input)) { field.setText(String.valueOf(value)); calcProduct(); return true; } else { field.setText(ZERO); field.selectAll(); return false; } } @Override public boolean verify(JComponent input) { try { value = Double.parseDouble(field.getText()); return true; } catch (NumberFormatException e) { return false; } } } 
  • 使用JSpinner或带有Number instance JFormattedTextField ,那么DocumentListener应该工作正常, no needed to parse String to Number instance

  • 否则,您必须使用DocumentFilter for JTextField来过滤non numeric chars ,其余(计数)保持不变,stil required robust parsing String to the Number instance