Hi, I've been searching all the internet for an answer for my problem, but none of the sites I've stumbled upon haven't given any results.

So, I have a JList, held inside JSCrollPane, held inside JPanel inside JFrame. I have a MySQL database, and another block of code retrieves stuff from there and puts it in a vector<String>. When I update the JLists ListModel to hold the exact same information as the vector, the JList doesn't update the results. I have only a blank JList as a result. :/

Here's some code of the problem.

// Cleaned version of the MainUI file, which creates the elements
public class MainUI {

    private JScrollPane seriesPane;
    private DefaultListModel lmSeries;
    private JList seriesList;
    private 

    MainUI(Main main_par) {
        mControl = main_par;
        createUI();
    }

    private void createUI() {

        ....

        lmSeries = new DefaultListModel();

        seriesPane = new JScrollPane();

        seriesList = new JList();

        seriesPane.add(seriesList);
        seriesPanel = new JPanel();

        seriesPanel.add(seriesPane);
        
        ....

    }

    void listSeries(Vector v) {
        DefaultListModel lm = (DefaultListModel) seriesList.getModel();
        lm.removeAllElements();
        for(int i = 0; i < v.size(); i++) {
            lm.add(i, v.elementAt(i));
            System.err.println("added: " + lm.lastElement());
        }
    }
}

The println in listSeries() method prints out all the lines correctly, so the ListModel does get updated. I'm running the main program in InvokeLater(), so I guess it should invoke the event dispatch thread..?

Recommended Answers

All 13 Replies

It looks to me like your code should work just fine. Are you sure that you aren't resetting the model at some point after listSeries() has updated it? The add() method automatically fires an event that should keep your JList updated with the model.

It looks to me like your code should work just fine. Are you sure that you aren't resetting the model at some point after listSeries() has updated it? The add() method automatically fires an event that should keep your JList updated with the model.

Nope, there isn't happening any resetting. I'm really confused with this. :S

JList() Constructs a JList with an empty, read-only, model.

The API says it all.

commented: Good eye. +14

The API says it all.

I tried to replace the constructor call with "= new JList(lm)" without any better results.

The API says it all.

Good catch, James. I never saw that. I assumed it was a mutable model like the default combobox model.

It looks like you'll need to create your own model if you wish to add or remove items. You can read about that in the tutorial here.

It should be just a minor change to your existing code to use new JList(lmSeries); since you're creating that model anyway.

But shouldn't this work with DefaultListModel? I mean, it has all the good jazz for adding, removing etc.

// in main code
...
    lmSeries = new DefaultListModel();
    seriesList = new JList(lmSeries);
...

// update code
    void listSeries(Vector v) {
        lmSeries.removeAllElements();
        for(int i = 0; i < v.size(); i++) {
            lmSeries.add(i, v.elementAt(i));
            System.err.println("added: " + lmSeries.lastElement());
        }
    }

Why doesn't this work? ;(

This is a good problem! That looks OK to me as well. Maybe the problem lies somewhere else? How hard would it be for you to strip this down to a stand-alone runnable program that displays the problem and that we can work on?

Okey, here's the three source codes. I stripped it to the near minimum, and it still clearly shows the problem. I checked the DefaultListModel code, and it does fire the IntervalAdded() method, which should update the list.

Note that the listSeries() -method states only one of the vast range of possibilities I have already tried. It _should_ work with that too, but it just doesn't. :(

EDIT:
Note that you don't need any "jar" tricks when running this, just compile with javac and then run with java. Wanted to state this :)

OK, I got a fix based on the way I usually do this, but I haven't worked out why your version doesn't work yet, but here goes:
I moved up the code that creates the list to be before creating the scrollpane, then used the scrollpane constructor with the list as parameter

lmSeries = new DefaultListModel();      
seriesList = new JList(lmSeries);
seriesList.setPreferredSize(new Dimension(180, 380));
seriesPane = new JScrollPane(seriesList);

ps: I note that add is inherited from Container, not overridden in scrollpane, so maybe it doesn't hook the model into the scrollpane in the same way that the constructor does. Anyway, it's working now.

