DocumentListener Java, ¿Cómo evito cadenas vacías en JTextBox?

enter image description here He estado trabajando en un proyecto personal para mejorar con la progtwigción. Mi objective es hacerlo mucho más robusto, recién estoy comenzando. Soy un estudiante de informática actual. De todos modos, estoy trabajando en hacer una porción del progtwig como se muestra. Calculo el salario por hora y proporciono algunos productos que todavía no he implementado. Estoy usando DocumentListener para que se calcule automáticamente. Me aparece un error cuando el texto se elimina por completo de un cuadro. Intenté solucionarlo con la statement if:

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

Esto es lo que tengo hasta ahora. Todavía no está hecho y me disculpo por el código novato. Empecé hace 2 meses con encoding real.

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

}

Haré de esto una respuesta: no utilizaría un DocumentListener para este fin, ya que me parece la herramienta incorrecta para el trabajo. Por un lado, escucha y actualiza continuamente los resultados mientras el usuario todavía está ingresando datos, datos que aún no están completos, en JTextField. Mucho mejor sería usar un ActionListener agregado a un JButton oa tus JTextFields.

Supongo que podrías utilizar un FocusListener, pero incluso eso me preocupa ya que es bastante bajo nivel.

Además: considere usar un InputVerifier para validar su entrada.

Además, considere mostrar sus datos tabulares en una JTable donde las columnas 1ª y 2ª son editables pero las otras no.

Editar
No estoy seguro de si esto es kosher, pero podría funcionar si haces tu cálculo desde dentro del verificador. Por ejemplo, actualizado para generalidad:

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

Como @HFOE sugiere, InputVerifier es la elección correcta, pero InputVerifier verify() “no debería tener efectos secundarios”. En su lugar, invoque calcProduct() en 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; } } } 
  • utilice JSpinner o JFormattedTextField con la Number instance , entonces DocumentListener debería funcionar correctamente, no needed to parse String to Number instance

  • de lo contrario, debe usar DocumentFilter para JTextField para filtrar non numeric chars , el rest (conteo) permanece inalterado, aún así se required robust parsing String to the Number instance

    Intereting Posts