我有一个包含多个组件的应用程序。其中之一是JTabbedPane带有其他内容的(显然)。我 只能 通过此getter 访问此窗格:
JTabbedPane
public JTabbedPane getPlotTabbedPane() { if (plotTabs == null) { plotTabs = new JTabbedPane(); plotTabs.setFocusable(false); plotTabs.add("Measurement", getPlotPanel()); plotTabs.add("Time", getPlotPanel().getTimePanel()); plotTabs.add("Data", getPlotPanel().getDataPanel()); plotTabs.add("Statistics", getPlotPanel().getStatisticsPanel()); plotTabs.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { getPlotPanel().refreshRenderer(); } }); } return plotTabs; }
因此,第一次访问它(即尚未创建时),然后再创建它,而在其他所有时间中,我只返回已经创建的JTabbedPane。我已经被告知这不是最好的技术(如果有人可以告诉我一种更好的方法而不弄乱布局组成代码,那么我很乐意接受建议)。
现在,在99%的情况下(应用程序启动),这可以正常工作。1%我得到一个
Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: -1 at java.util.Vector.elementAt(Vector.java:430) at javax.swing.JTabbedPane.getTitleAt(JTabbedPane.java:1091) at javax.swing.plaf.basic.BasicTabbedPaneUI$Handler.updateHtmlViews(BasicTabbedPaneUI.java:3564) at javax.swing.plaf.basic.BasicTabbedPaneUI$Handler.componentAdded(BasicTabbedPaneUI.java:3699) at java.awt.Container.processContainerEvent(Container.java:2065) at java.awt.Container.processEvent(Container.java:2036) at java.awt.Component.dispatchEventImpl(Component.java:4653) at java.awt.Container.dispatchEventImpl(Container.java:2097) at java.awt.Component.dispatchEvent(Component.java:4481) at java.awt.Container.addImpl(Container.java:1083) at javax.swing.JTabbedPane.insertTab(JTabbedPane.java:703) at javax.swing.JTabbedPane.addTab(JTabbedPane.java:777) at javax.swing.JTabbedPane.add(JTabbedPane.java:814) at companyname.product.gui.Tab.getPlotTabbedPane(Tab.java:386) at companyname.product.gui.Tab.getFullPlotPanel(Tab.java:374) at companyname.product.gui.Tab.initComponents(Tab.java:262) at companyname.product.gui.Tab.<init>(Tab.java:80)
我不会再深入探讨了,但这基本上是GUI的创建。Tab是扩展的JPanel。我无法真正弄清楚问题是什么,也无法采取预防措施。显然,我可以将Tab.java的386行包装在中try/catch,但这不能解决问题,而只能解决症状…
Tab
JPanel
try/catch
那么,您知道问题出在哪里,如何解决或应该怎么做?
堆栈跟踪似乎建议您从另一个线程然后从事件调度线程(EDT)访问Swing组件。这是不允许的。
我可以肯定的是,如果您确定只从正确的线程访问Swing组件,您将不再看到此异常。
可以在Swing的并发教程中找到更多信息。您还可以查看本文,其中包含RepaintManager可以帮助您检测到Swing线程违规的文章。
RepaintManager