我为JTable写了一个自定义表模型:
class MessageTableModel{
private static Set<Message> messages = Collections.synchronizedSet(new TreeSet<Message>());
.
.
.
public void setMessages(List<Message> newMessages) {
Collections.sort(newMessages);
Iterator<Message> it = messages.iterator();
while (it.hasNext()) {
Message mess = it.next();
if (!newMessages.contains(mess)) {
it.remove();
this.fireTableDataChanged();
}
}
for (Message message : newMessages)
if (message.isOrderStatusMessage())
if (!messages.contains(message)) {
addMessage(message);
}
this.fireTableDataChanged();
}
public Message getMessageAtRow(int row){
return (Message) messages.toArray()[row];
}
}
问题是有一个更新表值的线程,以perodically方式调用setMessages()方法。如果我在此次更新期间尝试获取一行:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
在这一行:
return (Message) messages.toArray()[row];
有一种方法可以让方法getMessageAtRow()等待修改完成,或者解决这个问题的其他方法吗?
答案 0 :(得分:3)
Swing是单线程的。您无法在事件线程之外的线程上修改模型。解决这个问题的最简单方法是:
public void setMessages(List<Message> newMessages) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Collections.sort(newMessages);
Iterator<Message> it = messages.iterator();
while (it.hasNext()) {
Message mess = it.next();
if (!newMessages.contains(mess)) {
it.remove();
this.fireTableDataChanged();
}
}
for (Message message : newMessages)
if (message.isOrderStatusMessage())
if (!messages.contains(message)) {
addMessage(message);
}
this.fireTableDataChanged();
}
)};
}
此外,fireTableDateChanged()
也应仅在事件线程上调用。