views:

916

answers:

1

I want to use MVC to structure my Swing application, but there seems to be a conflict.

As I understand MVC, the controller should handle input and update the model. The model should notify its observers of which the view is one.

I have two problems

  • Swing is all part of the view. The fact that components have their own models is an implementation detail. I want to keep the swing-specific code out of the controller/model don't I?
  • My controller needs to receive user-triggered events, but these come from the swing component which is in the view, and the controller shouldn't know about the view.

I'm sure this problem has been solved many times before, but I can't find a real world example of an MVC based swing app of a decent size.

Update - A problem I forgot

What MVC doesn't directly cater for is the structure of the various MVC components within the hierarchy of the application. For example, the main display may have "sales" and "purchasing" tabs, each of which might have "new" and "query" panels. On top of that, there may be an "amend selected" button which would create (possibly multiple) windows on request.

Something has to create a model,view and controller for these sub-components on request. It can't be the controller since the controller or model since they don't know which view to create and it shouldn't be the view since it's application logic and it's responding to an event (which is the controller's job).

Is there an answer?

+1  A: 

Swing components like JButton etc are the controller. The view classes are JButtonUI etc.

As for separating the event processing logic from your "view" code, the simplest thing is to inject a specific Controller class into all of your panels. That way, event handling can just look like:

doStuffButton.addActionListener( new ActionListener() {
    public void actionPerformed(ActionEvent e) {
       controller.doStuff(); // logic in controller
    }
});

Your panel classes can offer up Models to your controller, so for example:

public void doStuff() {
    MyData data = ...
    dataModel.setData(data)
}

That way the controller is aware of the model, and the view is aware of the controller but the controller is unaware of the view (implementation)

oxbow_lakes
a) Only as far as Swing is concerned - ie at the component level. I'm talking about using an MVC architecture for my application.b) Actually swing isn't strictly MVC - the component is the controller AND the view, and it uses a UIDelegate.
Draemon
This is true but as far as a) is concerned, I'm confused. You ask about structuring a Swing application
oxbow_lakes
I merely meant that the JButton class doesn't have all of the painting logic in (which I would consider to be the view)
oxbow_lakes
Your update is fine, but that means adding a lot of controller.doStuff() methods. I seem to remember trying this and running into problems, but I can't think what now. I'll have another go and see.
Draemon
for a) I was referring to the difference between using MVC as a design pattern at the component level (which swing roughly does) and using MVC as an architectural pattern at the application level. I think that swing's MVC is all part of the application's V.
Draemon
I know what you mean about trying to relate Swing's MVC to what you might do in any given app. I tend to be less restrictive about separating out the Model from the view. That is, my view class might have a `setData` method on it, but this is not necessarily extracted into an interface `DataModel`. Which is naughty of me. However, I definitely haven't found any issues in 10+ years of writing Swing applications with deferrring all logic to a `Controller` class
oxbow_lakes
I should say that I never expose view components (like individual `JButtons`, `JTextFields` etc) out of my view classes.
oxbow_lakes
Thanks. I'll give it another shot.
Draemon