6
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);
    }
  }
}

When setTheme() is called, this causes this to occur repeatedly (presumably for each component):

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)

Commenting out the line 'setTabComponentAt(getTabCount() - 1, panel);' stops the exception from being thrown (but this, of course, breaks the UI), as does overriding updateUI() in the TabbedArea class and wrapping super.updateUI() in SwingUtilities.invokeLater(..).

This appears to be similar to a bug that the jEdit team had with one of their plugins when updating the L&F. However, their solution was simply to not update the application's look and feel during runtime and to rely on a restart to do it.

Anyone have any ideas how this can be solved without needing a restart to change the look and feel?

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
Misha Griffiths
  • 228
  • 2
  • 9
  • Swing is not thread-safe, so you have to change the UI in the Event Dispatch Thread. Does wrapping implementation of `setTheme` into `SwingUtilities.invokeLater(...)` fix the issue? – Alexey Ivanov Aug 30 '11 at 20:48
  • What JRE are you using, and what L&Fs are you using? – wolfcastle Sep 20 '11 at 02:55

1 Answers1

1

Looking at the source for Java 6 I found line 263 of BasicTabbedPaneUI is a return statement:

        /* 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);
        }

The only thing that can cause your NPE is that tabPane reference is null. Without more info all I can guess is that you've removed a tab component without removing the corresponding tab.

RichW
  • 2,004
  • 2
  • 15
  • 24