我有一个程序需要更新 JList
的内容,它是另一个线程上的 DefaultListModel
。由于内容的数量可能会不时发生变化,所以我只是在更新时清除所有内容并将新内容添加到DefaultListModel
中。但似乎我遇到了一个问题,即 JFrame
在我的线程进行更新时开始刷新。我有这样的异常
Exception in thread "AWT-EventQueue-0"
java.lang.ArrayIndexOutOfBoundsException: 3
这是一个代码示例
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();
}
最佳答案
您在该代码段中两次违反了基本的“所有 Swing 组件都应在事件调度线程 (=EDT) 上访问/修改,并且仅在 EDT 上”。
- 您的主要方法应该将
new Frame()
调用包装在SwingUtilities#invokeLater
或一些类似的方法中 - 您的模型更新线程在后台线程上更改模型。更新模型将触发由
JList
接收的事件,JList
会在这些事件上更新自身(同样,在错误的线程上)。
两种可能的解决方案:
- 在您的后台线程上创建一个新的
DefaultListModel
,并在 EDT 上一次性替换它。 - 不断更新现有模型,但要确保更新发生在 EDT 上。
关于java - 在另一个线程上更新 DefaultListModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13097935/