刷新JTable在Swing中提供异常 [英] Refreshing JTable in Swing Gives Exception

查看:158
本文介绍了刷新JTable在Swing中提供异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我基本上试图刷新我的JTable每次击键被击中,或当观察者有一个更新。偶尔我得到的是一个冻结的应用程序,这个堆栈跟踪...


线程中的异常AWT-EventQueue-0java.lang .ArrayIndexOutOfBoundsException:5> = 5
在java.util.Vector.elementAt(未知源)
在javax.swing.table.DefaultTableColumnModel.getColumn(未知源)
在javax.swing。 plaf.synth.SynthTableUI.paintCells(未知来源)
在javax.swing.plaf.synth.SynthTableUI.paint(未知来源)
在javax.swing.plaf.synth.SynthTableUI.update(未知来源)
在javax.swing.JComponent.paintComponent(未知源)
在javax.swing.JComponent.paint(未知源)
在javax.swing.JComponent.paintToOffscreen(未知来源)
在javax.swing.RepaintManager $ PaintManager.paintDoubleBuffered(未知源)
在javax.swing.RepaintManager $ PaintManager.paint(未知源)
在javax.swing.RepaintManager.paint(未知来源)
在j avax.swing.JComponent._paintImmediately(未知源)
在javax.swing.JComponent.paintImmediately(未知源)
在javax.swing.RepaintManager.paintDirtyRegions(未知源)
在javax。 swing.RepaintManager.paintDirtyRegions(未知源)
在javax.swing.RepaintManager.seqPaintDirtyRegions(未知来源)
在javax.swing.SystemEventQueueUtilities $ ComponentWorkRequest.run(未知来源)
在java。 awt.event.InvocationEvent.dispatch(未知源)
在java.awt.EventQueue.dispatchEvent(未知源)
在java.awt.EventDispatchThread.pumpOneEventForFilters(未知源)
在java。 awt.EventDispatchThread.pumpEventsForFilter(未知源)
在java.awt.EventDispatchThread.pumpEventsForHierarchy(未知源)
在java.awt.EventDispatchThread.pumpEvents(未知源)
在java.awt。 EventDispatchThread.pumpEvents(Unknown Source)
在java.awt.EventDispatch Thread.run(未知源)
线程AWT-EventQueue-0中的异常java.lang.ArrayIndexOutOfBoundsException:4> = 4
在java.util.Vector.elementAt(未知来源)
at javax.swing.table.DefaultTableColumnModel.getColumn(Unknown Source)
at sun.swing.SwingUtilities2.convertColumnIndexToModel(Unknown Source)
在javax.swing.JTable.convertColumnIndexToModel(未知来源)
javax.swing.JTable.getColumnClass(未知源)
在javax.swing.plaf.synth.SynthTableUI $ SynthTableCellRenderer.getTableCellRendererComponent(未知源)
在javax.swing.JTable.prepareRenderer(未知来源)
在javax.swing.plaf.synth.SynthTableUI.paintCell(未知源)
在javax.swing.plaf.synth.SynthTableUI.paintCells(未知源)
在javax.swing。 plaf.synth.SynthTableUI.paint(未知源)
在javax.swing.plaf.synth.SynthTableUI.update(未知源)
在javax.swing.JComponent paintComponent(未知源)
在javax.swing.JComponent.paint(未知源)
在javax.swing.JComponent.paintToOffscreen(未知源)
在javax.swing.RepaintManager $ PaintManager paintDoubleBuffered(未知源)
在javax.swing.RepaintManager $ PaintManager.paint(未知源)
在javax.swing.RepaintManager.paint(未知来源)
在javax.swing.JComponent ._paintImmediately(未知源)
在javax.swing.JComponent.paintImmediately(未知源)
在javax.swing.RepaintManager.paintDirtyRegions(未知源)
在javax.swing.RepaintManager.paintDirtyRegions (未知源)
在javax.swing.RepaintManager.seqPaintDirtyRegions(未知源)
在javax.swing.SystemEventQueueUtilities $ ComponentWorkRequest.run(未知来源)
在java.awt.event.InvocationEvent .dispatch(未知来源)
在java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(未知源)
在java.awt.EventDispatchThread.pumpEventsForFilter(未知源)
在java.awt.EventDispatchThread.pumpEventsForHierarchy(未知源)
在java。 awt.EventDispatchThread.pumpEvents(未知源)
在java.awt.EventDispatchThread.pumpEvents(未知来源)
在java.awt.EventDispatchThread.run(未知来源)


