2010-08-26 190 views
3

我有一个JList组件应该被清空和重新填充。下面的代码(基于我的原始代码)显示了一个JList和一个JButton一个简单的窗口:非常缓慢JList重填

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测试了它。

+0

什么“物品”? – 2010-08-26 15:44:23

+0

元素(“aaaa”) – asalamon74 2010-08-27 07:09:19

回答

2

我建议编写自己的模型,它允许一次添加一堆值。我想这不是对模型的补充,而是由触发的图形用户界面事件导致的性能下降。

+0

Thx为小费。我自己的模型类基于DefaultListModel,我将其修改为使用AsbtractListModel并创建了一个添加一堆值的方法。放缓已经消除。仍然不完全理解DefaultListModel的这种奇怪的行为。 – asalamon74 2010-08-27 13:03:14

1

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

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

+0

您不能将项目添加到已关联的DefaultListModel关闭EDT(并期望它可以工作)。 – 2010-08-26 15:43:27

1

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

反正一个更好的方式做这将是创建一个新的模型,然后只需将其添加到列表:

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); 
     } 
    }); 

这种方式,因为每个新项目添加事件不会被触发。