DocumentListener Java, Wie verhindere ich leere Zeichenfolge in JTextBox?

Bildbeschreibung hier eingeben Ich habe an einem persönlichen Projekt gearbeitet, um mit der Programmierung besser zu werden. Mein Ziel ist es, es robuster zu machen, ich fange gerade an. Ich bin ein aktueller Informatikstudent. Jedenfalls arbeite ich daran, einen Teil des Programms wie gezeigt zu machen. Ich berechne den Stundenlohn und biete einige Ergebnisse an, die ich noch nicht implementiert habe. Ich verwende den DocumentListener, damit er automatisch berechnet wird. Ich bekomme einen Fehler, wenn der Text vollständig aus einer Box entfernt wird. Ich habe versucht, es mit der if-statement zu beheben:

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

Hier ist was ich bisher habe. Es ist noch nicht fertig und ich entschuldige mich für den Noob-Code. Ich habe vor 2 Monaten mit der eigentlichen Codierung begonnen.

  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)); } 

}

   

Ich mache das eine Antwort: Ich würde keinen DocumentListener für diesen Zweck verwenden, da es mir scheint, das falsche Werkzeug für den Job. Zum einen hört und aktualisiert es ständig die Ergebnisse, während der Benutzer immer noch Daten, die noch unvollständig sind, in das JTextField eingibt. Viel besser wäre es, einen ActionListener zu einem JButton oder zu JTextFields hinzuzufügen.

Ich nehme an, Sie könnten einen FocusListener verwenden, aber selbst das betrifft mich, da es ziemlich niedrig ist.

Außerdem sollten Sie einen InputVerifier verwenden, um Ihre Eingabe zu validieren.

Außerdem sollten Sie Ihre Tabellendaten in einer JTable anzeigen, in der die erste und die zweite Spalte bearbeitbar sind, die anderen jedoch nicht.

Bearbeiten
Ich bin mir nicht sicher, ob dies koscher ist, aber es könnte funktionieren, wenn Sie Ihre Berechnungen innerhalb des Verifizierers durchführen. Zum Beispiel, aktualisiert für die Allgemeinheit:

 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; } } } } 

Wie @HFOE vorschlägt, ist InputVerifier die richtige Wahl, aber verify() “sollte keine Nebenwirkungen haben.” calcProduct() stattdessen calcProduct() in 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; } } } 
  • Verwenden Sie JSpinner oder JFormattedTextField mit Number instance , dann sollte DocumentListener korrekt funktionieren, no needed to parse String to Number instance

  • Andernfalls müssen Sie DocumentFilter für JTextField um non numeric chars zu filtern. Ruhe (Zählen) bleibt unverändert, stil required robust parsing String to the Number instance