views:

286

answers:

1

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) + "!");
        }
     ;}
    ;}
}
+1  A: 

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();
  }
}
McDowell
I appreciate the swift response. I was able to switch the arg == "ROLL" with "ROLL".equals(arg), as well as the Exit and Help/About buttons. I've also cleaned up the code above to reflect that change, along with removing unnecessary code. Still haven't figured it out, though.
Sean Schnoor
I edited my answer, so hopefully the problem is clearer. _Also, note that you haven't initialized your `roll` member, so you'll get a NullPointerException when you try to use it._
McDowell
This is starting to make sense. I'll keep at it. :)
Sean Schnoor
Thank you! Sorry for closing this so late... I was unable to log in O_o
Sean Schnoor