Thanks for your effort, James, but it still doesn't work. No visible list yet...

That's wierd. I tried your code, it didn't work, I changed it as above, it worked.
Here's the exact code I used:

import java.io.File;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import java.io.IOException;

import javax.swing.SwingUtilities;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;




public class Main {
   
   public static void main(String[] args) throws IOException {

      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
              Main main = new Main();
          }
      });
   }
    
    // Controlled UI
    private MainUI ui;

    Main() {

        ui = new MainUI(this);
        ui.setVisible(true);
        fetchSeries();
    }

    private void fetchSeries() {
        // Originally, the vector is filled via database query, but
        // i'll just hard code it now...
        //Vector v = db.getSeries();
        Vector v = new Vector();
        v.add("Entry 1");
        v.add("Entry 2");
        v.add("Entry 3");
        
        ui.listSeries(v);
    }

}

class MainUI {

   // Controller controlling this UI
   private Main mControl;

   // Constants
   private static final int MAIN_WIDTH = 200;
   private static final int MAIN_HEIGHT = 460;

   // Variables
   private JFrame mainFrame;
   private JPanel mainPanel, seriesPanel;
   private JScrollPane seriesPane;
   private JList seriesList;
   private JLabel lblSeries;
   private DefaultListModel lmSeries;

   private Dimension screensize;

   MainUI(Main main_par) {
       mControl = main_par;
       createUI();

   }

   private void createUI() {
       // Get screen size
       Toolkit toolkit = Toolkit.getDefaultToolkit();
       screensize = toolkit.getScreenSize();

       // Create and set the main frame
       mainFrame = new JFrame("vg");
       mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       mainFrame.setBounds((screensize.width / 2) - (MAIN_WIDTH / 2),
               (screensize.height / 2) - (MAIN_HEIGHT / 2), MAIN_WIDTH, MAIN_HEIGHT);
       mainFrame.setPreferredSize(new Dimension(MAIN_WIDTH, MAIN_HEIGHT));
       mainFrame.setResizable(false);
       
       mainPanel = new JPanel();
       mainFrame.add(mainPanel);
       
       lmSeries = new DefaultListModel();      
                                                          
       seriesList = new JList(lmSeries);
       seriesList.setPreferredSize(new Dimension(180, 380));
       
       seriesPane = new JScrollPane(seriesList);
       seriesPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
       seriesPane.setPreferredSize(new Dimension(180, 380));
       

       
       seriesPanel = new JPanel();
       seriesPanel.setMaximumSize(new Dimension(180, 400));
       seriesPanel.setSize(180, 400);
       seriesPanel.setPreferredSize(new Dimension(180, 400));
       
       lblSeries = new JLabel("Sarja");
       lblSeries.setMaximumSize(new Dimension(180, 12));
       lblSeries.setPreferredSize(new Dimension(180, 12));
       
       seriesPanel.add(lblSeries);
       seriesPanel.add(seriesPane);

       mainPanel.add(seriesPanel);

       mainFrame.pack();
   }


   public void setVisible(boolean b) {
       mainFrame.setVisible(b);
   }

   void listSeries(Vector v) {     
       for(int i = 0; i < v.size(); i++) {
           lmSeries.add(i, v.elementAt(i));
           System.err.println("added: " + lmSeries.lastElement());
       }
       Enumeration e = ((DefaultListModel) seriesList.getModel()).elements();
       while (e.hasMoreElements()) {
          System.out.println("contains " + e.nextElement());
       }
   }
}

How does that work for you?

Now it works, I just don't know why. :D

I checked my code, and there wasn't really anything different from yours. Well, the main thing is, it works now. Thanks a lot!

I had the same problem. From the above code, I can see that in the working code the .removeAllElements()
is nowhere called.
Maybe this fixed the problem.
In a similar case, when I stopped using .removeAllElements() and .clear(),
and used list.setModel(the DefaultListModel()) whenever I wanted to clear the table, it worked fine.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.