Home > Blockchain >  When using JOptionPane.showInputDialog the window disappears before I can input and it's breaki
When using JOptionPane.showInputDialog the window disappears before I can input and it's breaki

Time:02-25

Why do my JOptionPane.showInputDialog windows disappear before I can enter an input? I think it's what's causing my code to break. I've googled everything I can think of and nothing seems to apply to what I'm doing here. The error I get is:

Exception in thread "main" java.lang.NumberFormatException: For input string: ""
        at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
        at java.base/java.lang.Integer.parseInt(Integer.java:678)
        at java.base/java.lang.Integer.parseInt(Integer.java:786)
        at ChiliToGo.collectOrder(ChiliToGo.java:25)
        at ChiliToGo.main(ChiliToGo.java:13)

I'm just in a beginner java course so It's probably really dumb what I'm doing.

I've tried formatting the string and moving the main method into a separate class to access the methods in a non-static way because they are the best solutions I got from the posts I found. I'm just really confused because the parseint shouldn't get the string until I press ok right? It's only there for a moment and I don't have a chance to enter the input

Any help would be appreciated, code is below. Sorry if I made any mistakes this is my first post

import javax.swing.JOptionPane;

public class ChiliToGo {    
    static int adultMeal = 7;
    static int kidsMeal = 4;
    static String adultMealOrder;
    static String kidsMealOrder;
    static int adultMealOrdered;
    static int kidsMealOrdered;
    static int totalPrice;

    public static void main(String[] args) {
        collectOrder();
        finalizeOrder();
    }

    public static void collectOrder() {

        adultMealOrder = JOptionPane.showInputDialog("Please enter the number of adult meals:");
        kidsMealOrder = JOptionPane.showInputDialog("Please enter the number of kids meals:");
        
        adultMealOrdered = Integer.parseInt(adultMealOrder);
        kidsMealOrdered = Integer.parseInt(kidsMealOrder);
    }

    public static void finalizeOrder() {
        for(int i = 0; i < adultMealOrdered; i  ) {
            totalPrice = totalPrice   adultMeal;
        }
        for(int n = 0; n < kidsMealOrdered; n  ) {
            totalPrice = totalPrice   kidsMeal;
        }

        JOptionPane.showInternalMessageDialog( null, "Your order total is: "   totalPrice, null, JOptionPane.INFORMATION_MESSAGE);
    }
}

CodePudding user response:

So, the error is telling you that the input value of "" can't be converted to int. You're not doing any validation on the String returned from showInputDialog and are simply, blindly, trying to convert it to an int, which is failing, because no input has been made (and even worse, the return value could be null).

There are any number of ways you "might" consider fixing this, but the basic idea is to:

  1. Check that the return value is not null
  2. Validate the return value to ensure it's actually an int value.

To this end, I might encapsulate the logic into a self contained unit of work, for example...

    public static Integer getIntFromUser(String prompt) {
        Integer result = null;
        boolean done = false;
        do {
            String value = JOptionPane.showInputDialog(prompt);
            // User pressed cancel
            if (value == null) {
                done = true;
            } else {
                Scanner scanner = new Scanner(value);
                if (scanner.hasNextInt()) {
                    result = scanner.nextInt();
                    done = true;
                } else {
                    JOptionPane.showMessageDialog(null, "Please enter a numeric value");
                }
            }
        } while (!done);
        return result;
    }

This will loop until the user either inputs a valid int value or presses Cancel (hence the reason it returns Integer instead of int, this way you can inspect the return value for null)

The collectOrder method would also change to look something more like...

public static boolean collectOrder() {
    boolean validUserInput = false;
    Integer inputValue = getIntFromUser("Please enter the number of adult meals:");
    if (inputValue != null) {
        // Only prompt for the kids meal if the adult value is valid,
        // otherwise it's likely that they clicked cancel
        adultMealOrdered = inputValue;
        inputValue = getIntFromUser("Please enter the number of kids meals:");
        if (inputValue != null) {
            kidsMealOrdered = inputValue;
            validUserInput = true;
        }
    }
    
    return validUserInput;
}

The intention here is to check the return result from getIntFromUser, if it's null, the user pressed <kbd>Cancel</kbd> and we should stop any further processing, otherwise we go onto the next step.

collectOrder also returns boolean to indicate whether it has all the required data or not, so we don't try and finalise the order with invalid or partial data.

Runnable example...

public static class ChiliToGo {

    static int adultMeal = 7;
    static int kidsMeal = 4;
    static int adultMealOrdered;
    static int kidsMealOrdered;
    static int totalPrice;

    public static void main(String[] args) {
        if (collectOrder()) {
            finalizeOrder();
        }
    }

    public static boolean collectOrder() {
        boolean validUserInput = false;
        Integer inputValue = getIntFromUser("Please enter the number of adult meals:");
        if (inputValue != null) {
            // Only prompt for the kids meal if the adult value is valid,
            // otherwise it's likely that they clicked cancel
            adultMealOrdered = inputValue;
            inputValue = getIntFromUser("Please enter the number of kids meals:");
            if (inputValue != null) {
                kidsMealOrdered = inputValue;
                validUserInput = true;
            }
        }
        
        return validUserInput;
    }

    public static Integer getIntFromUser(String prompt) {
        Integer result = null;
        boolean done = false;
        do {
            String value = JOptionPane.showInputDialog(prompt);
            // User pressed cancel
            if (value == null) {
                done = true;
            } else {
                Scanner scanner = new Scanner(value);
                if (scanner.hasNextInt()) {
                    result = scanner.nextInt();
                    done = true;
                } else {
                    JOptionPane.showMessageDialog(null, "Please enter a numeric value");
                }
            }
        } while (!done);
        return result;
    }

    public static void finalizeOrder() {
        for (int i = 0; i < adultMealOrdered; i  ) {
            totalPrice = totalPrice   adultMeal;
        }
        for (int n = 0; n < kidsMealOrdered; n  ) {
            totalPrice = totalPrice   kidsMeal;
        }

        JOptionPane.showInternalMessageDialog(null, "Your order total is: "   totalPrice, null, JOptionPane.INFORMATION_MESSAGE);
    }
}

But why not use a try-catch block?

Well, this might be a little old school, and you don't always have the choice, but try-catch blocks, generally, shouldn't be used as control flow mechanisms (every rule has an exception

  • Related