Java: Roller program - debug - variables not updating from JTextField and NumberFormatException thrown regardless of valid information

StackOverflow https://stackoverflow.com/questions/1899648

Question

Problems: I am unable to get the values of the JTextFields or the rollResultTotal to update. Even if the data in the JTextFields are valid, a NumberFormatException is still thrown.

Questions: Why don't the variables stay? Is this due to declaration in the class itself? Is it possible to update a JLabel panel to show an updated result? (tried this, epic failure)

Thanks in advance for any input and examples.

/*
   ITP-120:     Final Project
   Programmer:  S. Schnoor
   Date:        November 7th, 2009
   Filename:    SchnoorProject.java
   Purpose:     To generate "dice rolls" - a tally of random values as defined by the user,
                including a final calculation modifier.
*/

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import java.lang.*;
import java.math.*;

public class SchnoorProject extends JFrame implements ActionListener, EventListener
{
    // Declare Class Variables
    int sidesToRoll, diceToRoll, diceLeft, modifier, rollResult, rollResultTotal;
    String getSides, getDice, getModifier;
    JTextField inputSides       = new JTextField();
    JTextField inputDice        = new JTextField();
    JTextField inputModifier    = new JTextField();
    Random roll;

    // Panels and Buttons
    JPanel rollPanel;
    JButton newRollButton, helpButton, exitButton;

    // Create Colors
    Color darkPurple        = new Color ( 80,   0,  80);
    Color darkGold          = new Color (255, 215,   0);
    Color darkCoal          = new Color ( 24,  24,  24);
    Color crimson           = new Color (127,  12,  12);
    Color ltSilver          = new Color (140, 140, 180);

    public static void main(String args[])
    {
        JFrame frame = new SchnoorProject();

        WindowListener l = new WindowAdapter()
            {
                public void windowClosing(WindowEvent e)
                {
                    System.exit(0);
                }
            };

    frame.addWindowListener(l);
    frame.pack();
    frame.setVisible(true);

    }

    public SchnoorProject()
    {
        // Construction of Components
        rollPanel                           = new JPanel();
        getContentPane().add(rollPanel);


        JLabel      sidesLabel              = new JLabel ("Enter the number of sides on each die below.  (1 to 99)");
                    sidesLabel.setForeground(darkGold);
                    sidesLabel.setHorizontalAlignment(sidesLabel.CENTER);

        JTextField  inputSides              = new JTextField("6");
                    inputSides.setBackground(darkCoal);
                    inputSides.setForeground(darkGold);
                    inputSides.setHorizontalAlignment(inputSides.CENTER);

        JLabel      diceLabel               = new JLabel ("Enter the number of dice to roll below.  (1 to 99)");
                    diceLabel.setForeground(darkGold);
                    diceLabel.setHorizontalAlignment(diceLabel.CENTER);

        JTextField  inputDice               = new JTextField("3");
                    inputDice.setBackground(darkCoal);
                    inputDice.setForeground(darkGold);
                    inputDice.setHorizontalAlignment(inputDice.CENTER);

        JLabel      modifierLabel           = new JLabel ("Enter the final modifier  below.  (-99 to 99)");
                    modifierLabel.setForeground(darkGold);
                    modifierLabel.setHorizontalAlignment(modifierLabel.CENTER);

        JTextField  inputModifier           = new JTextField("2");
                    inputModifier.setBackground(darkCoal);
                    inputModifier.setForeground(darkGold);
                    inputModifier.setHorizontalAlignment(inputModifier.CENTER);

        JButton     newRollButton           = new JButton("ROLL");
                    newRollButton.setBackground(darkCoal);
                    newRollButton.setForeground(darkGold);
                    newRollButton.addActionListener(this);

        JButton     helpButton              = new JButton("Help/About");
                    helpButton.setBackground(darkCoal);
                    helpButton.setForeground(ltSilver);
                    helpButton.addActionListener(this);

        JButton     exitButton              = new JButton("Exit");
                    exitButton.setBackground(darkCoal);
                    exitButton.setForeground(crimson);
                    exitButton.addActionListener(this);

        //Conversions
                    getSides                = inputSides.getText();
                    getDice                 = inputDice.getText();
                    getModifier             = inputModifier.getText();
                    sidesToRoll             = Integer.parseInt(getSides);
                    diceToRoll              = Integer.parseInt(getDice);
                    modifier                = Integer.parseInt(getModifier);
                    diceLeft                = diceToRoll;
                    //rollResultTotal       = rollResultTotal;

        // Paneling
        rollPanel.setLayout(new GridLayout (3,3));
        rollPanel.setBackground(darkPurple);
        rollPanel.setForeground(darkGold);
        rollPanel.add(sidesLabel);
        rollPanel.add(diceLabel);
        rollPanel.add(modifierLabel);
        rollPanel.add(inputSides);
        rollPanel.add(inputDice);
        rollPanel.add(inputModifier);
        rollPanel.add(newRollButton);
        rollPanel.add(helpButton);
        rollPanel.add(exitButton);
    }

