Есть ли реализация JList с отложенной загрузкой? - PullRequest
3 голосов
/ 12 мая 2009

Есть ли способ реализовать отложенную загрузку с помощью Swing JList?

Ответы [ 4 ]

11 голосов
/ 12 мая 2009

В некотором смысле, да. Вы можете создать пользовательский ListModel, который использует метод getElementAt(int index) для загрузки правильного значения, если оно еще не загружено. См. Пример в Javadocs для JList:

// This list model has about 2^16 elements.  Enjoy scrolling.

ListModel bigData = new AbstractListModel() {
    public int getSize() { return Short.MAX_VALUE; }
    public Object getElementAt(int index) { return "Index " + index; }
};
5 голосов
/ 28 марта 2010

Я решил это. Я пропустил решение, которое обсуждалось в верхней части документации по JList API.

В примере исходного кода, который я разместил в другом ответе на эту тему, добавьте эту строку (и комментарий) после создания JList:

  // Tell JList to test rendered size using this one value rather
  // than every item in ListModel. (Much faster initialization)
  myList.setPrototypeCellValue("Index " + Short.MAX_VALUE); 

Проблема в том, что JList по умолчанию обращается к каждому элементу во всей ListModel, чтобы определить во время выполнения необходимый размер дисплея. Строка, добавленная выше, переопределяет это значение по умолчанию и указывает JList проверять только одно переданное значение. Это одно значение действует как шаблон (прототип) для определения размера отображения JList.

См:

http://java.sun.com/javase/6/docs/api/javax/swing/JList.html#prototype_example

2 голосов
/ 13 мая 2009

Просто добавьте к другому ответу, когда вы создаете собственную реализацию ListModel, когда вы загружаете данные, которые вы хотите вызвать:

fireIntervalAdded(Object source,int index0, int index1)

Предполагается, что вы загружаете данные в свой список постепенно. Это приведет к обновлению JList, использующему его в качестве модели.

См. Javadoc для fireIntervalAdded

1 голос
/ 28 марта 2010

Неправильно. Этот JList выше НЕ загружен лениво.

Swing настаивает на доступе к каждому элементу во всей ListModel при отображении его на экране. Кроме того, после доступа ко всем элементам Swing затем повторно обращается к первому n количеству элементов, видимых на экране (в окне просмотра, а не за пределами экрана ниже).

Запустите этот простой класс "TestJList", чтобы доказать это. Я вызываю println каждый раз, когда выполняется getElementAt. Вы можете ясно видеть, что Swing вызывает этот метод для каждого элемента в ListModel.

Это происходит для меня на MacBook Unibody под управлением Mac OS X 10.6.2 с Java:

"1.6.0_17" Java (TM) SE Runtime Окружающая среда (сборка 1.6.0_17-b04-248-10M3025) Java HotSpot (TM) 64-битная серверная виртуальная машина (сборка 14,3-b01-101, смешанный режим)

import javax.swing.*;

/**
 *  This example proves that a JList is NOT lazily-loaded.
 */
public class TestJList {
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("HelloWorldSwing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create an artificial ListModel. 
        ListModel bigData =
            new AbstractListModel() {
                public int getSize() {
                    // return Short.MAX_VALUE;  // Try this if you have a long while to waste.
                    return 10;
                }

                public Object getElementAt(int index) {
                    System.out.println("Executing 'getElementAt' # " + index);
                    return "Index " + index;
                }
            };

        // Create a JList.
        JList myList = new JList(bigData);

        // Add the JList to the frame.
        frame.getContentPane().add(myList);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(
            new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
            });
    }
}

Запустите этот код, и вы увидите:

Executing 'getElementAt' # 0
Executing 'getElementAt' # 1
Executing 'getElementAt' # 2
Executing 'getElementAt' # 3
Executing 'getElementAt' # 4
Executing 'getElementAt' # 5
Executing 'getElementAt' # 6
Executing 'getElementAt' # 7
Executing 'getElementAt' # 8
Executing 'getElementAt' # 9
Executing 'getElementAt' # 0
Executing 'getElementAt' # 1
Executing 'getElementAt' # 2
Executing 'getElementAt' # 3
Executing 'getElementAt' # 4
Executing 'getElementAt' # 5
Executing 'getElementAt' # 6
Executing 'getElementAt' # 7
Executing 'getElementAt' # 8
Executing 'getElementAt' # 9

-fin-

...