Inter-Component communication in Swing

What is the preferred method of communicating across JFrames (or JPanels and JDialogs, for that matter) in Swing?

For example, if I have two frames, and one has a few buttons that need to initiate actions in the other frame, what's the preferred way of sending the target frame a message?

I could create both frames as Singletons and simply create a new reference every time I needed to send a message, but something about that doesn't seem quite right.

I've also thought about creating a singleton AppRegistry class that each frame would "register" itself to, allowing lookups in the registry when a reference to a frame was needed.

Each of the above ways would do it, but I'd like to hear that the "best practice" approach might be.

Also, what aboout components in the same frame or dialog? Say I have a JFrame that contains three JPanels for layout's sake. The first panel contains a form consisting of JTextFields, the second panel contains a scroll pane with an embedded JTable, and the third panel contains Save and Cancel buttons.

Am I missing something very obvious, or is there no good way to communicate between these panels or between an individual panel and the outermost container (JFrame)? If I hit the Cancel button and want to call dispose on the JFrame, how would I do that without using a registry (as described above) or a singleton? What about if I hit the Save button and want to get access to the various form fields in the first panel or a row from the JTable in the second?

It makes sense that you're not able to communicate easily between JFrames, but it would seem there might be a short cut if the components that wish to communicate were in the same frame or dialog.

Originally posted by John Wells: What is the preferred method of communicating across JFrames (or JPanels and JDialogs, for that matter) in Swing?

Swing is based on the model-view-controllerpattern, and I tend to use this pattern when designing GUI apps. You have already specified a view, a couple of frames. I'd see the model as broken up into a few classes, one for the JTable model, one for the editor model and one (if necessary) for the group of buttons. The controller is really what you are grasping around in the dark for. A single class who's responsability it is for coordinating the functions of all the frames. This class listens for events occurring on the frames (possibly custom events which serve to streamline event handling) and fires events or invokes methods on interested parties. One should use interfaces to separate the implementation of the controller from the implementation of the frames' model and controller classes. If I were you, I'd be careful when using separate frames for parts of an application. They are very easy for the user to misplace, minimize, cover with other apps and so on. I'd either use dialogs to edit/add new elements and put the rest of the functionality in a single frame or look into using a Multiple Document Interface with JInternalFrames

I understand the basics of MVC very well, but am still not following how this can be effectively used to communicate between panels.

Say, for example, a button on one panel with an actionlistener that does a few calculations and then disables a textbox on another panel based on the result of that calculation.

How can a controller intervene and disable the textbox in response to those calculations? I (naively?) assume the JPanel containing the button would need a reference to the controller and would call some method on the controller, which would itself call another method on the JPanel containing the textbox to disable it. If the controller simply listened for actionevents from the button, it would have no way of knowing the calculation result.

Whew...I think I'm totally off target there. Could you perhaps provide an example that would better illustrate your suggestion?

Originally posted by John Wells: I (naively?) assume the JPanel containing the button would need a reference to the controller and would call some method on the controller. . . .

You need a reference in order to invoke a method (unless you use static methods, of course). What I suggest is not having a reference to the controller class, but a listener interface that the controller implements. This isolates the classes from being dependent on each other.

If the controller simply listened for actionevents from the button, it would have no way of knowing the calculation result.

Correct. Part of my suggestion is to have the calculator resolve the action event, then use a custom event to inform the controller. Conversely to the above isolation, having a custom event insures that any class which registers as a listener to the calculator panel will know how to handle the event (as opposed to the more common ActionEvent). An example gets real complex real quick because we aren't talking basic Swing here. We are trying to create easily maintained code by making independent software components (each possibly consisting of many UI classes, models and controllers) and using a controller class to coordinate them. I knew we'd discussed this before:Swing Interapp Communication [ December 20, 2004: Message edited by: Joe Ess ]

John Wells
Greenhorn

Joined: Apr 10, 2003
Posts: 7

posted Dec 21, 2004 06:43:00

0

Joe,

Thanks for the reply. That approach is valid, but I don't like the fact that you have to essentially subclass any components you'd like to be associated with the Controller.

I'm looking for a less intrusive solution. I found Werx's ReflectionBus, which looks perfect, but it's currently lacking any documentation whatsoever.