    // Implement ActionListener for multiple JButtons
    public void actionPerformed(ActionEvent e)
    {
        String arg = e.getActionCommand();
        if ("Help/About".equals(arg))
            {
                JOptionPane.showMessageDialog(null,"This application generates random values, based on the parameters input by the user.\nPlease choose number of dice, sides on each die, and a +/- roll modifier.\nIf no roll modifier is needed, enter 0 (numeric zero) in the modifier field.\n(The starting numbers tell the program to roll 3 six-sided dice and add 2 or '3d6+2'.)","Help/About",JOptionPane.INFORMATION_MESSAGE);
            }

        if ("Exit".equals(arg))
            {
                System.exit(0);
            }

        if ("ROLL".equals(arg))

                {
                    try
                    {
                        while (diceLeft>0)
                        {
                            getSides                    = inputSides.getText();
                            sidesToRoll                 = Integer.parseInt(getSides);
                            if(sidesToRoll<1 || sidesToRoll>99)     throw new NumberFormatException();
                            else

                            getDice                     = inputDice.getText();
                            diceToRoll                  = Integer.parseInt(getDice);
                            if(diceToRoll<1 || diceToRoll>99)       throw new NumberFormatException();
                            else

                            getModifier                 = inputModifier.getText();
                            modifier                    = Integer.parseInt(getModifier);
                            if(modifier<-99 || modifier>99)         throw new NumberFormatException();
                            else

                        rollResult                  = roll.nextInt(sidesToRoll)+1;
                        rollResultTotal             = rollResultTotal + rollResult;
                        diceLeft--;
                        }

                    }


                    catch(NumberFormatException ex)
                    {
                        JOptionPane.showMessageDialog(null,"You must enter an integer within the given range of each field.","ROLL",JOptionPane.INFORMATION_MESSAGE);
                        diceLeft = 0;
                    }


                    {   //Display the Roll Formula and Result
                    JOptionPane.showMessageDialog(null,"You entered a roll of " + (diceToRoll) + "d" + (sidesToRoll) + "+(" + (modifier) + ").\nYou rolled " + (rollResultTotal) + "!");
                    }
        ;}
    ;}
}
Was it helpful?

Solution

You initialize this member variable, but you never add this field to the UI:

JTextField inputSides = new JTextField(" ");

Here you read from this text field that still contains the String " ", which is not an integer.

getSides = inputSides.getText();
sidesToRoll = Integer.parseInt(getSides);

When you build your UI in the constructor, you declare another, local variable with the same name, pointing to a new object:

JTextField inputSides = new JTextField("6");

This is the object that appears in the UI. The local variable inputSides hides the member variable of the same name.


As an aside, this is not the right way to compare strings:

arg == "ROLL"

This only works because arg is pointing to the same, interned object instance. The correct way to compare these values would be:

"ROLL".equals(arg)

EDIT:

The trick you are missing is in thinking about the objects you are creating and which ones your reference variables are pointing at.

Consider this simplified version of your code:

public class ObjectReferences {
  private final JLabel label = new JLabel("I am FOO"); // label 1

  public ObjectReferences() {
    JLabel label = new JLabel("I am BAR"); // label 2

    JButton button = new JButton("Click me");
    button.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        onclick();
      }
    });

    // will display "I am BAR"
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(600, 400);
    frame.setLayout(new FlowLayout());
    frame.add(label); // label 2
    frame.add(button);
    frame.setVisible(true);
  }

  public void onclick() {
    // will display "I am FOO"
    JOptionPane.showMessageDialog(null, label.getText()); // label 1
  }

  public static void main(String[] args) {
    new ObjectReferences();
  }
}

Two label objects are created, but only one is added to the frame. label 1 is referenced by the member variable and this is the one visible to the onclick() method. Within the constructor, label 2 is referenced by a local variable called label that hides the member variable called label.

Your intent is to write something like this instead:

public class ObjectReferences {
  private final JLabel label = new JLabel("I am FOO");

  public ObjectReferences() {
    JButton button = new JButton("Click me");
    button.addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        onclick();
      }
    });

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(600, 400);
    frame.setLayout(new FlowLayout());
    frame.add(label);
    frame.add(button);
    frame.setVisible(true);
  }

  public void onclick() {
    JOptionPane.showMessageDialog(null, label.getText());
  }

  public static void main(String[] args) {
    new ObjectReferences();
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top