在L& F更改时,validate()树会抛出NullPointerException吗?

时间:2010-11-18 17:29:18

标签: java nullpointerexception jtabbedpane

public class TabbedArea extends JTabbedPane {
  public void addArea(){
    add(component);
    final JPanel panel = new JPanel(new BorderLayout());
    panel.add(new JLabel(title), BorderLayout.LINE_START);
    JButton closeButton = new JButton(new CloseIcon());
    closeButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        removeArea(subAreas.get(indexOfTabComponent(panel)));
      }
    });
    panel.add(closeButton, BorderLayout.LINE_END);

    setTabComponentAt(getTabCount() - 1, panel);
  }
}

public class LnFManager {
  public void setTheme(PlasticTheme theme){
    for (Window window : Window.getWindows()) {
      if (window.isDisplayable())
        SwingUtilities.updateComponentTreeUI(window);
    }
  }
}

当调用setTheme()时,会导致重复发生(大概是每个组件):

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
 at javax.swing.plaf.basic.BasicTabbedPaneUI.scrollableTabLayoutEnabled(BasicTabbedPaneUI.java:263)
 at javax.swing.plaf.basic.BasicTabbedPaneUI.access$400(BasicTabbedPaneUI.java:54)
 at javax.swing.plaf.basic.BasicTabbedPaneUI$TabContainer.doLayout(BasicTabbedPaneUI.java:3850)
 at java.awt.Container.validateTree(Container.java:1568)
 at java.awt.Container.validateTree(Container.java:1575)
 at java.awt.Container.validateTree(Container.java:1575)
 at java.awt.Container.validateTree(Container.java:1575)
 at java.awt.Container.validateTree(Container.java:1575)
 at java.awt.Container.validate(Container.java:1540)
 at javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1227)
 at flextrade.tca.ui.LnFManager.setTheme(LnFManager.java:113)
 at flextrade.tca.ui.ToolBar$15.actionPerformed(ToolBar.java:803)
 at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2012)
 at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2335)
 at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:404)
 at javax.swing.JToggleButton$ToggleButtonModel.setPressed(JToggleButton.java:308)
 at javax.swing.AbstractButton.doClick(AbstractButton.java:374)
 at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:829)
 at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:873)
 at java.awt.Component.processMouseEvent(Component.java:6108)
 at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
 at java.awt.Component.processEvent(Component.java:5873)
 at java.awt.Container.processEvent(Container.java:2105)
 at java.awt.Component.dispatchEventImpl(Component.java:4469)
 at java.awt.Container.dispatchEventImpl(Container.java:2163)
 at java.awt.Component.dispatchEvent(Component.java:4295)
 at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4461)
 at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4125)
 at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4055)
 at java.awt.Container.dispatchEventImpl(Container.java:2149)
 at java.awt.Window.dispatchEventImpl(Window.java:2478)
 at java.awt.Component.dispatchEvent(Component.java:4295)
 at java.awt.EventQueue.dispatchEvent(EventQueue.java:604)
 at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
 at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
 at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
 at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
 at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
 at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)

注释掉'setTabComponentAt(getTabCount() - 1,panel);'停止抛出异常(当然,这会打破UI),就像重写TabbedArea类中的updateUI()并在SwingUtilities.invokeLater(..)中包装super.updateUI()一样。

这似乎与jEdit团队在更新L& F时对其中一个插件的bug相似。但是,他们的solution只是在运行时没有更新应用程序的外观,而是依赖重启来完成它。

任何人都有任何想法如何解决这个问题,而无需重新启动来改变外观?

1 个答案:

答案 0 :(得分:1)

查看Java 6的源代码我发现BasicTabbedPaneUI的第263行是一个return语句:

        /* In an attempt to preserve backward compatibility for programs
         * which have extended BasicTabbedPaneUI to do their own layout, the
         * UI uses the installed layoutManager (and not tabLayoutPolicy) to
         * determine if scrollTabLayout is enabled.
         */
        private boolean scrollableTabLayoutEnabled() {
            return (tabPane.getLayout() instanceof TabbedPaneScrollLayout);
        }

唯一可能导致您的NPE的是tabPane引用为null。如果没有更多信息,我可以猜测你已经删除了一个标签组件而没有删除相应的标签。