我有一个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进行了测试。
答案 0 :(得分:2)
我建议编写自己的模型,允许一次添加一堆值。我想这不是模型的补充,而是由此触发的GUI事件会破坏性能。
答案 1 :(得分:1)
你不应该像这样在事件循环中向模型中添加大量元素。更好的做法是让你的动作监听器从一个线程中产生以添加项目,并让该线程调用一个SwingUtilities.invokeLater()来将更改事件激发到列表中。
请注意,根据下面的注释,您需要创建一个AbstractListModel(或它的子类)并将其作为模型,并在invokeLater中调用fireContentsChanged
。
答案 2 :(得分: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);
}
});
这样就可以在添加每个新项目时触发事件。