[英]Swing JList freezes when I delete and add while 0 index was selected
这是一个例子,你按下一个按钮,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);
}
如果我填充jList1
,然后选择(用鼠标)0 索引(jList 中的第一个元素),然后按下按钮,程序会在重新填充列表时冻结。 如果我选择任何其他元素或根本不选择列表中的任何项目,那么它就可以很好地填充。
PS 这个例子是在没有任何 Swing 或 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);
}
}
问题是在选择第一个元素时删除模型中的所有元素引起的。 它的实现方式,当一个索引被选择并被删除时,由于某种原因它会生成一个 selectionChanged 事件。 如果在删除另一个索引时选择了另一个索引(即使这意味着元素移动),它也不会生成 selectionChanged 事件。
移除的实现方式是定期移除第一个元素,而选择索引保持不变。 因此,对于选择索引 0 的情况,它会生成 1000 个 selectionChanged 事件,这些事件必须由 EDT 和侦听器处理。 如果选择另一个索引,则仅生成 1 个事件。 这大大减少了开销。
在选择索引 0 时重新填充之前,尝试手动将选择设置为索引 1:
if(jList1.getSelectedIndex() == 0){
jList1.setSelectedIndex(1);
}
我认为如果列表中只有一个元素,则无需担心 - 它不应该做任何事情来将索引设置为大于元素计数。 但这可能是特定于实现的。
出于某种原因, clearSelection()
将导致产生 selectionChanged 事件以重新填充空列表。
XxxListModel
add
/ remove
/ modify
Items
,例如
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Testing extends JFrame {
private static final long serialVersionUID = 1L;
private DefaultListModel listModel = new DefaultListModel();
private JList list = new JList(listModel);
private int currentSelectedRow = 0;
private int xX = 0;
public Testing() {
setLocation(400, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
for (int x = 0; x < 51; x++) {
listModel.addElement("" + x);
xX++;
}
JScrollPane sp = new JScrollPane(list);
final JViewport vp = sp.getViewport();
add(sp, BorderLayout.CENTER);
/*JButton btn = new JButton("Get Row:");
add(btn, BorderLayout.SOUTH);
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
try {
int goToRow = Integer.parseInt(JOptionPane.showInputDialog(getContentPane(), "Go To Row:"));
Rectangle r = list.getCellBounds(goToRow, goToRow);
if (goToRow > currentSelectedRow) {
r = list.getCellBounds(goToRow - 1, goToRow - 1);
int vph = vp.getExtentSize().height;
r.y += vph;
}
list.scrollRectToVisible(r);
list.setSelectedIndex(goToRow);
currentSelectedRow = goToRow;
} catch (Exception e) {
}
}
});*/
JButton btn1 = new JButton("Reset Model CastingModel");
add(btn1, BorderLayout.NORTH);
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
DefaultListModel model = (DefaultListModel) list.getModel();
model.removeAllElements();
for (int x = 0; x < 51; x++) {
model.addElement("" + (x + xX));
xX++;
}
//list.setModel(model);
}
});
JButton btn2 = new JButton("Reset Model directly from Model");
add(btn2, BorderLayout.SOUTH);
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
listModel.removeAllElements();
for (int x = 0; x < 51; x++) {
listModel.addElement("" + (x + xX));
xX++;
}
}
});
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Testing().setVisible(true);
}
});
}
}
编辑list.clearSelection()
; 没有任何问题,除了 1k 行之外的所有问题都是由 OP 所描述的问题引起的
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Testing extends JFrame {
private static final long serialVersionUID = 1L;
private DefaultListModel listModel = new DefaultListModel();
private JList list = new JList(listModel);
private int currentSelectedRow = 0;
private int xX = 0;
public Testing() {
setLocation(400, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
for (int x = 0; x < 999; x++) {
listModel.addElement("" + x);
xX++;
}
JScrollPane sp = new JScrollPane(list);
final JViewport vp = sp.getViewport();
add(sp, BorderLayout.CENTER);
JButton btn1 = new JButton("Reset Model CastingModel");
add(btn1, BorderLayout.NORTH);
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
list.clearSelection();
DefaultListModel model = (DefaultListModel) list.getModel();
model.removeAllElements();
for (int x = 0; x < 999; x++) {
model.addElement("" + (x + xX));
xX++;
}
//list.setModel(model);
}
});
JButton btn2 = new JButton("Reset Model directly from Model");
add(btn2, BorderLayout.SOUTH);
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
list.clearSelection();
listModel.removeAllElements();
for (int x = 0; x < 999; x++) {
listModel.addElement("" + (x + xX));
xX++;
}
}
});
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Testing().setVisible(true);
}
});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.