The MVC Pattern and Swing

The MVC pattern and Swing

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.

Brief Summary

  1. You're the user--you interact with the view. The view is your window to the model. When you do something to the view (like click the
    Play button) then the view tells the controller what you did. It's the
    controller's job to handle that.

  2. The controller asks the model to change its state. 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.

  3. The controller may also ask the view to change. 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.

  4. 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.

  5. 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.

Sample Image
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.

EDIT #1:

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.

EDIT #2:

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.

How MVC work with java swing GUI

This is a difficult subject to grasp in something like Swing, which already uses a form of MVC, albeit more like VC-M, where the model is separated from the view and controller, but where the view and controller are combined.

Think about a JButton, you don't supply a controller to manage how it's triggered when a user presses a key or clicks on it with the mouse, this is done internally and you are notified about the actions when the occur.

With this in mind, you need to allow the view to be semi self managed. For instance, based on your requirements, the view would have a button and text field.

The view itself would manage the interactions between the user and the button itself (maintain a internal ActionListener for example), but would then provide notifications to the controller about any state changes that the controller might be interested in.

In a more pure sense of a MVC, the view and model won't know anything about each other and the controller would manage them. This is a little contradictive to how Swing works, as Swing allows you to pass the model directly to the view, see just about any Swing component.

This doesn't mean that you can't make things work, but you need to know where the concept can falter or needs to be "massaged" to work better.

Normally, when I approach these type of things, I take step back and look at much wider picture, for example.

  • You have a view which can accept text and produce text or changes to it
  • You have a model which can load and modify text, but provides little other events
  • You have a controller which wants to get text from the model and supply it to the view and monitor for changes to the text by the view and update them within the model

Now, MVC works REALLY well with the concept of "code to interfaces (not implementation)", to that extent, I tend to start with the contracts...

View contract...

public interface TextView {

public void setText(String text);
public String getText();
public void addTextViewObserver(TextViewObserver observer);
public void removeTextViewObserver(TextViewObserver observer);

}

public interface TextViewObserver {
public void textWasChanged(TextView view);
}

Now, one of the requirements of the view is to generate events when the text has changed in some meaningful way, to this end, I've used a simple observer pattern to implement. Now you could argue that the controller is the observer, but to my mind, the controller may have functionality that I don't want to expose to the view (like the model for instance)

Model contract...

Next comes the model...

public interface TextModel {
public String getText();
public void setText(String text);
}

pretty simple really. Now, you might consider adding some kind of Exception to these methods to allow the model the ability to fail for some reason, but the Exception should be as generic as you can make it (or even a custom Exception), so that you can replace the implementation should you need to

Controller contract...

And finally, the controller...

public interface TextViewController {

public TextView getTextView();
public TextModel getTextModel();

}

again, pretty simple. You might have a more complex requirement for your controller, but for this example, this is about all we really need.

Implementations...

View...

public class TextViewPane extends JPanel implements TextView {

private JTextField textField;
private JButton updateButton;
private List<TextViewObserver> observers;

public TextViewPane() {
observers = new ArrayList<>(25);
textField = new JTextField(25);
updateButton = new JButton("Update");
updateButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fireTextWasChanged();
}
});

setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(textField, gbc);
add(updateButton, gbc);
}

@Override
public void setText(String text) {
textField.setText(text);
}

@Override
public String getText() {
return textField.getText();
}

@Override
public void addTextViewObserver(TextViewObserver observer) {
observers.add(observer);
}

@Override
public void removeTextViewObserver(TextViewObserver observer) {
observers.remove(observer);
}

protected void fireTextWasChanged() {
for (TextViewObserver observer : observers) {
observer.textWasChanged(this);
}
}

}

Model...

public class SimpleTextModel implements TextModel {

private String text = "This is some text";

@Override
public String getText() {
return text;
}

@Override
public void setText(String text) {
this.text = text;
}

}

Controller...

public class SimpleTextController implements TextViewController, TextViewObserver {

private TextView view;
private TextModel model;

public SimpleTextController(TextView view, TextModel model) {
this.view = Objects.requireNonNull(view, "TextView can not null");
this.model = Objects.requireNonNull(model, "TextModel can not be null");
view.addTextViewObserver(this);
}

@Override
public TextView getTextView() {
return view;
}

@Override
public TextModel getTextModel() {
return model;
}

@Override
public void textWasChanged(TextView view) {
getTextModel().setText(view.getText());
}
}

Putting it together...

