дерево validate () создает исключение NullPointerException при изменении L & F? - PullRequest
6 голосов
/ 18 ноября 2010
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, панель);' останавливает выдачу исключения (но это, конечно, нарушает пользовательский интерфейс), так же как и переопределение updateUI () в классе TabbedArea и перенос super.updateUI () в SwingUtilities.invokeLater (..).

Это похоже на ошибку , которую команда jEdit имела с одним из своих плагинов при обновлении L & F. Однако их решение состояло просто в том, чтобы не обновлять внешний вид приложения во время выполнения и полагаться на перезапуск, чтобы сделать это.

У кого-нибудь есть идеи, как это можно решить без перезапуска, чтобы изменить внешний вид?

1 Ответ

1 голос
/ 22 сентября 2011

Глядя на источник для Java 6, я обнаружил, что строка 263 BasicTabbedPaneUI является оператором возврата:

        /* 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 пуста. Без дополнительной информации я могу предположить, что вы удалили компонент вкладки, не удаляя соответствующую вкладку.

...