File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Swing / AWT / SWT and the fly likes Getting my main class and GUI components to talk without inner classes Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "Getting my main class and GUI components to talk without inner classes" Watch "Getting my main class and GUI components to talk without inner classes" New topic
Author

Getting my main class and GUI components to talk without inner classes

Luigi Plinge
Ranch Hand

Joined: Jan 06, 2011
Posts: 441

I'm doing the Quiz Card example from Head First Java (p 448-), but to make things interesting, I'm using NetBeans' GUI Builder rather than writing the code myself.

I have a CardBuilderPanel, which extends JPanel and contains text fields and buttons, that I create from my QuizCardBuilder instance, and also a CardBuilderFrame, which extends JFrame and contains menu items.

When I click a button in the panel I need it to send a QuizCard object back to my QuizCardBuilder to store in an ArrayList there. Likewise, I need to call a Save method in QuizCardBuilder when I click a menu item on the frame.

If the frame and panel were inner classes it would be easy, but they're not and I don't think they can be, using the GUI Builder. How do I do it? The frame and panel don't have a reference to the object that created them.

Do I have to create another listener in QuizCardBuilder... if so how, as it doesn't have references to the private components of the panel and frame?
Mohamed Sanaulla
Saloon Keeper

Joined: Sep 08, 2007
Posts: 3068
    
  33

You can always have a reference to the QuizCardBuilder instance in the GUI components and when ever you click on button you can invoke the addToList (supposing this adds the object to the list) method of the QuizCardBuilder instance to add the QuizCard object.

Can you post the code so that we can help you better?


Mohamed Sanaulla | My Blog
Luigi Plinge
Ranch Hand

Joined: Jan 06, 2011
Posts: 441

You can always have a reference to the QuizCardBuilder instance in the GUI components and when ever you click on button you can invoke the addToList (supposing this adds the object to the list) method of the QuizCardBuilder instance to add the QuizCard object.

But how do I get the reference to the QuizCardBuilder into the GUI components?

If you have a class Foo that creates a Bar, then your Foo can access the Bar's methods with bar.doSomething(), but if your Bar reacts to an event and wants to call back the Foo that created it, how does it do it?

Here are what the components look like + the code. I don't include all the generated stuff because it's too long.

The CardBuilderFrame:


The CardBuilderPanel:









As it is, for some reason the CardBuilderPanel is not displayed in the CardBuilderFrame. I don't know why. I just see the frame. If I replace the CardBuilderFrame in QuizCardBuilder with a regular JFrame, it displays the panel.

Do I have to make the CardBuilderPanel a instance variable of the CardBuilderFrame?

If I did that I could store the QuizCards in a List in the CardBuilderPanel (as I have above), and also add a save method to the panel, which can be called by the frame when the Save menu item is clicked.

I guess this approach would work, but I end up having all my application logic within my CardBuilderPanel class. It doesn't seem right to do it like this, because I just want to keep my GUI classes doing GUI things like displaying text fields, rather than being the application itself. It can't be normal to have a whole application that is an extension of JFrame?
Luigi Plinge
Ranch Hand

Joined: Jan 06, 2011
Posts: 441

I managed to get the panel to display... I changed the frame layout to BorderLayout...
Luigi Plinge
Ranch Hand

Joined: Jan 06, 2011
Posts: 441

Well, I have my version of the QuizCard app up and running now, including a Viewer frame / panel, but with all the code within the panel and frame class files.

I guess what I wanted to do is to put the listeners in the QuizCardBuilder class. All this class does at the moment is to call up a new frame and display it, while the frame and panel take care of all the logic.

I could implement this by adding accessor methods to the buttons and menu items, then put listeners in QuizCardBuilder using

but this seems a bit long-winded.
Mohamed Sanaulla
Saloon Keeper

Joined: Sep 08, 2007
Posts: 3068
    
  33

