2010-08-26 308 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); 
     } 
    }); 

這種方式,因爲每個新項目添加事件不會被觸發。