Click to See Complete Forum and Search --> : JMenuBar question
Qubit
03-27-2002, 04:37 PM
What is the best way to handle events that come from a menubar in Java? The only thing I can think of is having one big function like this
public void actionPerformed(ActionEvent e) {
String name = e.getActionCommand();
if ( name == "name1" ) {
// ...
} else if ( name == "name2" ) {
// ...
} // etc.
}
But somehow this looks too sloppy for me. Would it be possible to write a small anonymous class for each JMenuItem, that has only the code for that particular menu item?
Like this:
JMenuItem exit = new ...
exit.addActionListener(new ActionListener() {
// do only exit code here
});
JMenuItem somethingelse = ...
somethingelse.addActionListener( etc. )
How do the big boys handle this?
TheLinuxDuck
03-28-2002, 01:36 AM
Qubit:
I wish that I could help you, I've been out of Java for a while, and am in dire need of a refresher.. (^=
And, I also am prolly going to be doing some kind of BBS etiquette no-no.. but, I know who can answer your question. If you don't mind registering with another BBS, Dru Lee Parsec can help you here:
http://www.coderforums.net/forumdisplay.php?s=86fa5de77c8dc354755deb092be6179 9&forumid=32
He does Java for a living, so I know that he will have some answers.. there's another fellow here that is good with Java, nanode, but I haven't seen him around lately..
If you don't have any answers later this week, let me know, and I'll see if I can find one of my old sources that uses the JMenuBar, to see if it helps.
Bradmont5
03-28-2002, 02:26 AM
Originally posted by Qubit:
<STRONG> Would it be possible to write a small anonymous class for each JMenuItem, that has only the code for that particular menu item?
Like this:
JMenuItem exit = new ...
exit.addActionListener(new ActionListener() {
// do only exit code here
});
JMenuItem somethingelse = ...
somethingelse.addActionListener( etc. )
How do the big boys handle this?</STRONG>
yes, an anonymous class will work fine... like this:
JMenuItem exit = new ...
exit.addActionListener(new ActionListener() {
void actionPerformed(ActionEvent e){
// do stuff here
}
});
(that's pretty much what you had)
As for how the big boys handle it... I'm not sure... either like that, or separate classes, which lets you reuse them elsewhere.
Stuka
03-28-2002, 11:29 AM
The one project I wrote a menu on (for school), I used the second bit you listed almost exactly. I don't know that it's the "best" way, but what I did was to have the action listener call a defined function - this let me call that same function from another location (a windowClosing event for example) and keep my code for exiting, etc. in one place.
Dru Lee Parsec
03-28-2002, 01:04 PM
OK, JMenuBar is the actual menu bar across the top. The JMenuBar has JMenu objects added to it. The JMenu is the entire drop down menu part.
Within the JMenu are a bunch of JMenuItem objects. Now, look at the constructor of the JMenuItem. One of them is
public JMenuItem(Action a)
OK, so what you can do it to build an action and add it to the JMenuItem. What I do is to extend an AbstractAction object because it can have an icon and a String and an actionPerformmed method to whatever happens when the menu is clicked.
I also make my actions a Singleton object. That way, I can use exactly the same object for a menu item or a tool bar button. Here's some example code.
package com.tapper.actions;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import com.tapper.dialogs.*;
public class AboutBoxAction extends AbstractAction{
private static AboutBoxAction theOnlyOne = null;
public static AboutBoxAction getInstance(){
if (theOnlyOne == null){
theOnlyOne = new AboutBoxAction();
}
return theOnlyOne;
}
private AboutBoxAction() {
super("About Tapper");
}
public void actionPerformed(ActionEvent e){
AboutBoxDialog.getInstance().setVisible(true);
}
}
To add it to a JMenuItem you can do this:
JMenu helpMenu = new JMenu("Help");
JMenuItem helpAbout = new JMenuItem( com.tapper.actions.AboutBoxAction.getInstance());
helpAbout.setMnemonic('A');
helpMenu.setMnemonic('H');
helpMenu.add(helpAbout);
Then add helpMenu to your JMenuBar.
Qubit
03-28-2002, 03:07 PM
Wow Dru, that's some pretty leet Java! I understand how it works, only the Singleton class is new. What does it do? I can't find it anywhere in my API docs...
I haven't worked out the actions for the rest of my menuitems yet. I'll give it a shot for the longer parts of code.
Posted by TheLinuxDuck:
If you don't mind registering with another BBS, Dru Lee Parsec can help you here:
Well, Dru Lee Parsec helped me out here already, but I've registred anyway :D Thanks for the hint!
About the anonymous classes: I noticed that that approach worked, but I wasn't sure how Java handled events: I thought that maybe all event handlers received an ActionEvent, instead of just one handler.
Thanks for pointing that out to me!
Dru Lee Parsec
03-28-2002, 06:00 PM
A Singleton isn't part of the API, it's what's called a "Design Pattern". The point of a singleton is to make sure that if several classes use this class they will all use exactly the same instance of the class.
For example, I only want to build one "About Box". But let's say I want that about box to be fired up from a menu item and from a tool bar button (I wouldn't actually do that with an about box, but let's use it as an example)
OK, I don't want to build 2 about boxes in memory so I want to make sure that whoever ask for an about box the first time will cause the dialog box to be constructed. Every subsequent request for that about box gets back exactly the same instance that was already constructed.
The same thing is happening in our action. I don't want to load up memory with 2 instances of this action.
The way we do this is to make the default constructor private. Then we make a static method called getInstance. There is also a private static instance of the action called "theOnlyOne" and it's set to null.
[refer to the code above while reading this]
The first time the getInstance() method is called it checks to see if theOnlyOne is null. If it is then it calls the constructor. Since the getInstance method is inside the class it has access to the private constructor.
Now another class does a getInstance Request. It checks to see if the static member "theOnlyOne" is null. It's not! So it simply returns the one that was already created. This way, there is only one instance EVER created of this object.
Why would we need this? Is saving memory such a big thing? Well no, but now assume that you have a dialog box that holds a bunch of settings. If you didn't use a Singleton and you had your Menu and Toolbar each create separate instances of that dialog box then if you opened it with the menu and made some changes then those changes wouldn't appear when you open the same dialog box via the tool bar because they're different instances of the dialog box.
There are several other uses for a SIngleton. For further discussion of Design Patterns check out the book "Design Patterns" by Gamma, Helm, Johnson & Vlissides.
Stuka
03-29-2002, 10:56 AM
Dru Lee - great code. I should've thought about the Singleton on that, but, hell, that's why your the pro, and I'm a wannabe! :D Keep up the good work (coding and teaching)! And glad to see you back more often!
Qubit
03-29-2002, 01:25 PM
:eek:
Now I see! Thanks for the info! I've already made some similar classes, and it fits in just great!
(That design patterns stuff starts to look more useful & less boring, it seems)
Dru Lee Parsec
03-29-2002, 01:29 PM
I just wanted to add that if you want to see a bunch of source code that demonstrates all of these techniques then go to http://tapper.sourceforge.net/
You can download the source code at https://sourceforge.net/project/showfiles.php?group_id=10887
One of the things you will notice is that the menu of my Tapper project has the Java Look & Feel settings on it. You can select System, Windows, Java default, Motif, or Mac look & feel. (although not all L&F's are supported on all OS's. i.e. Mac is only available on a Mac, Windows is only available on Windows etc)
Check out the scrolling text in the about box. :)
I really need to start working on that project again. Work, projects at home and chess have been keeping me busy.
Stuka
03-29-2002, 07:03 PM
I did dl that stuff, and looked at it between semesters once...but school started back up and kicked my butt! I don't know squat about music, but I'd like to work on some code there - if you have a spot that could use work but needs no musical knowledge, I'll give it a shot in about 3 1/2 weeks (when the semester is over).
Dru Lee Parsec
03-29-2002, 08:04 PM
That would be awesome!
MKIIISupra is also working with me (as has nanode) on that project. I'm trying to finish an XML parser for it now (Time, all I need is time) and then there is a LOT of non-music related work to do.
In fact, the whole thing can be approached as a mathematical and algorithmic application. The ouput just happens to be of a musical topic.
In the interim, if you havn't done so already then sign up as a user on sourceforge and email me your user name at
<anti spam block>
druleeparsec AT users DOT sourceforge DOT net
</anti spam block>
That way when you're ready I can add you as a developer and give you cvs access.
Qubit
03-30-2002, 03:27 AM
mathematical
count me in :D