Очень медленное повторное заселение JList
У меня есть компонент 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.
3 ответа
Я бы посоветовал написать свою собственную модель, которая позволяет добавлять сразу несколько значений. Я думаю, что это не дополнение к модели, а вызванные этим вещи с графическим интерфейсом, которые убивают производительность.
Я не уверен, почему выбор элемента вызывает проблемы с производительностью. Но каждый раз, когда вы добавляете элемент, происходит событие, которое заставляет список перекрашивать себя. Поэтому, возможно, тот факт, что элемент выбран, требует дополнительной перекраски.
В любом случае, лучший способ сделать это - создать новую модель, а затем просто добавить ее в список:
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);
}
});
Таким образом, события не запускаются при добавлении каждого нового элемента.
Вы не должны добавлять множество элементов в модель в цикле событий, подобном этому. Намного лучше было бы, чтобы ваш слушатель действий порождал поток, чтобы добавить элементы, и чтобы этот поток вызывал SwingUtilities.invokeLater() для запуска события change в списке.
Обратите внимание, что в соответствии с комментарием ниже, вам нужно сделать AbstractListModel (или его подкласс) и сделать его моделью, и вызвать fireContentsChanged
на это в invokeLater.