所以我实际上每次击中按键时都会尝试刷新我的JTable,或者当观察者的部分有更新时.偶尔我得到的是一个冻结的应用程序和这个堆栈跟踪……
Exception in thread “AWT-EventQueue-0” java.lang.ArrayIndexOutOfBoundsException: 5 >= 5
at java.util.Vector.elementAt(Unknown Source)
at javax.swing.table.DefaultTableColumnModel.getColumn(Unknown Source)
at javax.swing.plaf.synth.SynthTableUI.paintCells(Unknown Source)
at javax.swing.plaf.synth.SynthTableUI.paint(Unknown Source)
at javax.swing.plaf.synth.SynthTableUI.update(Unknown Source)
at javax.swing.JComponent.paintComponent(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent._paintImmediately(Unknown Source)
at javax.swing.JComponent.paintImmediately(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread “AWT-EventQueue-0” java.lang.ArrayIndexOutOfBoundsException: 4 >= 4
at java.util.Vector.elementAt(Unknown Source)
at javax.swing.table.DefaultTableColumnModel.getColumn(Unknown Source)
at sun.swing.SwingUtilities2.convertColumnIndexToModel(Unknown Source)
at javax.swing.JTable.convertColumnIndexToModel(Unknown Source)
at javax.swing.JTable.getColumnClass(Unknown Source)
at javax.swing.plaf.synth.SynthTableUI$SynthTableCellRenderer.getTableCellRendererComponent(Unknown Source)
at javax.swing.JTable.prepareRenderer(Unknown Source)
at javax.swing.plaf.synth.SynthTableUI.paintCell(Unknown Source)
at javax.swing.plaf.synth.SynthTableUI.paintCells(Unknown Source)
at javax.swing.plaf.synth.SynthTableUI.paint(Unknown Source)
at javax.swing.plaf.synth.SynthTableUI.update(Unknown Source)
at javax.swing.JComponent.paintComponent(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent._paintImmediately(Unknown Source)
at javax.swing.JComponent.paintImmediately(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
如果有帮助,这是我刷新表的代码:
public synchronized void refreshTable()
{
Customer cust = custManager.getCustomer(phoneNumber.getText());
if (cust == null)
{
table.setModel(new DefaultTableModel(new Object[][] {},tableHeader) {
@SuppressWarnings("rawtypes")
Class[] columnTypes = new Class[] {Integer.class,String.class,Object.class,Object.class};
@SuppressWarnings({ "unchecked","rawtypes" })
public Class getColumnClass(int columnIndex) {
return columnTypes[columnIndex];
}
public boolean isCellEditable(int row,int column) {
return false;
}
});
table.getColumnModel().getColumn(0).setPreferredWidth(40);
table.getColumnModel().getColumn(1).setPreferredWidth(120);
return;
}
Object[][] grid = new Object[cust.getOrderHistory().size()][6];
SimpleDateFormat sdf = new SimpleDateFormat("MMM/dd/yyyy HH:mm");
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance();
int i = 0;
for (Entry<GregorianCalendar,Order> orderEntry : cust.getOrderHistory())
{
Order order = orderEntry.getValue();
grid[i][0] = order.getOrderID();
grid[i][1] = sdf.format((order.getProcessedTimestamp().getTime()));
grid[i][2] = currencyFormat.format(order.getSubTotal()/100.00);
grid[i][3] = currencyFormat.format(order.getTaxedAmount()/100.00);
grid[i][4] = currencyFormat.format(order.getTotal()/100.00);
grid[i][5] = order.getOrderStatus();
i++;
}
DefaultTableModel dft = new DefaultTableModel(grid,tableHeader) {
@SuppressWarnings("rawtypes")
Class[] columnTypes = new Class[] {Integer.class,Object.class};
@SuppressWarnings({ "unchecked","rawtypes" })
public Class getColumnClass(int columnIndex) {
return columnTypes[columnIndex];
}
public boolean isCellEditable(int row,int column) {
return false;
}
};
table.setModel(dft);
table.getColumnModel().getColumn(0).setPreferredWidth(40);
table.getColumnModel().getColumn(1).setPreferredWidth(120);
}
为了记录,我尝试在try / catch中包装它,没有那样也无济于事.我也尝试过更改默认的异常处理程序,这也是不成功的.
我可以看到的最大问题之一是,您没有将表格绑定到数据上,然后在更改单元格时刷新单元格,每次按键时都会从表格下方更改整个数据模型.
我猜测你正在经历一场“比赛”状态.您按一个键,开始重建您的表及其模型的过程.部分通过重建(请记住,Swing使用线程,因此在您键入时仍然会发生表更新),您将启动并触发另一个重建,从而在仍在运行的第一个刷新下更改模型.当然,在没有看到所有代码的情况下我无法确定,但我可以提出一些建议,使事情更清晰,更不容易出现并发问题.
您可以创建自己的表模型类,并实现它以直接查看模型,而不是编写获取模型数据并将其转换为每个关键笔划的简单表模型的代码.这样,您就不会在模型和阵列之间不断重新传输数据.
要创建自己的表模型,只需从AbstractTableModel(http://download.oracle.com/javase/6/docs/api/javax/swing/table/AbstractTableModel.html)扩展即可.如果你不确定如何去做,原始Java教程(http://download.oracle.com/javase/tutorial/uiswing/components/table.html#data)中有一个很好的例子.对你来说最重要的是“getValueAt”方法,它接受一行和一列并返回该单元格应包含的值.这就是您想要放置查看“Order”对象的代码并生成所需输出的位置.
获得自定义TableModel对象后,只需在初始化时将其新实例传递到表的“setModel”方法中.
完成后,您将需要处理合理的模型刷新.要刷新表中的所有数据,可以触发“fireTableDataChanged”事件.或者,您只能刷新实际需要更改的表格部分,而不是每次都刷新整个部分.而不是在这里详细介绍细粒度细节,我只是简单地指向优秀的Java Tutorial页面:http://download.oracle.com/javase/tutorial/uiswing/components/table.html#fire