This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
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.
Joined: Jul 19, 2011
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.
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:
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.
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
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.