JTable.removeColumn()方法会抛出异常。

3

如果只想在JTable上隐藏一列,我使用removeColumn()方法。但是它会抛出异常。

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 7 >= 7
at java.util.Vector.elementAt(Vector.java:470)
at javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:294)
at javax.swing.plaf.basic.BasicTableHeaderUI.paint(BasicTableHeaderUI.java:648)

我认为,在从视图中删除列之后,如果我修改了模型,那么就会出现此异常。这是因为视图中没有列,而模型正在更新表格吗?

在JTable中隐藏列的最佳方法是什么?而不是将大小设置为0。

编辑:异常并不经常发生。它是一种随机异常。无论如何,以下是代码:

    @Override
        protected Object doInBackground() throws Exception {
        ........
        resultDTO=//get data from database
        tableModel.setDataVector(resultDTO.getAllRows(), tableModel.getColumnNames());    
        // hide column
        table.removeColumn(table.getColumnModel().getColumn(7));
            System.out.println("table column count : " + table.getColumnCount());
            System.out.println("model column count : " + tableModel.getColumnCount());
        ........
        .........       
        }



initial result (with out any data in table, at application startup): 
table column count : 7
model column count : 8

after populating data (first running of above method):
table column count : 7
model column count : 8

after few times executing : 
table column count : 7
model column count : 8
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 7 >= 7
    at java.util.Vector.elementAt(Vector.java:470)
    at javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:294)
    at javax.swing.plaf.basic.BasicTableHeaderUI.paint(BasicTableHeaderUI.java:648)
    at javax.swing.plaf.synth.SynthTableHeaderUI.paint(SynthTableHeaderUI.java:173)

有时在首次加载数据时会出现上述异常,有时则没有。

我看到异常是在尝试绘制时从模型中抛出的。在您删除一个列并将其减少为7之后,模型仍然报告总共有8个列,这可能是可能的吗?实际上,这里没有太多信息供我们参考。 - arcy
看起来类似于[Bug ID:6586009](http://bugs.sun.com/view_bug.do?bug_id=6586009) - tenorsax
你尝试在EDT之外的模型中删除列了吗? - MadProgrammer
2个回答

1

您正在尝试在事件分发线程之外更新UI组件,这绝对不是一个好主意。

protected Object doInBackground() throws Exception {
    ........
    resultDTO=//get data from database
    // This shouldn't be done here
    tableModel.setDataVector(resultDTO.getAllRows(), tableModel.getColumnNames());  
    // and neither should this
    // hide column
    table.removeColumn(table.getColumnModel().getColumn(7));

使用SwingWorker值得赞赏。问题在于,Swing组件不是线程安全的,您永远不应该尝试在EDT之外更新它们,因为它们会导致意外的结果(就像您刚遇到的那样)。

我建议您使用publish/process方法来设置行数据,而不是直接设置。如果您无法确定何时删除列,则应在worker执行之前或worker的done方法中删除它。


好的,我只想了解一件关于Swing Worker的事情。如果在执行doInBackground()期间发生任何异常,会发生什么? - Sanjeev
@sanjeev 这是一个非常好的问题!doInBackground 是从 Callable 中调用的,而 Callable 又是由 ExecutorService 启动的...通常它们会被吸收...在执行后没有办法获取到对 Callable 的引用。但是,您可以在代码中添加 try/catch 块并捕获可能抛出的任何异常,然后维护一个稍后可以获取的引用,例如在 done 方法中。 - MadProgrammer

1

阅读关于SwingWorker的教程以及如何使用

  • process()

  • publish()

  • setProgress()

用于通知、添加、删除、修改Swing JComponentsdoInBackground()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接