4

I have a JList component which should be emptied and repopulated. The following code (based on my original code) shows a simple window with a JList and a JButton:

import java.awt.BorderLayout;
import javax.swing.*;

public class JListTest extends javax.swing.JFrame{
    JList jList;
    JButton button;
    DefaultListModel model;

    public JListTest() {
        jList = new JList();
        model = new DefaultListModel();
        jList.setModel( model );
        button = new JButton();

        getContentPane().add(jList, java.awt.BorderLayout.CENTER);

        button.setText("add 10000 items");
        button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                model.clear();
                for( int i=0; i<10000; ++i ) {
                    model.addElement( "aaaa");
                }
            }
        });
        getContentPane().add(button, BorderLayout.PAGE_START);        
        pack();        
    }

    public static void main(String args[]) {
        JListTest jlt =new JListTest();
        jlt.setSize(300, 300);
        jlt.setVisible( true );
    }
}

If I press the button the insertion (10000 items) is very fast. If I press it again and again it is still very fast.

If I select the third item and press the button, the result is the same, the insertion is very fast.

If I select the first item and press the button, the program becomes very slow (actually I have to stop it).

Why the selection of the first item slows down the execution?

I've tested it using JDK 1.5 and 1.6.

4

3 回答 3

2

I'd suggest to write your own model which allows to add a bunch of values at once. I guess it's not the addition to the model but the GUI things triggered by this that kill the performance.

于 2010-08-26T14:53:42.297 回答
2

我不确定为什么选择一个项目会导致性能问题。但是每次您添加一个项目时,都会触发一个事件,告诉列表重新绘制其自身。所以也许选择一个项目的事实会导致额外的重绘。

无论如何,更好的方法是创建一个新模型,然后将其添加到列表中:

    button.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            DefaultListModel dlm = new DefaultListModel();
            for( int i=0; i<10000; ++i ) {
                dlm.addElement( "aaaa");
            }
            jList.setModel(dlm);
        }
    });

这样,在添加每个新项目时不会触发事件。

于 2010-08-26T15:27:39.627 回答
1

您不应该在这样的事件循环中向模型中添加大量元素。更好的是让您的动作侦听器产生一个线程以添加项目,并让该线程调用 SwingUtilities.invokeLater() 以将更改事件触发到列表。

请注意,根据下面的评论,您需要创建一个 AbstractListModel(或其子类)并将其设为模型,并fireContentsChanged在 invokeLater 中调用它。

于 2010-08-26T14:48:07.443 回答