【问题标题】:Very slow JList repopulation非常慢的 JList 重新填充
【发布时间】:2011-04-04 07:47:07
【问题描述】:

我有一个应该清空并重新填充的 JList 组件。以下代码(基于我的原始代码)显示了一个带有 JList 和 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 );
    }
}

如果我按下按钮,插入(10000 个项目)非常快。如果我一次又一次地按下它,它仍然非常快。

如果我选择第三项并按下按钮,结果是一样的,插入非常快。

如果我选择第一项并按下按钮,程序会变得很慢(实际上我必须停止它)。

为什么选择第一项会减慢执行速度?

我已经使用 JDK 1.5 和 1.6 对其进行了测试。

【问题讨论】:

    标签: java jlist defaultlistmodel


    【解决方案1】:

    我建议编写您自己的模型,该模型允许一次添加一堆值。我想这不是模型的添加,而是由此触发的 GUI 事物会影响性能。

    【讨论】:

    • 谢谢小费。我自己的模型类基于 DefaultListModel,我对其进行了修改以使用 AsbtractListModel 并创建了一个添加一堆值的方法。减速已消除。仍然不完全理解 DefaultListModel 的这种奇怪行为。
    【解决方案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);
            }
        });
    

    这种方式不会在添加每个新项目时触发事件。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 您无法将项目添加到已连接的 DefaultListModel 关闭 EDT(并希望它能够工作)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      • 2015-02-03
      相关资源
      最近更新 更多