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.
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?
Reveal 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.
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
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.
- The model is created and stored in a variable that stays in scope.
- The
JListis given the model so it knows where to get its items. - The later
addElementcall changes the model, not theJList.
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.
- 1Identify the object to change
The items live in the
DefaultListModel, so the change goes to that object, not to theJList. - 2Call the add method on the model
Calling
addElementwith Mint adds the item to the model's data. - 3Leave the JList alone
No separate call to the
JListis needed. TheJListis registered to hear about changes in its model.
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.
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.
Mistakes Beginners Make With List Models
Common mistake Trying to add items to a list built directly from an array
Why it failsThe model Swing creates from an array can report its items but cannot add or delete them.
Do this insteadUse a DefaultListModel when the list must change.
Common mistake Calling a method on the JList to add an item
Why it failsThe add and remove operations act on the model, which holds the data the
JListdisplays.Do this insteadCall 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 failsWithout a stored reference, the program has no way to call methods on the model while it runs.
Do this insteadStore 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 failsThe 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 insteadCheck the class of the model you are actually using before calling its methods.
Practice Tracing a Removal
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
JListresponds 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
- 1A
JListis the view that draws items, while the list model holds the actual items and the operations that can act on them. - 2A list built directly from an array uses a simple model that can show items but cannot add or delete them.
- 3
DefaultListModelsupports adding and removing items, and changes to it generate aListDataEventthat the registeredJListuses to redraw itself. - 4When a list shows the wrong items, check the model contents, the notification, and the view's rendering in that order.
Key Takeaways
- A
JListis 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.
DefaultListModelsupports adding and removing items, and changing it generates aListDataEventthat makes theJListredraw.- When the list is wrong, trace backward through model contents, notification, and view rendering to find the broken link.