当选择0索引时删除和添加时,Swing JList冻结

Min*_*tis 2 java user-interface swing jlist

这是一个示例,其中您按下按钮,并且jList1重新填充了从a1到a1000的项目:

//variable
private List<String> list = new ArrayList<>();

...

//main method
jList1.setModel(new DefaultListModel());
for(int i = 0; i < 1000; i++) {
    list.add("a"+i);
}

...

//button action - jList1 refill
DefaultListModel dtm = (DefaultListModel)jList1.getModel();
dtm.removeAllElements();
for(String s : list) {
    dtm.addElement(s);
}
Run Code Online (Sandbox Code Playgroud)

如果我填充jList1,然后选择(用鼠标)0索引(jList中的第一个元素),然后按按钮,程序将在重新填充列表时冻结。如果我选择任何其他元素,或者根本不选择列表中的任何项目,则可以很好地填充它。

PS本示例在没有任何摆动或EWT线程的情况下完成,因为发现了使用它们的主要原因。

SSCCE:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lt;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;

/**
 *
 * @author Minutis
 */
public class Window {

    public static void main(String[] args) {
        final List<String> list = new ArrayList<>();


        JFrame frame = new JFrame("BorderLayout Frame");
        JPanel panel = new JPanel();
        final JList jList1 = new JList();
        JButton refill = new JButton("Refill");

        jList1.setModel(new DefaultListModel());
        for(int i = 0; i < 1000; i++) {
            list.add("a"+i);
        }

        refill.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                DefaultListModel dtm = (DefaultListModel)jList1.getModel();
                dtm.removeAllElements();
                for(String s : list) {
                    dtm.addElement(s);
                }
            }

        });

        frame.add(panel);
        panel.setLayout(new BorderLayout());
        panel.add(jList1, BorderLayout.CENTER);
        panel.add(refill, BorderLayout.SOUTH);
        frame.setSize(300, 300);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
Run Code Online (Sandbox Code Playgroud)

Jak*_*rka 5

问题是由于在选择第一个元素时删除了模型中的所有元素而引起的。当选择和删除索引时,由于某种原因,它将生成selectionChanged事件,该实现的方式。如果在删除另一个索引时选择了另一个索引(即使这意味着元素移动),则不会生成selectionChanged事件。

删除的方式是定期删除第一个元素,而选择索引保持不变。因此,对于选择索引0的情况,它将生成1000个selectionChanged事件,必须由EDT和侦听器处理。如果选择另一个索引,则仅生成一个事件。那大大减少了开销。

在选择索引0时重新填充之前,请尝试手动将选择设置为索引1:

if(jList1.getSelectedIndex() == 0){
     jList1.setSelectedIndex(1);
}
Run Code Online (Sandbox Code Playgroud)

我认为不必担心列表中是否只有一个元素-它不应做任何事情来将索引设置为大于该元素数。但这可能是特定于实现的。

由于某种原因,clearSelection()将导致为重新填充空列表而生成selectionChanged事件。