【问题标题】:How do I catch this exception in Swing?如何在 Swing 中捕获此异常?
【发布时间】:2010-10-18 22:22:20
【问题描述】:

我有一个 Swing 应用程序,即使我在 try/block 中有所有内容,也没有捕获到异常。

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)

【问题讨论】:

  • 我猜你在某个地方有一个网格

标签: java swing exception


【解决方案1】:

正如另一张海报所提到的,您的问题是在另一个线程中引发了异常,即事件调度线程。几个解决方案:

  • 在发生异常的实际代码周围放置一个 try/catch:例如如果它是对 ActionListener 处理的按钮单击的响应,请将 try/catch 放在您的 actionPerformed() 方法中;
  • 或者,将异常保留为未捕获的异常,并添加uncaught exception handler。例如:

    Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
      public void uncaughtException(Thread t, Throwable e) {
        // ... do something with exception here ...
      }
    });

顺便说一句,原则上您应该将 UI 启动代码放在 SwingUtilities.invokeLater() 中。

【讨论】:

  • 真的有人使用 Thread.setDefaultUncaughtExceptionHandler() 捕获到 EDT 中抛出的任何异常吗?我严重怀疑(至少在 JDK5 上,没有在 JDK6 上检查),因为 EDT 自己捕获所有异常,只是向 System.err 发出 printStackTrace()。
  • 至少在 JDK 6 中,它似乎“正确地”通过了未捕获的异常处理程序。我承认我没有意识到这在 5 和 6 之间发生了变化,但也许。
  • 我现在真的能够捕捉到异常了。(使用 jdk1.6。)
  • 在以前的 jdk 版本中,您必须使用非官方的技巧 - 使用您的处理程序设置“sun.awt.exception.handler”属性。像这样的东西: System.setProperty("sun.awt.exception.handler",ExceptionHandler.class.getName()); public class ExceptionHandler { public void handle(Throwable ex) { ... } } 这个技巧仍然有效(直到 java 6),但它可能在未来的版本中无效。
  • 我知道在事件调度线程上捕获未处理异常的唯一方法是注册一个新的 EventQueue,如 here 所述。使用Thread.setDefaultUncaughtExceptionHandler() 将不起作用。
【解决方案2】:

Swing 在事件分派线程中运行事物。您正试图在主线程中捕获它。

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

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

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

【讨论】:

【解决方案3】:

像 ArrayIndexOutOfBoundsException 这样的运行时异常表明了程序员的错误。因此,修复它们可能会更好,而不是捕捉并默默咀嚼它。

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

【讨论】:

  • 你是对的,但我正在使用为我咀嚼异常的库。因此,当绘制表格时,我得到了异常。但无论如何,我想知道我能做什么。我可能修复了不确定的库。
【解决方案4】:

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

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

您应该查看this thread,以更全面地了解解决方案及其优缺点。

【讨论】:

    【解决方案5】:

    如上所述,问题在于异常被抛出的位置 - 在事件调度线程上。

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

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

    【讨论】:

      猜你喜欢
      • 2011-10-17
      • 1970-01-01
      • 1970-01-01
      • 2014-07-08
      • 2013-09-20
      • 2017-09-09
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      相关资源
      最近更新 更多