1

I'm going off of what I saw in a textbook to make an action listener for a button. To do it, I made an inner class. When I try to call the inner class, the error comes up: cannot find symbol.

Here's the code:

package GUI;

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

public class ATMGUI extends GUI
{

    public ATMGUI()
    {

    this.makePane();
      this.makeButton("Withdraw");
        button.addActionListener(new WithdrawListener());
        pane.add(button);
      this.makeText("Enter amount to withdraw: ");
        pane.add(text);
      this.makeTextField("Enter amount here");
        pane.add(field);
    this.makeFrame();
    frame.add(pane);

    class WithdrawListener implements ActionListener
    {
        public void actionPerformed(ActionEvent click)
        {
        System.out.println("This is a test.");
        }
    }
    }
//------------------------------------------------------------------
    public void makeFrame()
    {
    frame = new JFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(500, 500);
      frame.setVisible(true);
    }

    public void makePane()
    {
    pane = new JPanel();
      pane.setLayout(new GridLayout(3,3));
      pane.setVisible(true);
    }

    public void makeButton(String buttonName)
    {
    button = new JButton(buttonName);
    }

    public void makeText(String addText)
    {
    text = new JLabel(addText);
    }

    public void makeTextField(String addText)
    {
    field = new JTextField(addText);
    }
}

This is the particular bit that is giving me trouble

button.addActionListener(new WithdrawListener());

I saw somewhere else that it had to be instantiated in a certain way. I tried something like:

    ATMGUI a = new ATMGUI();
    ATMGUI.WithdrawListener w = a.new WithdrawListener();

and then put w in for the argument, but that didn't really work for me either. Not sure if it is because I'm working in a subclass. Also not really sure if things need to be done differently because I'm working with an interface.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
aaa
  • 13
  • 5

4 Answers4

1

Place the WithdrawListener outside of the constructor context

public class ATMGUI extends GUI {

    public ATMGUI() {
        //...
        button.addActionListener(new WithdrawListener());  
        //...
    }

    class WithdrawListener implements ActionListener {

        public void actionPerformed(ActionEvent click) {
            System.out.println("This is a test.");
        }
    }
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • maybe OP wants the class to be local and not nested? – Aniket Thakur Apr 03 '15 at 04:32
  • @AniketThakur Based on what the OP's attempted and the reference to "inner class", this is my best guess at what they were aiming for. And while it's just my opinion, it's also easy to read – MadProgrammer Apr 03 '15 at 04:36
  • Yup if it is just used at one place IMO anonymous class would be better. – Aniket Thakur Apr 03 '15 at 04:37
  • Putting the inner class outside the constructor worked! I realize now why that wasn't working. (This stuff is pretty new to me if you haven't guessed, haha) Though it's true that this particular listener won't be reused, there will be others that will. So, this method matches up best with what I was looking for. Though, anonymous classes are really helpful too. – aaa Apr 03 '15 at 05:17
  • I really wish I could, especially since both methods are what I need. But unfortunately, I do not have the permissions to vote yet. – aaa Apr 03 '15 at 05:24
0

Add listener to button after local class declaration.

public void abc(){
    PQR pqr = new PQR(); // incorrect

    class PQR {

    }   
}

Correct way is

public void abc(){
    class PQR {

    }
    PQR pqr = new PQR(); //correct
}
Aniket Thakur
  • 66,731
  • 38
  • 279
  • 289
0

It seems like you must declare the local class before you use it. The follwing code snippets I tested:

This one showed no errors:

public void testFunc() {
    class Test {
    }
    Test test = new Test();
}

But this one does:

public void testFunc() {
    Test test = new Test();
    class Test {
    }
}

Edit: Sorry for posting nearly at the same time, next time I will check three times if someone already posted.

Quallenmann
  • 323
  • 2
  • 8
0

Use of anonymous type is recommended when you are not reusing a class.

Have a look at it (frequently used with listeners) - It's a great answer!! quoted from above link

Using this method makes coding a little bit quicker, as I don't need to make an extra class that implements ActionListener -- I can just instantiate an anonymous inner class without actually making a separate class.

I only use this technique for "quick and dirty" tasks where making an entire class feels unnecessary. Having multiple anonymous inner classes that do exactly the same thing should be refactored to an actual class, be it an inner class or a separate class.

this.makePane();
      this.makeButton("Withdraw");
        button.addActionListener(new ActionListener() { //starts here

            public void actionPerformed(ActionEvent click)
            {
            System.out.println("This is a test.");
            }
        });//ends
        pane.add(button);
      this.makeText("Enter amount to withdraw: ");
        pane.add(text);
      this.makeTextField("Enter amount here");
        pane.add(field);
    this.makeFrame();
    frame.add(pane);
Community
  • 1
  • 1
theRoot
  • 571
  • 10
  • 33
  • *"Obviously two buttons do not have same actions"* - Oh, I don't know, a `JMenuItem` (which is a type of button) and `JButton` (either as a standard button and/or as a toolbar button) might share the same listener, personally, I'd go for a `Action` instead, but that's just me. – MadProgrammer Apr 03 '15 at 04:50
  • Interesting. This is the first time I've seen an anonymous type before. This looks a lot simpler. Thanks! – aaa Apr 03 '15 at 04:59
  • @ArdjenLane have a look at [docs](https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html) for better understanding – theRoot Apr 03 '15 at 05:06