This week's book giveaway is in the Jython/Python forum.
We're giving away four copies of Murach's Python Programming and have Michael Urban and Joel Murach on-line!
See this thread for details.
Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Dumb question about Swing  RSS feed

 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dear JavaRanch,

Can anyone tell me why Swing (or AWT...or Java, for that matter) doesn't have an EventProducer interface?

I get that there may be many different types of Events, and that a component could be both a producer and Listener for a bunch of them, but it doesn't half make the API complicated.
All those add<whatever>Listener() and <whatever>Performed() methods seem incredibly dizzying to me.

Couldn't the type of Event just be an enum, and an attribute of an Event, rather than trying to drive the whole thing by subtyping?

Then it should be a relatively simple matter for a producer to work out which Listeners need to receive which Events, rather than machine-gunning them all. I suspect it could then be easily implemented with an EnumMap<EventType, List<EventListener>>, populated by a single addListener() method.

Confused of Scotland (alias: Winston).
 
Stevens Miller
Bartender
Posts: 1443
30
C++ Java Netbeans IDE Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:Can anyone tell me why Swing (or AWT...or Java, for that matter) doesn't have an EventProducer interface?


I've wondered that myself. I recently rolled my own little Publisher/Subscriber library, using enums, and it wasn't very hard. It allows grouping them, even, so one can unsubscribe from a whole group instead of from each individual event.

The only thing I can think of, as to the proliferation of types, is that it allows compile-time checking and, maybe (if you believe in such things) a degree of self-documentation. Those are just guesses. It's just as possible that we are trying to make sense of old code written by folks that didn't communicate with each other, or who thought this made sense at the time, and now we're just stuck with it.

I suppose one could put a wrapper around it (the Adapter pattern?), if one really felt strongly enough to do so.
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:The only thing I can think of, as to the proliferation of types, is that it allows compile-time checking and, maybe (if you believe in such things) a degree of self-documentation.

True. I hadn't thought about the documentation side of it. But if that's the case, they made a pig's ear of it, because there's no cross-reference from a Listener to a producer.

Another possibility of course is that it was all done before enums were part of the Java multiverse (although maybe not before 'Effective Java v1', which taught you how to "roll your own").

It would certainly be nice to have compile-time checking, but Swing's implementation does seem to me to be a bit of "OO gone mad", which makes me wonder if there isn't a pattern for it. And furthermore, the whole thing seems to have been designed specifically for Swing (or AWT), when in fact the Producer→Consumer (or Event→Listener) model is actually much broader than that.

Sheesh. I knew there was a reason I hate GUIs.

Winston
 
Stevens Miller
Bartender
Posts: 1443
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is kind of lengthy, but if you create the javadoc, it might be interesting to you. It's my implementation of an enum-based, general Publisher/Subscriber model.

First, the package-info.java file:



Next, the Publisher.java class:



And, finally, the exquisitely intricate Subscriber.java interface:



Whaddayathink?
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:Whaddayathink?

Ooof. A bit much for an evening after sevurial beers; but you get a cow for effort, and I'll look it over as soon as I can.

Cheers.

Winston
 
Stevens Miller
Bartender
Posts: 1443
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:Another possibility of course is that it was all done before enums were part of the Java multiverse

You may have cracked it. Java gained enums in 1.5. A random sampling of all those subinterfaces and implementations of EventListener indicate they were all pretty entrenched by then.

I've only been using Java since Java 6 came out, so maybe I'm overstating things, but it does seem to me that the language designers (and their close cousins, the library designers) have done a pretty good job of adding things to the language without costing much backwards compatibility. Alas, I find that, if I don't get a book written since the current version came out (whichever one that is at the time), I pretty much always end up "learning" something that's already obsolete (but typically only deprecated, not eliminated, though one shouldn't assume that means it's still safe to use, e.g. Thread.stop). An apropos example is Observable/Observer. Interestingly, those go back to 1.0, and everyone tends to tell me they are dead for all future purposes (partly/mostly because Observable is a class, and extending it cuts you off from extending other classes for the sake of something that hardly needs to implemented in a superclass, maybe reflecting an imperfect understanding of the whole Event/Listener paradigm by the Sun Gods at the time).

What that suggests is that your original question might now be posed as, "Can anyone tell me why Swing (or AWT...or Java, for that matter) doesn't have an EventProducer interface yet?"

