Swing JTabbedPane lança IndexOutOfBoundsException durante o preenchimento

Eu tenho um aplicativo com vários componentes. Um deles é um JTabbedPane com outras coisas nele (obviamente). Eu access este painel apenas através deste getter:

 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; } 

Então, da primeira vez, eu acessei (ou seja, quando ainda não foi criado), eu criei, todas as outras vezes, eu apenas JTabbedPane já criado. Já me disseram que essa não é a melhor técnica (se alguém puder me dizer uma melhor que não atrapalhe o código da composição do layout, estou muito aberto a sugestões).

Agora, isso funciona perfeitamente bem – digamos – 99% dos casos (o aplicativo é iniciado). Em 1% eu recebo um

 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.(Tab.java:80) 

Eu não vou mais longe na pilha, mas isso é basicamente a criação da GUI. Tab é um JPanel estendido. Eu não consigo descobrir, qual é o problema nem o que posso fazer para evitar isso. Obviamente, eu poderia simplesmente quebrar a linha 386 do Tab.java em um try/catch , mas isso não resolve o problema, apenas resolve os sintomas …

Então, você sabe qual é o problema, como posso resolvê-lo ou como devo fazer isso?

O stacktrace parece sugerir que você acessar componentes Swing de outro thread, em seguida, o segmento de expedição de events (EDT). Isso não é permitido.

Tenho certeza de que você garantiria que acessasse apenas os componentes do Swing do thread correto, e você não verá mais essa exceção.

Mais informações podem ser encontradas no tutorial concurrency no Swing . Você também pode dar uma olhada neste artigo que contém um RepaintManager que pode ajudá-lo a detectar violações de threads do Swing