Problem with inner class


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 13 of 13

Thread: Problem with inner class

Hybrid View

  1. #1
    Join Date
    Aug 2006
    Posts
    10

    Problem with inner class

    I'm a first-year Java student, so please go easy on me.

    I'm trying to create a GUI that allows generates a bill for mechanic services. I've defined the Swing components in an outer class, then define an inner class to do the event handling and logic. Problem is, the inner class doesn't recognize any of the components from the outer class, so I can't even get a clean compile.

    Here's the code for the GUI/processor. (I actually execute another class containing only a "main" method that instantiates the JoesAuto class.)

    ----
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;

    public class JoesAuto extends JFrame

    {
    final private double OIL_CHANGE_CHARGE = 26.00;
    final private double LUBE_JOB_CHARGE = 18.00;
    final private double RAD_FLUSH_CHARGE = 30.00;
    final private double TRAN_FLUSH_CHARGE = 80.00;
    final private double INSPECTION_CHARGE = 15.00;
    final private double MUFFLER_REPL_CHARGE = 100.00;
    final private double TIRE_ROTATE_CHARGE = 20.00;

    // constructor
    public JoesAuto()
    {
    // superclass constructor
    super("Service invoice");
    // instantiate a frame
    JFrame invoice = new JFrame();

    // build a panel for the routine services checkboxes
    JPanel routineServicesPanel = new JPanel();
    routineServicesPanel.setLayout(new GridLayout(7, 1));
    routineServicesPanel.setBorder(BorderFactory.createTitledBorder("Standard Services"));

    // build the routine services checkboxes
    final JCheckBox oilChange = new JCheckBox("Oil change -- $" + OIL_CHANGE_CHARGE);
    final JCheckBox lubeJob = new JCheckBox("Lube job -- $" + LUBE_JOB_CHARGE);
    final JCheckBox radFlush = new JCheckBox("Radiator flush -- $" + RAD_FLUSH_CHARGE);
    final JCheckBox tranFlush = new JCheckBox("Transmission flush -- $" + TRAN_FLUSH_CHARGE);
    final JCheckBox inspection = new JCheckBox("Inspection -- $" + INSPECTION_CHARGE);
    final JCheckBox mufflerRepl = new JCheckBox("Muffler replacement -- $" + MUFFLER_REPL_CHARGE);
    final JCheckBox tireRotate = new JCheckBox("Tire rotation -- $" + TIRE_ROTATE_CHARGE);

    // add the routine services checkboxes to the routine services panel
    routineServicesPanel.add(oilChange);
    routineServicesPanel.add(lubeJob);
    routineServicesPanel.add(radFlush);
    routineServicesPanel.add(tranFlush);
    routineServicesPanel.add(inspection);
    routineServicesPanel.add(mufflerRepl);
    routineServicesPanel.add(tireRotate);

    // place the routine services panel at the top of the frame
    add(routineServicesPanel, BorderLayout.NORTH);

    // build a panel for the custom services text fields
    JPanel customServicesPanel = new JPanel();
    customServicesPanel.setLayout(new GridLayout(2, 3));
    customServicesPanel.setBorder(BorderFactory.createTitledBorder("Custom Services"));

    // build the custom services text fields
    final JTextField customService = new JTextField("Service: ");
    final JTextField customParts = new JTextField("Parts: ");
    final JTextField customLabor = new JTextField("Labor: ");
    final JTextField customTotal = new JTextField("Total: ");
    customTotal.setEditable(false);

    // add the custom services text fields to the custom services panel
    customServicesPanel.add(customService);
    customServicesPanel.add(customParts);
    customServicesPanel.add(customLabor);
    customServicesPanel.add(customTotal);

    // place the custom services panel in the center of the frame
    add(customServicesPanel, BorderLayout.CENTER);

    // build a panel for the total and the action button
    JPanel displayPanel = new JPanel();

    // build labels and associated text/buttons
    final JLabel totalLabel = new JLabel("TOTAL: ");
    final JTextField total = new JTextField("$0000.00");
    final JButton calculate = new JButton("Calculate");

    // add a listener to the calculate button
    CalcButtonListener listener = new CalcButtonListener();
    // register the button listener
    calculate.addActionListener(listener);

    // add the display fields to the display panel
    displayPanel.add(totalLabel);
    displayPanel.add(total);
    displayPanel.add(calculate);

    // place the display panel at the bottom of the frame
    add(displayPanel, BorderLayout.SOUTH);

    // complete the frame definition
    setSize(700, 500);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    pack();
    setVisible(true);


    } // terminates JoesAuto constructor

    // build a private inner class to process the interrupt and
    // handle the logic
    // this class is still within the outer class, but not within the constructor
    private class CalcButtonListener implements ActionListener
    {

    // the interrupt handler if the calculate button is clicked
    public void actionPerformed(ActionEvent e)
    {
    // local variables
    double routineCharges = 0;
    double customPartsCharges = 0;
    double customLaborCharges = 0;
    double customTotalCharges = 0;
    double totalCharges = 0;
    JoesAuto jac = new JoesAuto();

    // accumulate charges for the routine services
    // ERROR "oilChange cannot be resolved"
    // ERROR [this error occurs with lubeJob, radFlush, tranFlush ... as well]
    if (oilChange.isSelected())
    {
    routineCharges =+ OIL_CHANGE_CHARGE;
    }
    if (lubeJob.isSelected())
    {
    routineCharges =+ LUBE_JOB_CHARGE;
    }
    if (radFlush.isSelected())
    {
    routineCharges =+ RAD_FLUSH_CHARGE;
    }
    if (tranFlush.isSelected())
    {
    routineCharges =+ TRAN_FLUSH_CHARGE;
    }
    if (inspection.isSelected())
    {
    routineCharges =+ INSPECTION_CHARGE;
    }
    if (mufflerRepl.isSelected())
    {
    routineCharges =+ MUFFLER_REPL_CHARGE;
    }
    if (tireRotate.isSelected())
    {
    routineCharges =+ TIRE_ROTATE_CHARGE;
    }

    // calculate custom charges from user entry
    // ERROR "customParts cannot be resolved
    customPartsCharges = Double.parseDouble(customParts.getText());
    // ERROR "customLabor cannot be resolved
    customLaborCharges = Double.parseDouble(customLabor.getText()) * 20.0;
    customTotalCharges = customPartsCharges + customLaborCharges;
    customTotal.setText("Total: " + customTotalCharges);

    // sum routine charges and custom charges
    totalCharges = customPartsCharges + customLaborCharges + routineCharges;

    // display summed charges
    // ERROR "displayPanel cannot be resolved
    total.setText("Total: " + totalCharges);

    } // terminates the actionPerformed method
    } // terminates the private inner class
    } // terminates JoesAuto class

    ----
    The errors are marked with comments that say ERROR.

    Can anybody help me out? I know it's just something stupid, but I can't find it.

    Thanks in advance.

  2. #2
    Join Date
    Aug 2006
    Posts
    10
    Anybody?

  3. #3
    Join Date
    Mar 2004
    Posts
    78
    Yo,

    You define a class, right? Than you want to acces some variables from the outter class ?

    Wel, there is nothing wrong with this except if the variables are not properties of the outter class. What I saw in the code is that in the constructor you create some variables. Well the inner class has no idea of them and run time it will never get any idea.

    1. Add reference to the objects you create as property of the outter class.
    2. Use the fully qualified name of the variable:


    public class JoesAuto extends JFrame {

    // some suff

    final JCheckBox oilChange;
    // or final JCheckBox oilChange = new JCheckBox.....

    // other stuff

    private class CalcButtonListener implements ActionListener {

    public void actionPerformed(ActionEvent e) {

    JoesAuto.oilChange.doAnythingYouWant(<params>);
    }
    }
    }


    And I am not sure if you do not need to add a static modifier to the inner class.

    NewUniverse

  4. #4
    Join Date
    Aug 2006
    Posts
    10
    You're exactly right. The components in the outer class were defined locally to the constructor, but were never defined to the the outer class globally. Duh.

    I got that part fixed.

    Now I'm getting runtime errors (null pointer exceptions) on the check boxes.

    What I want is for the user to be able to check the appropriate boxes for the routine services, add any custom services in the text fields, and then hit the "calculate" button and have everything tallied up. I don't want the system to calculate a total everytime a check box is checked or unchecked, so I didn't register an item listener for each checkbox component because that would trigger an event.

    Is that the right way to look at it, or will I have to have those listeners and then code the logic to handle the checkbox event(s) one way and the "calculate" event another?

    Thanks for the quick reply, by the way.

  5. #5
    Join Date
    Aug 2006
    Posts
    10
    Specifically, the runtime errors I'm getting now are:

    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at JoesAuto$CheckBoxListener.itemStateChanged(JoesAuto.java:151)
    at javax.swing.AbstractButton.fireItemStateChanged(Unknown Source)
    at javax.swing.AbstractButton$Handler.itemStateChanged(Unknown Source)
    at javax.swing.DefaultButtonModel.fireItemStateChanged(Unknown Source)
    at javax.swing.JToggleButton$ToggleButtonModel.setSelected(Unknown Source)
    at javax.swing.JToggleButton$ToggleButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
    ----

    ***? This happens if I 1) click any of the checkboxes;
    2) enter any of the text fields;
    3) click the calculate button.

    The "null pointer exception" is coming out of the "oilChange" checkbox (that's Line 151). From what I can deduce, the JRE is trying to fire an ItemStateChanged event when the box is clicked, which passes the event up through the abstract.buttonhandler and the DefaultButton stuff etc.. But they all say "unknown source," which indicates that the don't know where the event came from. That would lead me to believe that the event isn't registered, but all the checkboxes have listeners registered to them in the constructor.

    Is this another "duh"?

  6. #6
    Join Date
    Aug 2006
    Posts
    10
    Let me show an even simpler example. This gets the same stupid NullPointerException on the displayTotal.getText().

    ---
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;

    public class CheckTest extends JFrame
    {
    private JTextField test;
    private JTextField display;
    private JButton work;

    public CheckTest()
    {
    super("Services Invoice");
    JFrame testFrame = new JFrame();
    JTextField test = new JTextField(10);
    JTextField display = new JTextField(10);
    JButton work = new JButton("work");
    JPanel testPanel = new JPanel();
    testPanel.setLayout(new GridLayout(3, 1));
    testPanel.add(test);
    testPanel.add(display);
    testPanel.add(work);
    add(testPanel, BorderLayout.NORTH);

    WorkButtonListener listener = new WorkButtonListener();
    work.addActionListener(listener);

    setSize(700, 500);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    pack();
    setVisible(true);
    }

    private class WorkButtonListener implements ActionListener
    {

    // the interrupt handler if the calculate button is clicked
    public void actionPerformed(ActionEvent e)
    {
    String displayTest = new String("");
    displayTest = test.getText();
    display.setText(displayTest);

    }
    }
    }

    ----

    This is not rocket science, yet the event handler seems to choke and puke on it every time.

Similar Threads

  1. Assembly class
    By Shailesh C.Rathod in forum .NET
    Replies: 2
    Last Post: 03-13-2002, 08:53 PM
  2. Replies: 6
    Last Post: 06-19-2001, 12:47 AM
  3. How To Do It - Shared Class Variables Part III
    By Patrick Ireland in forum .NET
    Replies: 5
    Last Post: 05-10-2001, 07:19 PM
  4. How To Do It - Shared Class Variables Part IV
    By Patrick Ireland in forum .NET
    Replies: 3
    Last Post: 05-07-2001, 04:04 PM
  5. problem with zipinputstream class
    By dinesh in forum Java
    Replies: 1
    Last Post: 11-29-2000, 12:19 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center