TextViewPane view = new TextViewPane();
TextModel model = new SimpleTextModel();
TextViewController controller = new SimpleTextController(view, model);

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(view);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);

Now, all this is just an example of one possible solution. You could have a controller implementation which has a particular implementation of the model or view or both, for example.

The point is, you just shouldn't care. The controller doesn't care how the view is implemented, it only cares that it will generate textWasChanged events. The model doesn't care about the view at all (and visa-versa) and the controller doesn't care about model, only that it will get and set some text.

For a more complex example, you can have a look at Java and GUI - Where do ActionListeners belong according to MVC pattern?

After thoughts

  • This is just ONE possible way to approach the problem. For example, you could limit the view to a single observer.
  • You should always be thinking "can I change any one part of the MVC and will it still work?" This makes you think about the possible issues that changing any one part of the implementation might have on the surrounding contracts. You should get to the point that it simply doesn't matter how each layer is implemented
  • A view may act as a controller for another sub-view (or act as a container for another controller of a sub-view). This can scare people sometimes, but it's possible for a view to act as parent container for one or more sub controllers/views, this allows you to develop complex UIs
  • Don't expose implementation details in your contracts, for example, the model shouldn't throw a SQLException, as another implementation might not be based on a SQL based solution. Don't expose UI elements, this means that ALL implementations would then need to implement those elements. What happens if I want a implementation of the view that presents a JComboBox to the user instead of JTextField? This is also the reason I don't use a ActionListener in the view contract, because I have no idea how a textWasChanged event might actually be generated by an implementation of the view

Correctly implementing the MVC pattern in GUI development using Swing in Java

Maybe I am misunderstanding, and everything should be done differently in different languages?

There is no misunderstanding; the pattern is merely applied differently.

As noted in a comment by @ordous and this this answer by @udalmik, a Swing application may have multiple implementations of the MVC pattern. As noted here and here, "not every interaction needs to pass through your application's controller." In contrast, a web application may well "have a 1:1 relation between views and controllers."

The Swing separable model architecture, cited here, "collapses the view and controller parts of each component into a single UI (user-interface) object." Swing controllers are scattered among the descendants of JComponent, typically in the component's UI delegate. As a concrete example, BasicButtonUI contains a BasicButtonListener that handles user mouse interaction.

Almost used the answer in the link, but the fact that his controller extends JPanel ruined it, totally confused me there.

This can be confusing, as a simple Swing program may have no explicit controller at all. As suggested in this outline, the controller has direct access to any relevant view and model; it may also listen to user interaction with the view. The example was intended to illustrate the simplest such interaction. It is mere coincidence that the effect is evoked by user interaction with a view component. The simulation cited here, for example, has a ControlPanel of view components that update the application's view and model. The DisplayPanel listens directly for a ComponentEvent that requires a model update. Etc.

Your application's controller is then free to focus on the application's needs.

@Marco13 elaborates on this and cites additional examples in this related answer.

Java Swing + MVC pattern in a modular way

The Model, View, Controller pattern allows us to separate business logic, screen rendering and handling asynchronous events into discrete classes. The benefit of this is that it effectively decouples all the fundamental responsibilities of a GUI-driven application into dedicated classes. This means that the functionality of each class is isolated, which better accommodates application-specific customization and maintainability.

So, with this fundamental approach, the application's overall architecture for your application is good so far, however what your boss is looking for is slightly different. He's asking for the implementation of some architecture which will allow you to rapidly and simply modify the UI. So, immediately, you can tell what he's asking for is with respect to the View element of the MVC.

Below I use pseudo-code to provide a generic example of how you could create these modular graphical elements.

public final class View {

private GUIElement mModularElement;

public final void setModularElement(final GUIElement pModularElement) {
this.mModularElement = pModularElement;
}

public final GUIElement getModularElement() {
return this.mModularElement;
}

public final void onRender(final GUIVariable pGUIVariable) {
this.getModularElement().draw(pGUIVariable);
}

}

In this code, we've defined the View of the application access to an instance of something called ModularElement, of type GUIElement. By using public getter/setter methods, the Controller can get the View to render any type of Object that inherits from GUIElement. So, if you ever wanted to change the GUI, you could specify a new kind of GUIElement without making changes to the surrounding architecture.

This is a basic example, because other kinds of responsibilities, not just rendering, would need to be handled by the GUIElement to maximize flexibility. These would include defining the screen layout, encapsulation of further graphical elements, how they handle MotionEvents, all lie within extending the functionality of GUIElement. You could even draw an array of GUIElements. Importantly, mModularElement would exist within your Model to adhere to the MVC pattern; the implementation above avoids this in the interest of simplicity.

