brimborium
brimborium

Reputation: 9522

Swing JTabbedPane throws IndexOutOfBoundsException while filling up

I have an application with several components. One of them is a JTabbedPane with other stuff in it (obviously). I access this pane only via this 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;
}

So the first time, I access it (i.e. when it is not yet created), I create it, all the other times, I just give back the already created JTabbedPane. I was already told that this is not the best technique (if somebody can tell me a better one that does not mess up the layout composition code, I am very open to suggestions).

Now, this works perfectly fine in - let's say - 99% of the cases (application starts). In 1% I get a

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)

I won't go further down the stack, but this is basically the creation of the GUI. Tab is a extended JPanel. I can not really figure out, what the problem is nor what I can do to prevent it. Obviously, I could just wrap line 386 of Tab.java in a try/catch, but that doesn't solve the problem, it just solves the symptoms...

So, do you know what's the problem, how I can solve it or how I should do that stuff?

Upvotes: 1

Views: 761

Answers (1)

Robin
Robin

Reputation: 36621

The stacktrace seems to suggest you access Swing components from another thread then the Event Dispatch Thread (EDT). This is not allowed.

I am pretty certain if you would make sure you only access Swing components from the correct thread you won't see this exception anymore.

More information can be found in the Concurrency in Swing tutorial. You can also take a look at this article which contains a RepaintManager which can help you to detect Swing threading violations

Upvotes: 3

Related Questions