DocumentListener Java, Come si impedisce la stringa vuota in JTextBox?

inserisci la descrizione dell'immagine qui Ho lavorato a un progetto personale per migliorare con la programmazione. Il mio objective è renderlo molto più robusto, sto solo iniziando. Sono uno studente di informatica corrente. Ad ogni modo, sto lavorando per creare una parte del programma come mostrato. Calcolo il salario orario e fornisce alcune uscite che non ho ancora implementato. Sto usando DocumentListener in modo che calcoli automaticamente. Ricevo un errore quando il testo viene rimosso completamente da una finestra. Ho provato a correggerlo con l’istruzione if:

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

Ecco cosa ho finora. Non è ancora finito e mi scuso per il codice noob. Ho iniziato 2 mesi fa con una vera codifica.

  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 actionPerformsd(ActionEvent arg0) { monWage.setText(Double.toString(5)); } 

}

Farò una risposta: non userei un DocumentListener per questo scopo, poiché mi sembra lo strumento sbagliato per il lavoro. Per uno, è continuamente in ascolto e aggiornamento dei risultati mentre l’utente sta ancora immettendo dati, dati che sono ancora incompleti, nel JTextField. Molto meglio sarebbe usare un ActionListener aggiunto a un JButton o ai tuoi JTextFields.

Suppongo che potresti usare un FocusListener, ma anche questo mi riguarda dal momento che è piuttosto di basso livello.

Inoltre: considerare l’utilizzo di un InputVerifier per convalidare l’input.

Inoltre: considera la possibilità di visualizzare i tuoi dati tabulari in una tabella J, in cui la prima e la seconda colonna sono modificabili, mentre le altre non lo sono.

modificare
Non sono sicuro che sia kosher, ma potrebbe funzionare se fai i tuoi calcoli all’interno del verificatore. Ad esempio, aggiornato per generalità:

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

Come suggerisce @HFOE, InputVerifier è la scelta giusta, ma verify() “non dovrebbe avere effetti collaterali”. Invece, invocare 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; } } } 
  • utilizzare JSpinner o JFormattedTextField con l’ Number instance , quindi DocumentListener dovrebbe funzionare correttamente, no needed to parse String to Number instance

  • altrimenti devi usare DocumentFilter per JTextField per filtrare non numeric chars , resto (conteggio) rimane invariato, stil required robust parsing String to the Number instance