如何在Swing中捕获此exception?

我有一个Swing应用程序,即使我在try / block拥有所有内容,也不会捕获exception。

 public static void main(String[] args) { try { App app = new App(); app.setVisible(true); } catch (Throwable e) { System.err.println("never printed"); } } 

我得到的就是这个堆栈跟踪:

 Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 9 >= 9 at java.util.Vector.elementAt(Vector.java:427) at javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:633) at javax.swing.JTable.getValueAt(JTable.java:2695) at javax.swing.JTable.prepareRenderer(JTable.java:5712) at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2075) at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:1977) at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1773) at javax.swing.plaf.ComponentUI.update(ComponentUI.java:143) at javax.swing.JComponent.paintComponent(JComponent.java:763) at javax.swing.JComponent.paint(JComponent.java:1027) at javax.swing.JComponent.paintChildren(JComponent.java:864) at javax.swing.JComponent.paint(JComponent.java:1036) at javax.swing.JViewport.paint(JViewport.java:747) at javax.swing.JComponent.paintChildren(JComponent.java:864) at javax.swing.JComponent.paint(JComponent.java:1036) at javax.swing.JComponent.paintChildren(JComponent.java:864) at javax.swing.JComponent.paint(JComponent.java:1036) at javax.swing.JComponent.paintChildren(JComponent.java:864) at javax.swing.JComponent.paint(JComponent.java:1036) at javax.swing.JLayeredPane.paint(JLayeredPane.java:564) at javax.swing.JComponent.paintChildren(JComponent.java:864) at javax.swing.JComponent.paintToOffscreen(JComponent.java:5129) at javax.swing.BufferStrategyPaintManager.paint (BufferStrategyPaintManager.java:277) at javax.swing.RepaintManager.paint(RepaintManager.java:1217) at javax.swing.JComponent.paint(JComponent.java:1013) at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21) at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60) at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97) at java.awt.Container.paint(Container.java:1780) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:714) at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:694) at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run (SystemEventQueueUtilities.java:128) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209) at java.awt.EventQueue.dispatchEvent(EventQueue.java:597) at java.awt.EventDispatchThread.pumpOneEventForFilters (EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter (EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy (EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) 

正如另一张海报所提到的,你的问题是exception被抛出在另一个线程中,即事件调度线程。 几个解决方案:

  • 在发生exception的实际代码周围放置一个try / catch:例如,如果它是响应ActionListener处理的按钮单击,则将try / catch放在actionPerformed()方法中;
  • 或者,将exception保留为未捕获的exception,并添加未捕获的exception处理程序 。 例如:
 Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { // ... do something with exception here ... } }); 

另外,原则上你应该在SwingUtilities.invokeLater()中使用你的UI启动代码。

Swing在事件调度线程中运行事物。 你试图在主线程中捕获它。

请注意,swing不是线程安全的,你也应该在事件调度线程中做事。

要捕获exception,可以从该堆栈跟踪中覆盖某些方法,例如组件中的paint方法。

对我来说,exception确实看起来像你应该修复的错误,而不是你应该通过捕捉隐藏的东西。

像ArrayIndexOutOfBoundsException这样的运行时exception显示程序员错误。 因此,更好的方法是修复它们而不是悄悄地咀嚼它。

只是对exception原因的疯狂猜测。 一旦JTable开始在屏幕上绘制数据,某些东西会同时从表模型的数据向量中删除行。

为了捕获从EDT内部抛出的exception,我所知道的唯一合适的方法是:

  • 编写自己的EventQueue(我一般不建议)
  • 使用Swing内部属性“ sun.awt.exception.handler ”(我使用它并且它至少适用于所有Sun JDK sun.awt.exception.handler和1.6,至少在IBM JDK 1.4和1.5上使用;我没有在其他上检查它JDK虽然)

您应该看看这个主题,以便更全面地了解解决方案的优缺点。

如上所述,问题在于抛出exception – 在事件派发线程上。

如果你想设置一个try / catch块来捕获这个特定的问题,我会把一个扔进App类的paint方法。 覆盖它并在那里的try catch块中调用super.paint。

如果您想要一种通用的方法来捕获未捕获的exception,请查看Thread.setUncaughtExceptionHandler 。 您可以使用exception处理程序调用该方法,并且可以处理应用程序中未捕获的所有exception。