使用 JTabbedPane 时抛出异常

发布于 2024-08-30 15:38:34 字数 3511 浏览 3 评论 0原文

我在应用程序中使用 JTabbedPane,并使用 ChangeListener 监听其更改,以便我可以知道当前选择了哪个选项卡。 所以我的 stateChanged 方法是;

public void stateChanged(ChangeEvent e) {
    currentPageIndex = jTabbedPane.getSelectedIndex();
}

但是,当我向 JTabbedPane 添加新选项卡时,它在上面的方法中抛出 ArrayIndexOutOfBoundsException ,我不知道为什么。有些人建议类似的情况,这是一个错误 https://bugs.java.com /bugdatabase/view_bug?bug_id=4873983,但正如您将看到的,有人说解决方案是使用 EventDispatchThread 中的 Swing。

这是什么意思,它们是指 SwingUtilities.invokeLater 吗?有人可以告诉我如何相应地修改我的 stateChanged 方法以避免异常吗?

编辑:下面是我的 addTab() 方法。这在程序开始时被多次调用,并且“有时”会触发 stateChanged() 方法。在某些时候,stateChanged() 会导致异常。这就是我到目前为止可以从调试器中得知的。我知道这看起来不太清楚,所以如果您以前没有听说过这种事情,没关系,感谢您的努力。但我认为这可能与我上面给出的链接有关。

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:抛出此异常。在我的方法实际执行完毕并完成所有操作后,会触发一个 actionPerformed() ,然后是一大堆东西,然后是异常。

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.EventDispatchThread.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)

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 https://bugs.java.com/bugdatabase/view_bug?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.EventDispatchThread.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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浮生未歇 2024-09-06 15:38:34

最可能的答案是您正在从非 EDT 线程更改 Swing 中的某些内容。任何涉及 Swing 组件或 Swing 组件使用的模型的内容都必须在 EDT 上执行。这包括 Swing 对象和模型的构造。

找到此类非 EDT 操作的最简单方法就是使用 Substance 外观和感觉运行。转至 Substance 网站,然后单击“获取”。下载 Substance 和 Trident 库,将它们添加到您的类路径中,然后使用选项

-Dswing.defaultlaf=org.pushingpixels.substance.api.skin.SubstanceBusinessLookAndFeel

Substance is very adamant that swing actions 在 EDT 上发生来启动 JVM。如果您在另一个线程执行某些操作,它将引发异常。最好的部分是,由于异常发生在调度任何事件之前,因此有问题的代码仍在堆栈上。这可以让您了解错误真正发生的位置,而不是尝试通过多个 PumpEvent 堆栈进行回溯。

注意: Substance 不能替代仔细的编码。在某些情况下,它可能无法检测到模型的非 EDT 更改。物质只会让事情变得更容易。

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.

睡美人的小仙女 2024-09-06 15:38:34

我建议启动调试器并逐步执行代码,直到到达抛出异常的位置。看看是什么值导致了这种情况,然后开始逆向工作。

从您发布的三行代码可以看出。是

currentPageIndex = jTabbedPane.getSelectedIndex();

您的侦听器实现的数据成员吗?

您传入的 index 的值是多少?

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?

谎言 2024-09-06 15:38:34

您没有发布 SSCCE。 5 行代码不是 SSCCE。

一方面,您不应该使用 updateUI() 方法。我不知道为什么我在发布的代码中经常看到这种情况。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文