If they were to add one, none of those existing classes/interfaces would break or become unavailable. The current library seems pretty well supplied with classes made obsolete by later, superior replacements (Vector/ArrayList, for example, unless you need the former's thread-safe behavior). Maybe they just don't see a pressing need to add a more generalized implementation? It's a good question, since all those classes can be baffling, or even somewhat intimidating (at least, they were for me when I was greenhorn). You think you'll never learn them all, until you eventually figure out that you don't need to learn them all, and they are really just for the sake of grouping sets of event types together in isolated, named spaces. I agree that enums are a better way. Here's hoping they come to the same conclusion someday, and provide the needed additions to the standard library.
 
Stevens Miller
Bartender
Posts: 1443
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
Stevens Miller wrote:Whaddayathink?

Ooof. A bit much for an evening after sevurial beers; but you get a cow for effort, and I'll look it over as soon as I can.


Heh. Thanks for the beef .

It's New Year's Day, so beer gets priority over my code. If you do feel like reading it, skip the Java and just generate the javadoc. If I'm on the right or wrong track, I think you'll know from that alone.
 
Campbell Ritchie
Sheriff
Posts: 53749
127
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:. . . Another possibility of course is that it was all done before enums were part of the Java multiverse . . .
Agree with Stevens. Swing came out in Java1.2 about 1997 and like many of the earlier versions it suffered (maybe: naughty suggestion follows) from being rushed out before enums generics etc were completed. In those days the easiest way to define such options was with constant ints. If you look at some classes e.g. BigDecimal you find some methods have been overloaded to take more modern programming with RoundingMode which uses enums. If you look in the Swing Package, you find there are a few enums. Obviously they never updated the methods to take such enums, maybe because people had already got used to using ints.

On the other had, Swing is probably on its way out, to be replaced by JavaFX; if we look in a JavaFX package you find it has two enums in. I don't know much about FavaFX but it might use ints less than Swing, and Swing won't be updated much.
 
Rob Spoor
Sheriff
Posts: 20893
81
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:Whaddayathink?

Apart from not using lazy loading using Map's new computeIfAbsent method, I would have used Map and Set instead of HashMap and HashSet in the subscriptions declaration.
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:On the other had, Swing is probably on its way out, to be replaced by JavaFX; if we look in a JavaFX package you find it has two enums in.

Wow. I just had a quick look at it, and it made sense immediately. And with a Group right at the top, too - not to mention an EventHandler<T extends Event> interface. What a slick little package. Have to get me some of that.

Is it included with the SDK, or do you have to plug it in?

Winston
 
Campbell Ritchie
Sheriff
Posts: 53749
127
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think you have to plug it in. I know precious little about JavaFX I am afraid.

You can get 50% off O'Reilly e‑books at the moment. They have a few about JavaFX, but some of those are in German.
 
Karthik Shiraly
Bartender
Posts: 1210
25
Android C++ Java Linux PHP Python
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
(Desktop applications cheerleader here glad to help out! we're a dying breed, you see)

Winston, JavaFX is built into the JRE since Java 7. It's in jre/lib/jfxrt.jar in Oracle JRE 7 (that's JavaFX v2.2) and in jre/lib/ext/jfxrt.jar in JRE8 (that's JavaFX v8).
But if you're using OpenJDK, unfortunately it's not built in; have to build it yourself or download openjfx.jar.

JavaFX 8 tutorials are good to start off.

Edit: Just noticed some of your links are to JavaFX 2. Since JavaFX API is still evolving, it's better to use JavaFX 8 javadocs

As for this discussion, I'm coming in a bit late, but if I understood right, the question is regarding the explosion of Event subtypes and event handler methods subtypes in Swing.
If that's so, I'm afraid JavaFX programming model does not improve much upon it. It too has a fairly deep Event hierarchy
and adding handlers involves calling one of the many Node.set<event>Handlers.
 
Karthik Shiraly
Bartender
Posts: 1210
25
Android C++ Java Linux PHP Python
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Perhaps Node.addEventHandler() gets you close, though I've never felt the need to use it. EventType is not an enum but you can write code like mynode.addEventHandler(ActionEvent.ANY, myCommonHandler).
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Karthik Shiraly wrote:JavaFX 8 tutorials are good to start off.
Edit: Just noticed some of your links are to JavaFX 2. Since JavaFX API is still evolving, it's better to use JavaFX 8 javadocs

Thanks for that Karthik.

As for this discussion, I'm coming in a bit late, but if I understood right, the question is regarding the explosion of Event subtypes and event handler methods subtypes in Swing.

Yes. My specific point was about the link between event producers and Listeners, and that there seem to be a million different methods for registering Listeners with producers, presumably to ensure compile-time type checking. There also doesn't appear to be any EventProducer superclass (or interface) - presumably for the same reason.

It's sort of understandable if the framework was created in 1.2, because the designers didn't yet have any goodies like generics or enums to call on, but I can't help feeling that there was a pattern out there that could have been used, even if it was just to overload a single registration method for different Listener subtypes.

If that's so, I'm afraid JavaFX programming model does not improve much upon it. It too has a fairly deep Event hierarchy and adding handlers involves calling one of the many Node.set<event>Handlers.

Pity. I wonder if functional interfaces and lambdas might help? I'm still getting my head around them, so I'm not sure; but it seems possible.

But thanks for all the useful information. Very interesting.

Winston
 
Campbell Ritchie
Sheriff
Posts: 53749
127
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
EventHandler appears to be a functional interface. So you can use it in a λ.
 
Piet Souris
Rancher
Posts: 1783
55
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I do not quite understand what the problem is.
Indeed, depending on the component, you might need
to choose what specific xxxListener to add.
But in practice, there aren't that many.
A button, menu? addActionListener
Panel, Label? addMouse(Motion)Listener
Sliders and comboboxes? addChangeListener

There are umpteen other Listeners as well, but my
experience is that the components for which you need
to add some specialist Listeners are already so complex,
that the Listener is only a tiny portion of the problem.

As Karthik says, in JavaFX you can indeed use 'addEventHandler'
in the way you described a long time ago in your opening post,
but you still need to know what kind of Event you need to have,
and add code that can handle the Event you're interested in.

All I can advise is: if you really want to get into all sorts of GUI,
whether FX or Swing or whatever, just start and practise.
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Let me state my analysis of the problem, and see if it generates any ideas (or ridicule ). Some these points may not be directly related to the discussion so far.

  • A Swing screen is made up of Components that may need to react to certain Events.
  • A Component can contain other Components.
  • The machine on which the screen is displayed has devices that can initiate a reaction (mouse, keyboard, touchpoint etc) - let's call these "action" Events.
  • Reaction may involve translating events understood by one component into other events understood by (and targeted at) others - let's call these "command" Events.
  • There may also be other Events generated periodically by the machine or the Swing app itself (eg, a clock "tick") - let's call these "timer" Events.
  • A single Event may meed to be "multicast" - ie, blasted to a bunch of components at once - a 'selection rectangle' springs to mind.
  • Thus, a Component may need to be both a Producer of, and a Listener for, many types of Event.

  • Does this seem like a reasonable outline of the problem?

    Now we come to the crux:
  • Events may vary wildly in the sort of information they transmit, so it's important:
    (a) That a Listener receive only the types of Event it's listening for.
    (b) That this type-checking is enforced at compile time.

  • Basically, there has to be a 1:1 relationship between a Producer and a Listener, and there just doesn't seem to be a simple way of doing that at compile time without a large matrix of Producer and Listener types, because there's no simple way to say "I'm a Producer (or Listener) for <all these types> of Event" declaratively.


    I can think of one possible solution, but it involves breaking encapsulation:

    1. Say an EventProducer looks like this:2. And a EventListener looks like this:3. Any Component that wants to generate Events declares itself to be an EventGenerator, which is simply a marker interface that indicates it contains one or more public EventProducers.
    4. A Component that wishes to "listen" for an Event creates an object of a nested or inner (or anonymous) class that implements Listener<T>, where T is the type of Event it wants to listen for, and registers it with the public EventProducer in the "generating" Component.

    Obviously, if the EventGenerator doesn't contain an EventProducer member of the right type - which should be clear from the documentation - it can't be done.

    In Stevens' words: Whaddayathink?

    Winston
     
    Winston Gutkowski
    Bartender
    Posts: 10573
    65
    Eclipse IDE Hibernate Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:EventHandler appears to be a functional interface. So you can use it in a λ.

    Dang! So all my last post was for nothing.

    I wonder when Swing8 (or FX8) will come out?

    Winston
     
    Winston Gutkowski
    Bartender
    Posts: 10573
    65
    Eclipse IDE Hibernate Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Piet Souris wrote:I do not quite understand what the problem is. Indeed, depending on the component, you might need to choose what specific xxxListener to add.

    And that's my point. Not only do there seem to be a pile of methods, but some of them don't even adhere to the xxxListener rule.

    I think we've worked out that there probably wasn't another alternative at the time though.

    There are umpteen other Listeners as well, but my experience is that the components for which you need to add some specialist Listeners are already so complex, that the Listener is only a tiny portion of the problem.

    You may be right. Drag and drop - not to mention group selection - seem to be real mind-benders.

    As Karthik says, in JavaFX you can indeed use 'addEventHandler' in the way you described a long time ago in your opening post, but you still need to know what kind of Event you need to have, and add code that can handle the Event you're interested in.

    Yes, but I shouldn't have to remember a pile of different method names depending on it - especially since generics were introduced. See what you think about my solution above - although it looks like it may already be redundant.

    All I can advise is: if you really want to get into all sorts of GUI, whether FX or Swing or whatever, just start and practise.

    Unlikely to happen - although I have to admit that FX intrigues me. I just hate GUIs. Always have, always will; and I'm happy to leave the coding of 'em to the gamer/smartphone generation. Webpages too, come to that.

    This was more of an intellectual exercise than anything: Swing's implementation of the Producer→Consumer problem as applied to Events.

    Otherwise leave me in my back room with my Marvel comics and let me supply the information that all these GUIs and smartphones and websites need.

    But thanks for your comments. Pithy as usual.

    Happy New Year everyone.

    Winston
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!