This week's book giveaway is in the Mac OS forum.
We're giving away four copies of a choice of "Take Control of Upgrading to Yosemite" or "Take Control of Automating Your Mac" and have Joe Kissell on-line!
See this thread for details.
The moose likes Swing / AWT / SWT and the fly likes Help with ActionListener Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "Help with ActionListener" Watch "Help with ActionListener" New topic
Author

Help with ActionListener

Adam Burda
Ranch Hand

Joined: Jul 19, 2011
Posts: 40
Hello all, I need help again. I making a simple porgram. But i having trouble with the Actionlistener.

Here is my code.



and I am getting an error

TestForm.java:34: addActionListener(java.awt.event.ActionListener) in javax.swing
.AbstractButton cannot be applied to (TestForm.Panel1)
button1.addActionListener(this);
^

Nitin Surana
Ranch Hand

Joined: Jan 21, 2011
Posts: 129

You've tried creating nested classes and hence addActionListener(this) refers to the innerclass which doesn't implement the ActionListener Interface.
Adam Burda
Ranch Hand

Joined: Jul 19, 2011
Posts: 40
So do I resolve it?
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18570
    
    8

You don't have to resolve it, no. Of course if you don't then your code will just be a bunch of text which can't be run. So it's up to you whether you want to resolve it or not.

If you do, I would recommend (since you said you were writing a simple program) that you don't create a nested class like that. It isn't necessary, you can create a JPanel object in your main class and add buttons to it just fine without having to erect a whole new class.
Adam Burda
Ranch Hand

Joined: Jul 19, 2011
Posts: 40
Yes i did say it was a simple program. But i was playing with the nesting the panel. and wanted to do a ActionListener with in it. So do I add the ActionListener to the Panel class? If so can you show me how. Becouse Panel1 extends JPanel implements ActionListener, does not work.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18570
    
    8

Well, if you're going to be using nested classes anyway, let's get rid of the old-fashioned bad design where the whole GUI class implements ActionListener. That's bad object-oriented design because you're saying "This class (which creates a GUI) IS-AN ActionListener". But it isn't, at least that's not its primary purpose. Instead it should HAVE-AN ActionListener. In fact in real life such a class could have several ActionListeners. If you use the style you're using now, you can only have (be) one, and therefore it has to have code which deals with several different buttons. Again bad design; a method should have only one purpose.

Now I know you wrote the code that way because you based it on an example you saw somewhere. There's lots of examples like that. But what I'm saying is, don't follow those examples because there are better ways.

So. Here's your nested class:

But you don't want "addActionListener(this)" because "this" -- the Panel1 object being constructed -- isn't an ActionListener. And as I've being saying, it shouldn't be one anyway. It should contain an ActionListener object which does just what that button needs and nothing else. So start like this:

If you leave it like this then you'll get an error message saying you can't instantiate the ActionListener interface. So let's write an anonymous inner class which subclasses ActionListener:

Which will tell you that you haven't implemented the required methods from that interface, so let's do that:

At which point the compiler is happy. But you aren't, because the method doesn't actually do anything. What should it do? Put that code into the method:

And there you go.
Jason Bullers
Greenhorn

Joined: Dec 27, 2011
Posts: 28

I agree completely with Paul. I'd also like to add that there isn't usually any compelling reason to subclass JFrame, either. If you're going to be working with GUI code, it's better to start right. To start with, we'll not extend the JFrame class anymore. Instead, we create an instance of JFrame. This is done using SwingUtilities.invokeLater(Runnable) to ensure that our GUI code executes on the Event Dispatch Thread (EDT). All GUI code should be handled on that thread only.


Next, we can add the rest of the code you had in the constructor. Note that I've moved setVisible(boolean) to be the last call. It's better to call this only once all of the content has been added. pack() will make the frame as small as it can be while still fitting all of the components you want it to contain. You can move your setSize(int, int) call to the Panel1 class, instead. Try using setPreferredSize() or overriding getPreferredSize() rather that calling setSize(). Doing it this way also has the added benefit of knowing exactly how big your canvas is: the panel with the button is 600 x 100 now, whereas before, the whole window was 600 x 100. The size of the panel is dependent on how much space is taken up by the frame's decorations.


Just for the sake of completeness, your fields can now probably just be local variables in Panel1's constructor. It's generally a good idea to reduce the scope of your variables to the minimum they can be. There's less potential for accidents that way.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18570
    
    8

Yeah, that too.
Adam Burda
Ranch Hand

Joined: Jul 19, 2011
Posts: 40
Hey Guy's, Thank you for your time. That was very helpfull.
Adam Burda
Ranch Hand

Joined: Jul 19, 2011
Posts: 40
Ok I am a total noob. When I run the app i get a new error.

TestForm.java:19: non-static variable this cannot be referenced from a static context

frame.setContentPane(new Panel1());
^

also as for the setPreferredSize(400,200); is that placed in the panel1 class?

Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39079
    
  23
Move the entire Frame code into a class of its own. Let’s call it MyDisplay.Now you simply write new MyDisplay(); in the run() method. I think setPreferredSize() applies to the panel.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39079
    
  23
I think this discussion would fit better onto our GUIs forum. Moving.
Jason Bullers
Greenhorn

Joined: Dec 27, 2011
Posts: 28

Adam Burda wrote:Ok I am a total noob. When I run the app i get a new error.

TestForm.java:19: non-static variable this cannot be referenced from a static context

frame.setContentPane(new Panel1());
^

also as for the setPreferredSize(400,200); is that placed in the panel1 class?


The error you are getting refers to the Panel1 object (note how there is an arrow ^ pointing at it). The way you have declared your inner class, it is tied to instances of the outer class. There doesn't seem to be any reason to have Panel1 tied to your main class, so you should be able to declare Panel1 as static and everything should work just fine. A static inner class is effectively a stand alone class with nested scope.

And yes, place that call in the Panel1 class.

EDIT: What Campbell said with the MyDisplay class is another option. Doing it that way, you don't have to make your inner class static; you are no longer trying to create an instance of that inner class from a static context, so it will work. For a little more information on inner classes, take a look at my posts here.
 
GeeCON Prague 2014
 
subject: Help with ActionListener