I'm using a JTabbedPane in my application and I listen to its changes with ChangeListener
so that I can know which tab is currently selected.
So my stateChanged
method is;
public void stateChanged(ChangeEvent e) {
currentPageIndex = jTabbedPane.getSelectedIndex();
}
But while I'm adding new tabs to the JTabbedPane
it throws an ArrayIndexOutOfBoundsException
in the method above, I don't know why. Some suggested for a similar case that this is a bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4873983, but as you'll see some says the solution is to work with Swing from EventDispatchThread.
What does it mean, do they mean the SwingUtilities.invokeLater
thing? Can someone show me how I can modify my stateChanged
method accordingly to avoid the exception?
Edit: And below is my addTab()
method. This is called multiple times at the beginning of the program, and it 'sometimes' fires stateChanged()
method. And at some point stateChanged()
causes the exception. That's what I could tell from the debugger up to now. I know it doesn't seem clear, so if you haven't already heard this kind of thing before, that's OK, thanks for your effort. But I think this could be related to the link I gave above.
void addTab(EJournal eJournalModel,int index, String pageName) {
SectionPage newPage = new SectionPage(jTabbedPane.getSize(), controller, eJournalModel.getSections().get(currentPageIndex));
JScrollPane scrollPane = new JScrollPane(newPage);
scrollPanes.add(index, scrollPane);
sectionPages.add(index, newPage);
jTabbedPane.insertTab(pageName, idleIcon, scrollPane, null, index);
jTabbedPane.updateUI();
}
Edit2 : This exception is thrown. After my methods actually finished executing and evertying is finished, an actionPerformed()
is fired, then a whole bunch of stuff and then exception.
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
at javax.swing.plaf.basic.BasicTabbedPaneUI.tabForCoordinate(BasicTabbedPaneUI.java:1488)
at javax.swing.plaf.basic.BasicTabbedPaneUI.setRolloverTab(BasicTabbedPaneUI.java:558)
at javax.swing.plaf.basic.BasicTabbedPaneUI.access$2000(BasicTabbedPaneUI.java:37)
at javax.swing.plaf.basic.BasicTabbedPaneUI$Handler.mouseEntered(BasicTabbedPaneUI.java:3604)
at java.awt.Component.processMouseEvent(Component.java:6272)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3255)
at java.awt.Component.processEvent(Component.java:6028)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4630)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
at java.awt.LightweightDispatcher.trackMouseEnterExit(Container.java:4363)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4220)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
at java.awt.Container.dispatchEventImpl(Container.java:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2475)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchTh开发者_如何学Goread.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)
The most likely answer is you are altering something in Swing from a non-EDT thread. Anything that touches a Swing component, or a model used by a Swing component must execute on the EDT. This includes construction of Swing objects and models.
The hands-down easiest way to find these sort of non-EDT actions is to run with the Substance Look and Feel. Go to the Substance web site and click "Get". Download the Substance and Trident libraries, add them to your classpath, then start your JVM with the option
-Dswing.defaultlaf=org.pushingpixels.substance.api.skin.SubstanceBusinessLookAndFeel
Substance is very adamant that swing actions take place on the EDT. It will throw an exception if you do something another thread. Best part is that since the exception occurs before any event is dispatched the offending code is still on the stack. This lets you where the error really happened instead trying to backtrack through multiple pumpEvent
stacks.
Note: Substance is not a replacement for careful coding. There are cases where it can fail to detect non-EDT changes to models. Substance just makes it easier.
I'd recommend firing up a debugger and stepping through your code until you reach the point where the exception is thrown. See what value is causing this and start working backwards.
It's possible to tell from the three lines of code that you've posted. Is
currentPageIndex = jTabbedPane.getSelectedIndex();
a data member of your Listener implementation?
What's the value of the index
that you're passing in?
You did not post a SSCCE. 5 lines of code is NOT a SSCCE.
For one thing you should NOT be using the updateUI() method. I have no idea why I see this so often in posted code.
精彩评论