代码之家  ›  专栏  ›  技术社区  ›  asalamon74

非常缓慢的重新填充

  •  3
  • asalamon74  · 技术社区  · 15 年前

    我有一个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个项目)是非常快的。如果我一次又一次地按它,它仍然很快。

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

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

    我已经用JDK1.5和1.6测试过了。

    3 回复  |  直到 15 年前
        1
  •  2
  •   Landei    15 年前

    我建议你自己写一个模型,可以一次添加一堆值。我猜不是模型的添加,而是由它触发的GUI东西破坏了性能。

        2
  •  2
  •   camickr    15 年前

    我不知道为什么选择一个项目会导致性能问题。但每次添加一个项时,都会触发一个事件,通知列表重新绘制它的lef。因此,可能一个项目被选中的事实会导致额外的重新绘制。

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

        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
  •  1
  •   Paul Tomblin    15 年前

    您不应该像那样在事件循环中向模型中添加大量元素。更好的方法是让你的动作监听器派生出一个线程来添加项目,并让该线程调用SwingUtilities.invokeLater调用器()启动列表的更改事件。

    请注意,根据下面的注释,您需要创建AbstractListModel(或其子类)并将其设置为模型,然后调用 fireContentsChanged 在召唤器里。

    推荐文章