[英]How do I update a JTable based on a notification received from a long-running task in other thread?
I've an Observer TableModel which listens to some changes, performed in the database, and when so the update method below is called. 我有一个Observer TableModel,它监听在数据库中执行的一些更改,然后调用下面的更新方法。 My problem is, how should I prevent errors like:
我的问题是,我应该如何防止错误:
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.set(ArrayList.java:337)
at com.mysimpatico.memoplatform.persistenceui.MeaningsViewerTopComponent$DefaultTableModelImpl.update(MeaningsViewerTopComponent.java:108)
I don't see how SwingWorker would help. 我不知道SwingWorker会如何提供帮助。 I've the long-running database task being performed in a separate thread, but this calls upon a method (database persisting) in an Observable class which notifies observers.
我在一个单独的线程中执行长时间运行的数据库任务,但是这会在Observable类中调用一个方法(数据库持久化)来通知观察者。
@Override
public void update(Observable o, final Object arg) {
final Meaning meng = (Meaning) arg;
final int row;
final boolean insert;
synchronized (mengs) {
if (mengs.contains(meng)) {
row = meng.getObjId();
mengs.set(row, meng);
insert = false;
} else {
row = mengs.size();
mengs.add(row, meng); //last
insert = true;
}
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
if (insert) {
fireTableRowsInserted(row, row);
} else {
fireTableRowsUpdated(row, row);
}
}
});
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
} catch (InvocationTargetException ex) {
Exceptions.printStackTrace(ex);
}
}
}
Despite firing insert / update TableModelEvent
s on the event dispatch thread you're actually updating the TableModel
on whichever thread is performing the notification of the database update. 尽管在事件调度线程上触发插入/更新
TableModelEvent
,但实际上在执行数据库更新通知的任何线程上都会更新TableModel
。 This is dangerous as it means: 这很危险,因为它意味着:
TableModel
in an inconsistent state. TableModel
处于不一致状态。 TableModel
as the notification thread is altering it. TableModel
因为通知线程正在改变它。 The solution should (in theory) simply be a case of moving your call to SwingUtilities.invokeAndWait
to outside the block of code that begins: synchronized(mengs)
. 解决方案应该(理论上)只是将您对
SwingUtilities.invokeAndWait
的调用移到开始的代码块之外: synchronized(mengs)
。 Also, once you've done this you can actually removed the synchronized keyword entirely as all access to your model will be done on the EDT. 此外,一旦完成此操作,您实际上可以完全删除synchronized关键字,因为对模型的所有访问都将在EDT上完成。
As an aside I would avoid using the Observer
/ Observable
classes (for more information see my answer to this question ); Observable
我会避免使用Observer
/ Observable
类(有关更多信息,请参阅我对此问题的回答 ); far better to define domain-specific listener interfaces and event classes (that subclass java.util.EventObject
). 更好地定义特定于域的侦听器接口和事件类(子类
java.util.EventObject
)。
Are your indexes correct? 你的索引是否正确?
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
The above statement says you only have one entry in the array list. 上面的语句说你只在数组列表中有一个条目。 I can't tell if your code is an "add" or an "update".
我不知道你的代码是“添加”还是“更新”。 But remember that ResultSet indexes are 1 based not 0 based so maybe you need to subtract 1 from all your row values?
但请记住,ResultSet索引是基于1而不是基于0,所以可能需要从所有行值中减去1?
One option is using a org.jdesktop.application.Task
. 一种选择是使用
org.jdesktop.application.Task
。 You will need to pass the TableModel
to the Task and then so a simple TableModel.insert
call. 您需要将
TableModel
传递给Task,然后再进行简单的TableModel.insert
调用。
Note: The task is just a nice wrapper around a Thread. 注意:任务只是围绕Thread的一个很好的包装器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.