Swing JTabbedPane генерирует IndexOutOfBoundsException при заполнении

У меня есть приложение с несколькими компонентами. Одним из них является 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)

Я не буду идти дальше по стеку, но это в основном создание графического интерфейса. Tab это расширенный JPanel, Я не могу понять, в чем проблема, и что я могу сделать, чтобы предотвратить это. Очевидно, я мог бы просто обернуть строку 386 из Tab.java в try/catch, но это не решает проблему, оно просто решает симптомы...

Итак, вы знаете, в чем проблема, как я могу ее решить или как мне это делать?

1 ответ

Решение

Похоже, что трассировка стека предлагает вам доступ к компонентам Swing из другого потока, а не из потока диспетчеризации событий (EDT). Это не разрешено

Я совершенно уверен, что если вы убедитесь, что обращаетесь к компонентам Swing только из правильного потока, вы больше не увидите это исключение.

Более подробную информацию можно найти в учебнике по параллелизму в Swing. Вы также можете взглянуть на эту статью, которая содержит RepaintManager которая может помочь вам обнаружить нарушения потоков Swing

Другие вопросы по тегам