Synchronized JList and JComboBox?
Asked Answered
K

2

9

In Java Swing, what's the best way for a JList and a JComboBox to be synchronized in terms of the data, i.e., to have the same list of items at any given point of time? Basically, if I add items to (or remove items from) one, the other should reflect the change automatically.

I've tried doing the following, but it doesn't seem to work:

JList list = new JList();
JComboBox comboBox = new JComboBox();
DefaultListModel listModel = new DefaultListModel();
// add items to listModel...
list.setModel(listModel);
comboBox.setModel(new DefaultComboBoxModel(listModel.toArray()));
Kingwood answered 8/2, 2011 at 23:6 Comment(0)
C
11

Your models - the ListModel for the list and the ComboboxModel for the combobox - need to be synchronized.

In the general case this would mean writing a special implementation of the models, but in your case you have luck: DefaultComboBoxModel in fact implements ListModel, so you simply can use the same model object for both your components.

JList list = new JList();
JComboBox comboBox = new JComboBox();
DefaultComboBoxModel listModel = new DefaultComboBoxModel();
// add items to listModel...
list.setModel(listModel);
comboBox.setModel(listModel);
Congeries answered 8/2, 2011 at 23:13 Comment(5)
I can't believe I didn't think of that even after scouring the APIs. It worked perfectly. Thanks a lot for your help!Kingwood
Neat for synchronizing the items, but is there a simple way to also synchronize the selected item ?Furor
@HpTerm: Not that easy. The Comboboxmodel manages the selection itself, while the list has a separate ListSelectionModel. You could subclass DefaultComboboxmodel implementing ListSelectionModel, or use listeners to synchronize the selection state (but take care to avoid infinite loops). (And you should set the selection mode to SINGLE_SELECTION.)League
Thx for the answer. I only need SINGLE_SELECTION. I've tried using bindings in Netbeans without success. I have now a working solution but it's more some kind of workaround. That's why I was asking myself if someone had an other way of doing that i didn't know. Thx.Furor
BTW thank you for the explanation of the defaultcomboboxmodel implements listmodel. I was struggling using 2 different models and synchronizing them, it's so much easier that way. Moreover, by doing as you shown has drastically simplified my workaround of synchronizing the selecteditem.Furor
R
5

You could have them share the same model, probably a DefaultComboBoxModel since it implements ListModel and thus should work for both the JComboBox and the JList. For example:

 import java.awt.Dimension;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;

 import javax.swing.*;

 public class ShareComboModel {
      private static final int TIMER_DELAY = 2000;

      public static void main(String[] args) {
           SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                     createGui();
                }
           });
      }

      private static void createGui() {
           String[] data = {"Fe", "Fi", "Fo", "Fum"};

           final DefaultComboBoxModel model = new DefaultComboBoxModel(data);

           JComboBox combobox = new JComboBox(model);
           JList jlist = new JList(model);

           new Timer(TIMER_DELAY, new ActionListener() {
                private int count = 0;
                public void actionPerformed(ActionEvent e) {
                     model.addElement("count: " + count);
                     count++;
                }
           }).start();

           JPanel comboPanel = new JPanel();
           comboPanel.add(combobox);

           JPanel listPanel = new JPanel();
           listPanel.add(new JScrollPane(jlist));          

           JPanel panel = new JPanel(new GridLayout(1, 0));
           panel.add(comboPanel);
           panel.add(listPanel);
           panel.setPreferredSize(new Dimension(400, 200));

           JFrame frame = new JFrame("App");
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           frame.getContentPane().add(panel);
           frame.pack();
           frame.setLocationRelativeTo(null);
           frame.setVisible(true);
      }
 }
Reo answered 8/2, 2011 at 23:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.