Advertisement

[java] OO Styles

Started by May 10, 2000 06:40 PM
11 comments, last by Jim_Ross 24 years, 7 months ago
I recently read an article on javaworld about seperating GUI actions from the classes that instatiate them. Instead of making a MenuBar class that implements ActionListener and including tons of if(e.getSource() == such&such MenuItem) {...} you create the buttons with a JFC Action object. These provide basic strings, icons, and event handlers for JFC atomic components, which eliminates lenghty actionPerformed() methods from your classes. This is all fine and I didn''t know aoout the Action class before, but the author put down the method of making individual subclasses for each GUI piece. For example, to make a "new" button and an "ok" button you would make a class OkButton extends JButton, and give component specific listeners and text and what not to that sub-class. Well, I did this a few times... mainly because I didn''t like the long event listeners in my GUI code. My question is, does anyone else use this latter and more frowned-upon style?
For simple things like buttons, I usually use anonymous inner classes:

JButton ok_button = new JButton("OK");
ok_button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
doOK();
}
});

For other things, like menu items in particular, the Action paradigm works great. The nice thing is you completely abstract the functionality from the form, which means that you can change the GUI without affecting the underlying funcionality, and you that you can also provide users with multiple ways to access the functionality. For example, you can have an Action accessible from an item in a menu, a toolbar button, or whatever other sort of input control you want.

This allows for great flexibility in GUI design, and also helps in establishing a customizable GUI. It''ll come in handy if you want to support undo/redo as well.

Ultimately, applications I write use a combination of actions, anonymous inner classes, and "traditional" event listeners.

Actions are used to do things to the "document" the user is working with.
Anonymous inner classes are for dialog buttons, window events, and other very basic things.
And traditional event listeners are used for things like processing mouse and keyboard events (and these may invoke Actions as well).
I am a Jedi, like my father before me
Advertisement
Hmm.. I fogot about anonymous inner classes. I never understood their syntax well when I was starting out, so i never really used them, except when the examples did. But I always use them with adapters if implementing the listener requires many method definitions. Here's the article for everyone interested, it's pretty good:

http://www.javaworld.com/javaworld/jw-04-2000/jw-0414-action.html

Edited by - Jim_Ross on May 11, 2000 9:56:24 AM
Adapters are the way to go for complex listener types. But in those cases, I''ll usually go the "traditional" route and use a class that implements the listener type (or extends the adapter), because I think that overly complex anonymous inner classes can render the code unreadable. I usually just call a single method from within the anonymous inner class method as in the example above, anyway, just to keep the clutter down.
I am a Jedi, like my father before me
I don''t know if this is the right way to do it, but I use something like this

class window extends Window implements ActionListener
{
...
...
Button button = new Button();

button.addActionListener(this);
...
public void actionPerformed(ActionEvent e)
{

if (e.getSource()== button)
{
System.exit(0);
}
}

}


Unluckily that getSource() doesn''t work anymore in 1.3 as it Did earliar and I haven''t downloaded it''s documentation so can anyone explain replacer for it?

Time comes, time goes and I only am.
Hm. I''d think that would continue to work. I don''t see anything in the docs or release notes that that''s changed... make sure that you''re comparing the same "button" reference in the event handler method that you assigned to begin with.

Otherwise, you might try using an anonymous inner class just for the buttons anyway.

I''ll have to do some messing around & see if I run into the same problems.
I am a Jedi, like my father before me
Advertisement
I don''t know if this changed since 1.3, but I''ve found that Event.getSource() always return an Object, so you have to cast, I end up doing something like this:

if( ((Button)e.getSource()).getText() == "OK" ) { ... }
One word of warning here -- never use == to compare two Strings, always use .equals().

The test (objectA == objectB) will return true if objectA and objectB both reference the same class instance, which is why event.getSource() == button *should* work.

But the equals method''s implementation is dependent on the object you''re comparing, and especially for Strings, when it''s the content of the Strings you want to compare, that''s an important distintion to make. So the test would be:

(button.getText().equals("OK"))

(I excluded the casting for clarity).

You should ALWAYS use this when comparing Strings.

Note, however, that

(objectA == objectB)

may return false, even though

(objectA.equals(objectB))

returns true. It''s the difference once again between comparing object instances and their contents.
I am a Jedi, like my father before me
The code that Arch@on posted should work in jdk1.3. I do those kinds of comparisons all the time and my programs run under jdk1.3.

I would advise against Mr Ross solution where he compares strings instead of button instances. It just makes harder internationalization and as an earlier poster wrote, the equals method is really the way to do it (the equals method for strings perform a == check too so it should not degrade performance much). You don''t need to cast the Object returned from e.getSource() if you just want to perform a == check against an instance of a Button, such as the one Arch@on does.

Henry
Well, how do you check the instance of getSource with the instance of a particular button if you don''t have an instance of that button?
Ex:

JButton jb = new JButton("OK");
jb.addActionListener(this);
panel.add(jb);
...

actionPerformed(ActionEvent e) {
if(e.Source() == jb) { //this won''t work
...
}

That''s why I use the text of the buttons, and I use == because I''m used to php, the compiler doesn''t complain, and the code runs.

This topic is closed to new replies.

Advertisement