Hope this helps.

java swing vs mvc: is this pattern indeed possible?

When I have build larger applications (person years of development), we often abstract the MVC architecture above the individual components to a top level controller/model and view, and accept that the individual components will be their own personalized MVC. GeoffreyZheng is absolutely correct in his assessment, and it is something I have actually loved about developing with the Swing environment. That being said, if you want true MVC, you will probably need to abstract away from individual components and talk about a view in a more abstract terminology.

Comparing Java swing MVC with Android design pattern

Each Swing JComponent has ComponentUI that is responsible for displaying a component. While JComponent has a paint method, only user derived classes use it directly - "standard" implementations very often just call the paint method of the attached UI instead. This allows to plug-in various look and feel implementations very easily - a different look and feel just provides different ComponentUI's. Very clearly component is the "model" and the UI is the "view". And Android does not inherit this decoupling in very obvious way. For instance, its TextView seems just painting drawables when a similar JLabel has UI.

This is however not the only place where MVC approach is used, and for some other specific cases Android and Swing MVC are very similar. For instance, Android ListView has a model (ListAdapter) very much like Swing JList has ListModel. In both cases the model provides data while the component itself provides possibilities to display. The possible difference is that Swing has more components with such decoupled data and presentation. JTable and JTree have similar models when Android does not provide such components out of box. There is no tree at all, and TableLayout is a that is called GridLayout in Swing, not similar to JTable.

The general approach for invalidating and repainting is not much different and in both frameworks only dedicated master thread can touch components. Also, event listeners (probably other group of "controllers") are very similar in Java and Android, all differences between them could probably be called "subtle" only.

Containers and layout manages are also quite similar between Swing and Android, the main differences being that Swing has much more possible implementations of its LayoutManager to choose from than Androids ViewGroup (classes like DatePicker, while derived from ViewGroup, are not general purpose layout managers). Also, part of Android layout is encoded in XML while Swing is typically plain Java only. If layout managers are also kind of "controllers" responding to events like resizing or reorientation, this part is very similarly done. However I am not sure if layout managers are really "controllers" as they update more the view than the model.

In general, Swing seems more optimized for the large, complex GUI that shows up on a large screen when Android is better suited for small screens with just a few visible components, large enough to be operated with fingers without stylus.

MVC pattern with java Swing

A change I would make maybe would be to do all database related operations within the model, that is, even managing my own database connections. This will allow the Controller class to be completely independent from the where and the how you get the data.

All that the Controller needs to know is that it needs to call the Model to get whatever information it needs to eventually pass on to the View.

As an extra note as well, it is usually a good idea to implement an extra layer between the Controller and the Model, known as a Service layer. This usually comes in handy when you also need to expose certain similar functionality through other means, such as REST. This will allow you to write all your queries in the Model layer, then, any extra customization will be done within the Service layer. This will allow the Controller and REST API to deliver the same functionality without either cluttering the Model layer or else have duplicate code in the Controller and REST API.

Populate Jlist with data in Swing using the MVC Pattern correctly

I don't know how to pass the data to the View without breaking the MVC model; this is storing/creating data on the View.

You could make the "controller" a ListModel, you could then have it proxy the data from the underlying model, either as another ListModel or via the information the original model is providing.

To my mind, this is overkill and wasting a lot of you time.

Swing already implements MVC, all bit more like MV-C, trying to wrap another (pure) MVC on top of it is always going to present issues.

Instead, the model should provide some data, either as an array or List, which can past to the view for it to present, in what ever way the view decides is best.

In this case, the view isn't "creating data", because that data is provided by the controller via the model.

No matter what you do, you will find the view has to maintain a reference to the data at some level, for example, a JTextField will store data in the form of String - it has to, it can't work without doing so.

This is just my opinion, but I've fought these issues before. Focus on the requirements of the data, focus on how you might communicate with the model, controller and view in a way which decouples each layer from the other (i.e. don't expose UI elements to the controller, it doesn't care "how" it's managed, only that the view promises to provide some information).

This way you can change the implementation of the model, view and/or controller and none of the others should care, it should continue to work

building swing gui using mvc pattern with observer pattern

An implementation of MVC explained along with how an observer pattern might work:

Up-to-date Swing MVC example + Question

Some guidelines to follow while using Swing:

GUI guidelines for swing



Related Topics



Leave a reply



Submit