Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

validate() tree throws NullPointerException on L&F change?

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?

like image 953
Misha Griffiths Avatar asked Nov 18 '10 17:11

Misha Griffiths


1 Answers

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.

like image 67
RichW Avatar answered Oct 04 '22 20:10

RichW