tags:

views:

367

answers:

1

I've got my "virtual list" in swing working well, but it seems to fail when I exceed some particular number of items. By "fail" I mean that the scroll bar magically vanishes when the number of items is > Nmax, and it comes back when the number of items is <= Nmax; Nmax seems to be somewhere around 119,304,000 on my system.

What am I running up against?!?!

(Here's a test program: on my computer, if I type in 119,304 it works ok, but I click the up arrow and the scroll bar disappears)

package com.example.test;

import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.AbstractListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

// based on:
// http://www.java2s.com/Tutorial/Java/0240__Swing/extendsAbstractListModel.htm
// http://www.java2s.com/Tutorial/Java/0240__Swing/SpinnerNumberModel.htm
// http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/SpinnerNumberModel.html
// http://www.java2s.com/Tutorial/Java/0240__Swing/ListeningforJSpinnerEventswithaChangeListener.htm
// http://java.sun.com/products/jfc/tsc/tech_topics/jlist_1/jlist.html

public class BigVirtualList extends JFrame {

    public static void main(String[] args) {
     new BigVirtualList();
    }

    static final int initialLength = 1;
    final private JList list1 = new JList();
    final private BVLData bvldata = new BVLData(initialLength*1000);

    public BigVirtualList() {
     this.setTitle("Big virtual list");
     this.getContentPane().setLayout(new BorderLayout());
     this.setSize(new Dimension(400, 300));
     list1.setModel(bvldata);

     list1.setPrototypeCellValue(list1.getModel().getElementAt(0));


     SpinnerModel model1 = new SpinnerNumberModel(initialLength,1,1000000,1);
     final JSpinner spinner1 = new JSpinner(model1);

     this.getContentPane().add(new JScrollPane(list1), BorderLayout.CENTER);
     JLabel label1 = new JLabel("Length (1000s of items):");
     JPanel panel1 = new JPanel(new BorderLayout());
     panel1.add(label1, BorderLayout.WEST);
     panel1.add(spinner1, BorderLayout.CENTER);
     this.getContentPane().add(panel1, BorderLayout.SOUTH);  

     ChangeListener listener = new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
       Integer newLength = (Integer)spinner1.getValue();
       bvldata.setLength(newLength*1000);
      }
     };

     spinner1.addChangeListener(listener);
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     setVisible(true);
    }
}

class BVLData extends AbstractListModel {
    public BVLData(int length) { this.length = length; }

    private int length;

    public int getLength() { return length; }
    public void setLength(int length) {
     int oldLength = getLength();
     this.length = length;
     int newLength = getLength();

     if (newLength > oldLength)
      fireIntervalAdded(this, oldLength+1, newLength);
     else if (newLength < oldLength)
      fireIntervalRemoved(this, newLength+1, oldLength);  
    } 

    @Override
    public Object getElementAt(int index) {
     return "Item "+index+" mod 107 = "+(index%107);
    }

    @Override
    public int getSize() { return getLength(); }

}
+6  A: 

Well I don't see the purpose but anyway ...

I guess you break the integer max value somewhere in the scroll pane:

System.out.println("CellHeight:"+list1.getFixedCellHeight());
System.out.println("CellHeight*119304000:"+NumberFormat.getNumberInstance().format(list1.getFixedCellHeight()*119304000.0));
System.out.println("MAXINT:"+Integer.MAX_VALUE);

Gives you the numbers:

CellHeight:18
CellHeight*119304000:2.147.472.000
MAXINT:2.147.483.647

As you can see adding another 18000 pixel in height will go beyond MAXINT ... this gets you in trouble.

pkliem
+1: I was coming to the same conclusion. 2^31 / 18 ~= 119304647.
Pourquoi Litytestdata
Ah! That makes sense. So the list actually tries to render items as if it were a very large canvas, each item in their proper place?
Jason S
+1: I just added the line "list1.setFixedCellHeight(10);" and now it goes to 214,748.
Michael Myers
Most probably the list does not render all items on a virtual canvas. I guess the scroll bar bounds will be set to 0...maxheight. If the height exceeds the positive integer max value it overflows to the negative and the scroll bar is "no longer needed"
pkliem
Jason S
Well, I think reimplementing a scroll bar using long might be possible (or do the scroll management yourself use a scrollbar and a factor). I would try to think of other possibilities to navigate since its not really usable with a scrollbar anyway
pkliem
yeah, maybe a pair of scrollbars (coarse+fine "zoom"), and a spinner for random-access.
Jason S