6

I'm building my first Swing app and am trying to figure out how my JDialogs - exclusively invoked when the user selects a JMenuItem - can update the components in the main client area of the JFrame which is the parent "window" of the whole app.

This is the design I've come up with, but don't know if its: (1) just plain bad, (2) not the standard (thus best) way, or (3) if I'm totally off-base here. Any suggestions are enormously appreciated.

Basically, the user selects a JMenuItem, which launches a JDialog. The user interacts with the components on the dialog, and then clicks "Done". If everything validates, the JDialog closes, and I want the parent window (a JFrame) to have its state updated (and eventually rippled out into its components).

My design:

Have an AppStateController that is a member of the JFrame subclass (my application). I would then create an AppStateChangeListener and AppStateChange EventObject subclass so that whenever a dialog validates and closes, it fires an AppStateChange event. Since the parent JFrame is the only registered listener to that event, I could define a handler that gets the event passed to it. I would make sure the AppStateChangeEvent had enough metadata to describe all the possible changes.

In theory, I like this approach: it should be clean and free of "spaghetti"-type calls to multiple controls every time a different event fires. However, I fear it may be overkill.

What do best practices dictate here? I'm not really a GUI person!

IAmYourFaja
  • 55,468
  • 181
  • 466
  • 756
  • good question, I had this kind of deal, I figured out I was wasting to much time with thatt. The point is, do you really plan/need on re-using that dialog? – fredcrs Aug 16 '11 at 18:38

1 Answers1

5

Java has several ways to implement the observer pattern; several are discussed here.

The mechanism prescribed by EventListenerList is probably the most general, as it would allow you to define your own event and listener types, and it is familiar to Swing programmers. Instead of making the JFrame a listener, let the highest level JComponent do so. Each instance of JComponent has a suitable protected member, listenerList.

Bound Properties are also an excellent choice, as shown here.

If you go with Observable, you'll need to use a delegate.

Addendum: As concrete examples, uses the EventListenerList scheme to manage chart, dataset and series events. In contrast, uses bean properties to notify listeners of widget selections.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Awesome response @trashgod! Thank you! However, this EventListenerList has me confused: If I set my highest-level JComponent as the only listener, and that JComponent belongs to my JFrame, then how do my dialogs obtain the EventListenerList so that they can call the `fireFooXXX(...)` method(s)? Do I cache this list, or just call `myHighJComponent.fireFooXXX(...)`? – IAmYourFaja Aug 16 '11 at 19:06
  • Adding the listener to the highest level `JComponent` comports with your proposed design, but _any_ `JComponent` in your application can listen for an `AppStateChangeEvent`. Each such component must implement the relevant `fireAppStateChange()` method, and you'd pass the component to the dialog. [`fireActionPerformed()`](http://download.oracle.com/javase/6/docs/api/javax/swing/AbstractButton.html#fireActionPerformed%28java.awt.event.ActionEvent%29) in `AbstractButton` is a good example. – trashgod Aug 16 '11 at 19:24