Jak zmusić użytkownika do podania tylko liczb dodatnich w kalkulatorze BMI

0

Hej.,

Dopiero uczę się Javy, więc z góy przepraszam za błedy.

Na zaliczenie w szkole mam do zrobienia kalkulator BMI. Zbudowałem program z użyciem jFrame w Net Beans. Mam problem jak przymusić użytkownika do użycia liczb dodatnich. Próbowałem użyć try/catch, ale udało mi się to tylko w przypadku użycia liter (pojawia się ramka "Użyj cyfr").

Tak wygląda główna część kodu:

private void calculateActionPerformed(java.awt.event.ActionEvent evt) {
    try {
      weight = Double.parseDouble(weightValue.getText());
      height = Double.parseDouble(heightValue.getText());

      if(lbs.isSelected()){
          weight = weight / 2.205;
      }
      
      if(inch.isSelected()){
          height = height / 39.37;
      }
      else if(cm.isSelected()){
          height = height / 100;
      }
      
      bmi = weight /(height*height);
      
    } //end try
    catch(NumberFormatException nfe)
    {
        String message = String.format("%s\n%s", nfe.getMessage(), "Use Numbers only");
        JOptionPane.showMessageDialog(Main.this, message, "Input Error", JOptionPane.ERROR_MESSAGE);
    }
0

Zrób if na wartości ujemne

5

Zależy co oznacza przymusic. Bo dosłownie to wtedy musisz uzyc np maski na inputy i to będzie najładniejsze rozwiązanie. http://www.java2s.com/Code/Java/Swing-JFC/JFormattedTextFieldaninputmaskforatelephonenumber.htm

Co do twojego kodu to jak musi to byc na errorach to bym zmienił na coś takiego:

// najpierw zdefiniował dwie funkcje isNumeric i isPositive
boolean isNumeric(String strNum) {
    if (strNum == null) {
        return false;
    }
    try {
        double d = Double.parseDouble(strNum);
    } catch (NumberFormatException nfe) {
        return false;
    }
    return true;
}

boolean isPositive(Double value){
    return value >= 0.0 
}

i potem

if(isNumeric(weightValue.getText()) && isNumeric(heightValue.getText())){

    weight = Double.parseDouble(weightValue.getText());
    height = Double.parseDouble(heightValue.getText());

    if(isPositive(weight) && isPositive(height)){
      // uruchom logike
    } else {
      //wywal bład
    }    
} else {
 // logika od błedu dla wartości które nie są liczbą
}
0

Wolę nieco inne podejście:

public class BmiForm extends javax.swing.JFrame
{
    private boolean goodInput;
    private double weight;
    private double height;
    private static interface SetValue{ void set(double value); }
    
    public BmiForm()
    {
        initComponents();
        DocumentListener changeListener=new DocumentListener()
        {
            @Override public void insertUpdate(DocumentEvent e) { onChange(); }
            @Override public void removeUpdate(DocumentEvent e) { onChange(); }
            @Override public void changedUpdate(DocumentEvent e) { onChange(); }
        };
        tfWeight.getDocument().addDocumentListener(changeListener);
        tfHeight.getDocument().addDocumentListener(changeListener);
        onChange();
    }
    
    private double parseValue(JTextField field)
    {
        double value=Double.parseDouble(field.getText());
        if(value<=0) throw new InvalidParameterException("Incorrect value");
        return value;
    }
    
    private void checkField(JTextField field,SetValue setValue)
    {
        try
        {
            setValue.set(parseValue(field));
            field.setToolTipText("");
            field.setBackground(Color.white);
            //btnCalc.setEnabled(true);
        }
        catch(Exception e)
        {
            goodInput=false;
            //btnCalc.setEnabled(false); // alternatywa goodInput
            field.setToolTipText(e.getMessage());
            field.setBackground(Color.yellow);
        }
    }
    
    private final void onChange()
    {
        goodInput=true;
        checkField(tfWeight,(v) -> weight=v);
        checkField(tfHeight,(v) -> height=v);
        if(goodInput)
        {
            double bmi=weight/(height*height);
            tfResult.setText(String.format("%.2f",bmi));
        }
        else tfResult.setText("Wrong data");
    }

    @SuppressWarnings("unchecked")

    public static void main(String args[])
    {
        java.awt.EventQueue.invokeLater(() -> new BmiForm().setVisible(true));
    }

    private javax.swing.JTextField tfHeight;
    private javax.swing.JTextField tfResult;
    private javax.swing.JTextField tfWeight;
}

Użyszkodnik zmienia dane, zaś wynik wylicza się w locie, bez przycisku <Licz>.
Zalety:

  • Użyszkodnik widzi w którym miejscu nabroił
  • Użyszkodnik najeżdża myszą na "nabrojone" miejsce i czyta czemu.

Wada:

  • Nie zbyt łatwo oddzielić logikę od reszty

Rozwiązania dla wady:
Zawsze do checkField() można przekazać mapę klasa wyjątku => tekst błędu
Zawsze do checkField() można przekazać dodatkowy interfejs sprawdzający konkretne pole np:
Waga: 15..500
Wzrost: 70..260

0

Dziękuję za podpowiedzi. wyprobuję obie wersje :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1