• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

Help with ActionListener

 
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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);
^

 
Ranch Hand
Posts: 129
Netbeans IDE Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So do I resolve it?
 
Sheriff
Posts: 28371
99
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Sheriff
Posts: 28371
99
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 115
11
IntelliJ IDE Clojure Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Sheriff
Posts: 28371
99
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yeah, that too.
 
Adam Burda
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey Guy's, Thank you for your time. That was very helpfull.
 
Adam Burda
Ranch Hand
Posts: 43
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?

 
Marshal
Posts: 80281
432
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Marshal
Posts: 80281
432
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think this discussion would fit better onto our GUIs forum. Moving.
 
Jason Bullers
Ranch Hand
Posts: 115
11
IntelliJ IDE Clojure Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
My name is Inigo Montoya, you killed my father, prepare to read a tiny ad:
Smokeless wood heat with a rocket mass heater
https://woodheat.net
reply
    Bookmark Topic Watch Topic
  • New Topic