You can make QuizCardBuilder as an instance variable in CardBuilderFrame and in all the action listeners you can use the QuizCardBuilder instance to invoke the methods.
Luigi Plinge
Ranch Hand

Joined: Jan 06, 2011
Posts: 441

But if the QuizCardBuilder is a variable of the CardBuilderFrame, how do I invoke its methods from the buttons on the CardBuilderPanel? I need to use both the menu items in the frame and the buttons and text fields on the panel.
Mohamed Sanaulla
Saloon Keeper

Joined: Sep 08, 2007
Posts: 3068
    
  33

Luigi Plinge wrote:But if the QuizCardBuilder is a variable of the CardBuilderFrame, how do I invoke its methods from the buttons on the CardBuilderPanel? I need to use both the menu items in the frame and the buttons and text fields on the panel.


Then you can make it part of both the components.
Luigi Plinge
Ranch Hand

Joined: Jan 06, 2011
Posts: 441

But it will then be 2 different instances, so if I try to use a method to save it from the frame, it won't contain the questions/answers that have been added on the panel.

Plus it doesn't make sense to have it as an instance variable. QuizCardBuilder is the application itself and creates the frame and panel - it doesn't belong to the frame or panel.
Mohamed Sanaulla
Saloon Keeper

Joined: Sep 08, 2007
Posts: 3068
    
  33

Luigi Plinge wrote:But it will then be 2 different instances, so if I try to use a method to save it from the frame, it won't contain the questions/answers that have been added on the panel.

Plus it doesn't make sense to have it as an instance variable. QuizCardBuilder is the application itself and creates the frame and panel - it doesn't belong to the frame or panel.


You are creating the Frame and panel objects at the same time. While you are creating it- You can pass a reference to QuizCardBuilder
Luigi Plinge
Ranch Hand

Joined: Jan 06, 2011
Posts: 441

Good idea!

I could invoke instantiate the frame with

and then use it as an instance variable in the frame and panel.

Is this a standard way of doing things? I haven't seen it before.
Mohamed Sanaulla
Saloon Keeper

Joined: Sep 08, 2007
Posts: 3068
    
  33

I dont know if its a standard or not. But usually if you see the MVC architecture- You would have Controller Classes which respond to the actions from the UI and Model classes which actually represent the data you are working with. In your case- You have the View classes- JFrame, JPanel and then one class which has methods which respond to different actions and these methods then work on the data you have created during the response to the action.
Luigi Plinge
Ranch Hand

Joined: Jan 06, 2011
Posts: 441

If anyone's interested, I got a bunch of instances running in different threads all talking to each other using the method suggested above, giving the output

After 0.1 seconds, Controller #1 calls Jemaine
After 0.4 seconds, Brahbra calls Murray
...Murray explodes!
After 0.4 seconds, Murray calls Bret
After 0.9 seconds, Murray calls Brahbra
...Brahbra explodes!
After 1.1 seconds, Brahbra calls Jemaine
After 1.1 seconds, Controller #2 calls Bret
After 1.3 seconds, Bret calls Brahbra
...Brahbra explodes!
After 1.4 seconds, Murray calls Bret
After 1.9 seconds, Jemaine calls Murray
...Murray explodes!
After 2.0 seconds, Controller #1 calls Murray
...Murray explodes!
After 2.1 seconds, Controller #2 calls Bret
After 2.4 seconds, Bret calls Controller #2
After 2.7 seconds, Brahbra calls Jemaine
After 2.9 seconds, Murray calls Brahbra
...Brahbra explodes!
After 3.1 seconds, Murray calls Controller #1

etc.

Each instance calls another instance, which calls the first back to get its ID. The different classes can react in different ways to being called, like exploding.

They don't have to be the same class. In this example I set up an interface and extended an abstract class to save having to re-implement the same methods, but you don't need to and could do it on a class by class basis by overloading the "link" method. (I suspect generics could come in handy but I haven't read up on those yet.)







 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Getting my main class and GUI components to talk without inner classes