Friday, December 25, 2009

Swing Event Handling Part 2

Last post discussed some possible improvements to Swing event handling. With a few drawbacks.

The first was that the code presented could only easily fire one type of event. Which is easy to fix. In Java, or any similar language, whenever you want to expand from "one type of thing" to "multiple types", consider a Map. We define Broadcasters, which is essentially a

HashMap<Class<? extends EventObject>, Broadcaster>



The three main methods are straightforward:
public synchronized void addListener(Class eventClass, EventListener l) {
Broadcaster b = classMap.get(eventClass);
if (b != null)
b.addListener(l);
else if (l instanceof GenericListener) {  // automatically handle these
b = new Broadcaster.Generic();
b.addListener(l);
classMap.put(eventClass, b);
}
else throw new RuntimeException("no broadcaster for " + eventClass);
}

public void fireEvent(EventObject event) {
Broadcaster b = classMap.get(event.getClass());
if (b != null)
b.fireEvent(event);
}


public void removeListener(Class eventClass, EventListener l) {
classMap.get(eventClass).removeListener(l);
}



One problem solved. As for having multiple listeners in a class, that's trickier. A class cannot declare that it implements GenericListener, and GenericListener because, after erasure, these are the same. One solution is to use an inner class. I'm not a big fan of anonymous inner classes, but a lot of programmers (and example code) use these for their listener code anyway, so this is no different or no worse than much current practice. e.g.





addListener(Foo.class, new GenericListener() {

@Override
public void handleEvent(Foo event) {
// do something here
}

}

No comments:

Post a Comment