DocumentListener Java,如何防止JTextBox中出现空字符串?

时间:2012-08-05 16:27:56

标签: java swing jtextfield documentlistener inputverifier

enter image description here我一直致力于个人项目,以便在编程方面做得更好。我的目标是让它更加强大,我刚刚开始。我是现任计算机科学专业的学生。无论如何,我正在努力制作一部分程序,如图所示。我计算小时工资并提供一些我尚未实施的产出。我正在使用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));

}

}

3 个答案:

答案 0 :(得分:8)

正如@HFOE建议的那样,InputVerifier是正确的选择,但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;
        }
    }
}

答案 1 :(得分:7)

我会给出一个答案:我不会为此目的使用DocumentListener,因为在我看来这是一个错误的工具。首先,当用户仍在将数据(尚未完成的数据)输入JTextField时,它会不断地监听和更新结果。更好的方法是使用添加到JButton或JTextFields的ActionListener。

我想你可以使用一个FocusListener,但即使这样也会让我担心,因为它很低级。

另外:考虑使用InputVerifier来验证您的输入。

另外:考虑在JTable中显示表格数据,其中第1列和第2列是可编辑的,但其他列不可编辑。

修改
我不确定这是否是犹太洁食,但如果你在验证者中进行计算,它可能会起作用。例如,更新了一般性:

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

答案 2 :(得分:5)

  • JSpinnerJFormattedTextFieldNumber instance一起使用,然后DocumentListener应正常运行,no needed to parse String to Number instance

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