I have a program that need to update the content of JList
, which is DefaultListModel
on another thread. Since the number of contents may change from time to time, so I just clear all content and add new content into DefaultListModel
when updating. But seems I ran into an issue that JFrame
starts refreshing while my thread is doing update. I got exceptions like this
Exception in thread "AWT-EventQueue-0"
java.lang.ArrayIndexOutOfBoundsException: 3
Here is an example of the code
DefaultListModel model;
JList jList;
JScrollPane jScrollPane;
Thread thread;
public Frame() {
this.setTitle("ASM_SIMULATOR");
this.setBounds(100, 100, 500, 500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getContentPane().setLayout(null);
model = new DefaultListModel();
jList = new JList(model);
jScrollPane = new JScrollPane(jList);
jList.setBounds(50, 50, 300, 200);
jScrollPane.setBounds(50, 50, 300, 200);
this.getContentPane().add(jScrollPane);
this.setVisible(true);
thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
makeData();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
}
public void makeData() {
System.out.println("makeData()");
model.clear();
for (int i = 0; i < 20; i++) {
model.addElement((int) (Math.random() * 100));
}
}
public static void main(String[] args) {
new Frame();
}
You violate the basic "all Swing component should be accessed/modified on the Event Dispatch Thread (=EDT), and on the EDT only" twice in that code snippet.
new Frame()
call in an SwingUtilities#invokeLater
or some similar methodJList
, on which the JList
updates itself (again, on the wrong thread).Two possible solutions:
DefaultListModel
on your background thread, and replace it in one go on the EDT.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With