如果有帮助,这里是我的代码刷新表:

  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,
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);
返回;
}

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(条目< 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)
类[] columnTypes = new Class [] {Integer .class,String.class,
Object.class,Object.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.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://下载.oracle.com / javase / tutorial / uiswing / components / table.html#data ),如果您不确定该怎么做。对于你最重要的是getValueAt方法,它接受一行和一列,并返回该单元格应该包含的值。这就是你想要放置代码,看看你的Order对象并生成你想要的输出。



一旦你有你自定义的TableModel对象,只需传递一个新的当你第一次初始化它的时候,它的实例就是这个表的setModel方法。



一旦完成,你将要处理 em>模型刷新。要刷新表中的所有数据,您可以触发fireTableDataChanged事件。或者,您只能刷新表中实际需要更改的部分,而不是每次刷新整个事物。而不是在这里进入细微的细节,我只是指出你完美的Java教程页面: http://download.oracle.com/javase/tutorial/uiswing/components/table.html#fire


So I'm essentially trying to refresh my JTable every time a keystroke is hit, or when there's an update on the observer's part. Occasionally what I get is a frozen application and this stack trace...

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)

If it helps, here is my code for refreshing the table:

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, 
                                                   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, String.class, 
                                               Object.class, Object.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.setModel(dft);
    table.getColumnModel().getColumn(0).setPreferredWidth(40);
    table.getColumnModel().getColumn(1).setPreferredWidth(120);
}

For the record, I have tried wrapping it around in a try/catch, and no that will not help. I also have tried changing the default exception handler, and that has been unsuccessful as well.

解决方案

One of the biggest problems I can see is that you are not binding the table to your data then refreshing cells as they change, you are changing the whole data model out from under the table every time you press a key.

I'd hazard a guess that you're experiencing a "race" condition. You press a key, and that starts off the process of rebuilding your table and its model. Part way through that rebuild (remember, Swing uses threads, so the table update is still happening while you type,) you're going and triggering another rebuild, which changes the model out from under the first refresh which is still running. Of course, without seeing all of your code I can't be certain about that, but I can suggest a few things to make things a bit cleaner and less prone to concurrency issues.

Rather than writing code which takes your model data and translates it into a simple table model every key stroke, you can create your own table model class, and implement it to look directly at your model. That way you don't have the problem of constantly re-transferring data between your model and the array.

To make your own table model, you can just extend from the AbstractTableModel ( http://download.oracle.com/javase/6/docs/api/javax/swing/table/AbstractTableModel.html ). There's a great example in the original Java Tutorial ( http://download.oracle.com/javase/tutorial/uiswing/components/table.html#data ) if you're not sure how to go about it. The most important thing for you is the "getValueAt" method, which takes a row and a column and returns what value that cell should contain. That's where you want to put the code which looks at your "Order" object and produces the output you want.

Once you have your custom TableModel object, just pass a new instance of it into the "setModel" method of the table when you first initialize it.

Once that is done, you'll want to handle sensible model refreshes. To refresh all of the data in the table, you can trigger a "fireTableDataChanged" event. Alternatively, you can refresh only the parts of your table which actually need to be changed, not the whole thing every time. Rather than go into the fine grain details here, I'll just point you to the excellent Java Tutorial page on doing exactly that: http://download.oracle.com/javase/tutorial/uiswing/components/table.html#fire

这篇关于刷新JTable在Swing中提供异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