One of the design patterns which I find most difficult to get a real grasp of in "real SWING life" is the MVC pattern. I've been through quite a few of the posts at this site which discuss the pattern, but I still do not feel that i have a clear understanding of how to take advantage of the pattern in my (Java SWING) application.
Let's say that I have a JFrame which contains a table, a couple of text fields and a few buttons. I would probably use a TableModel to "bridge" the JTable with an underlying data model. However, all functions responsible for clearing fields, validating fields, locking fields along with button actions would usually go directly in the JFrame. However, doesn't that mix the Controller and View of the pattern?
As far as I can see, I manage to get the MVC pattern "correctly" implemented when looking at the JTable (and the model), but things get muddy when I look at the entire JFrame as a whole.
I'd really like to hear how others go about with regard to this. How do you go about when you need to display a table, a couple of fields and some buttons to a user (using the MVC pattern)?
A book i'd highly recommend to you for MVC in swing would be Head First Design Patterns by Freeman and Freeman. They have a highly comprehensive explanation of MVC.
- You’re the user — you interact with the view. The controller takes your actions and interprets them. If you click on a button, it’s the controller’s job to figure out what that means and how the model should be manipulated based on that action.
- The controller asks the model to change its state. When the controller receives an action from the view, it may need to tell the view to change as a result. For example, the controller could enable or disable certain buttons or menu items in the interface.
- The controller may also ask the view to change. When something changes in the model, based either on some action you took (like clicking a button) or some other internal change (like the next song in the playlist has started), the model notifies the view that its state has changed.
- The model notifies the view when its state has changed. When something changes in the model, based either on some action you took (like clicking a button) or some other internal change (like the next song in the playlist has started), the model notifies the view that its state has changed.
- The view asks the model for state. The view gets the state it displays directly from the model. For instance, when the model notifies the view that a new song has started playing, the view requests the song name from the model and displays it. The view might also ask the model for state as the result of the controller requesting some change in the view.
Source (In case you're wondering what a "creamy controller" is, think of an Oreo cookie, with the controller being the creamy center, the view being the top biscuit and the model being the bottom biscuit.)
Um, in case you're interested, you could download a fairly entertaining song about the MVC pattern from here!
One issue you may face with Swing programming involves amalgamating the SwingWorker and EventDispatch thread with the MVC pattern. Depending on your program, your view or controller might have to extend the SwingWorker and override the
doInBackground() method where resource intensive logic is placed. This can be easily fused with the typical MVC pattern, and is typical of Swing applications.
Additionally, it is important to consider MVC as a sort of composite of various patterns. For example, your model could be implemented using the Observer pattern (requiring the View to be registered as an observer to the model) while your controller might use the Strategy pattern.
I would additionally like to answer specifically your question. You should display your table buttons, etc in the View, which would obviously implement an ActionListener. In your
actionPerformed() method, you detect the event and send it to a related method in the controller (remember- the view holds a reference to the controller). So when a button is clicked, the event is detected by the view, sent to the controller's method, the controller might directly ask the view to disable the button or something. Next, the controller will interact with and modify the model (which will mostly have getter and setter methods, and some other ones to register and notify observers and so on). As soon as the model is modified, it will call an update on registered observers (this will be the view in your case). Hence, the view will now update itself.