Concepts / The Model-View-Controller Pattern in Swing

The Model-View-Controller Pattern in Swing

A JList gets its items from a list model, the object that knows the actual list of items and the operations that can be performed on it.

  • Programming

Starting With a Changing Flavor List

Swing's list component, JList, shows a set of items in a window. Many programs need that list to change while they run: a new item appears, or an old one disappears. This article uses a small flavor-list program to explain how that change happens. The program builds a list of ice cream flavors, creates a JList to display them, and then adds one more flavor to the model. The question the rest of the article answers is simple: when the list changes on screen, what exactly was changed in the program? The answer is not the JList itself. It is a separate object, and understanding that separation is the key to debugging most list problems in Swing.

What do you think happens?

The flavor program adds a new flavor and the JList shows it. Which object did the program change to make that happen: the JList, or something else?

  • The JList itself, by inserting the flavor into its display

  • A separate object that holds the list of items, which the JList is connected to

Reveal answer
Answer:

The program changed a separate object that holds the list of items, not the JList. That object is the list model, and the JList displays what the model contains.

The source states that the JList is the view, while the data itself is held by a third part called the model. The programmer changes the model, and the JList redraws to match it. Keep this answer in mind as you read the rest of the article.

Three Cooperating Parts of a JList

A JList is best understood as having several cooperating parts rather than one. The list that appears in the window is only the view. Listener objects act as the controller: they respond when the user clicks an item. The data itself is held by a third part, the model. The source names this object a ListModel, and it is the object that actually knows the list of items. The model is the object that knows the actual list of items and the operations that can be performed on it.

Flavor programmakes the changeDefaultListModelholds the itemsJListview that draws itemsVisible listwhat the user seeschanges dataannounces changeredraws items
Which object holds the actual items, which object draws them, and how does data move between them? The program changes the model, and the view receives the change and redraws.

Keeping these parts separate explains a lot. The model holds the data, the view draws it, and listeners respond to user actions. When you want the screen to show something different, your task is to change the model. You do not reach into the drawn list and edit it directly.

What a List Model Knows and Can Do

Definition

A list model is the object that holds the actual items of a JList together with the operations that can be performed on those items.

The source gives a useful way to think about the model. A model is defined not only by the data it contains but also by the set of operations that can be performed on that data. When you choose a model, you are choosing two things at once: what it holds, and what you are allowed to do with it. This is why two lists that display the same items can behave very differently. Their models offer different operations.

Two Kinds of List Model

Swing offers more than one kind of list model, and the difference matters as soon as a list needs to change. The two kinds are compared below, and each is described in its own subsection.

Keeping a Reference to the Model

The flavor program holds the DefaultListModel in a variable that is kept for the life of the program, rather than only inside the constructor call. The source explains why this matters. Because you keep a reference to the model, you can add and delete flavors while the program is running by calling methods on that model object. If the model were created and passed to the JList without being stored anywhere, the program would have no way to reach it later.

java
Notes on the code
  • The model is created and stored in a variable that stays in scope.
  • The JList is given the model so it knows where to get its items.
  • The later addElement call changes the model, not the JList.
Worked example

Adding a Flavor While the Program Runs

The flavor list shows Vanilla and Chocolate. The program must show Mint as well, without rebuilding the JList.

  1. 1
    Identify the object to change

    The items live in the DefaultListModel, so the change goes to that object, not to the JList.

  2. 2
    Call the add method on the model

    Calling addElement with Mint adds the item to the model's data.

  3. 3
    Leave the JList alone

    No separate call to the JList is needed. The JList is registered to hear about changes in its model.

Result

The model now holds Vanilla, Chocolate, and Mint, and the visible list is updated to show all three.

Tracing a Change to the Screen

The automatic update is driven by an event. When a list model is modified, it generates an event of type ListDataEvent. The JList registers itself with its model as a listener for these events. When an event arrives, the JList responds by redrawing itself to reflect the new contents of the model. The diagram below traces the steps in order, with each arrow showing which object notifies which.

Flavor programcalls addElementDefaultListModelstores the new itemJListregistered listenerScreenshows the new item1. addElement(Mint)2. ListDataEvent3. redraws itself
After addElement is called on a DefaultListModel, what happens step by step before the new item appears on screen, and which object notifies which?
Key point

The programmer's only responsibility is the change to the model. No separate step is needed to repaint the list.

Locating an Unexpected Result

Most list bugs come from a broken link somewhere in the chain of model, event, and view. When the visible list does not match what you expected, work backward through that chain and ask at which step the result diverged. The three places to check are the model contents, the notification, and the view's rendering. The flowchart below turns that check into a sequence of questions.

Wrong items shownModel holds correctitems?Fix the change madeto the modelCheck the listenerregistrationChange event fired?Check view renderingnoyesnoyes
If the JList shows the wrong items, at which point in the model-to-view path should you check: the model contents, the notification, or the view's rendering?

Mistakes Beginners Make With List Models

  • Common mistake

    Trying to add items to a list built directly from an array

    Why it fails

    The model Swing creates from an array can report its items but cannot add or delete them.

    Do this instead

    Use a DefaultListModel when the list must change.

  • Common mistake

    Calling a method on the JList to add an item

    Why it fails

    The add and remove operations act on the model, which holds the data the JList displays.

    Do this instead

    Call addElement or the matching removal method on the model object.

  • Common mistake

    Creating the model inside the constructor call and never storing it

    Why it fails

    Without a stored reference, the program has no way to call methods on the model while it runs.

    Do this instead

    Store the DefaultListModel in a variable that lives for the life of the program.

  • Common mistake

    Assuming the model type from the fact that the object is a JList

    Why it fails

    The methods you can call depend on the actual class of the model, and a model built from an array is not a DefaultListModel.

    Do this instead

    Check the class of the model you are actually using before calling its methods.

Practice Tracing a Removal

MEDIUM

A flavor program uses a DefaultListModel that holds Vanilla, Chocolate, and Mint. The program then removes Chocolate from the model. Trace the change: which object is changed first, what notification is generated, which object receives it, and what the screen shows afterward. If the screen still showed Chocolate, at which of the three checks in the flowchart would you start looking?

Hints
  • Start by asking which object the removal is called on.
  • The notification comes from the model, and the JList responds to it.
  • If the model no longer holds Chocolate but the screen still shows it, the problem lies between the notification and the view.

Where the Pattern Fits Together

  1. 1
    A JList is the view that draws items, while the list model holds the actual items and the operations that can act on them.
  2. 2
    A list built directly from an array uses a simple model that can show items but cannot add or delete them.
  3. 3
    DefaultListModel supports adding and removing items, and changes to it generate a ListDataEvent that the registered JList uses to redraw itself.
  4. 4
    When a list shows the wrong items, check the model contents, the notification, and the view's rendering in that order.

Key Takeaways

  • A JList is the view, the list model holds the actual items and the operations allowed on them, and listeners respond to user actions.
  • A list built from an array uses a simple model that cannot add or delete items.
  • DefaultListModel supports adding and removing items, and changing it generates a ListDataEvent that makes the JList redraw.
  • When the list is wrong, trace backward through model contents, notification, and view rendering to find the broken link.