JDK-8185854 : NPE on non-editable ComboBox in TabPane with custom Skin
  • Type: Bug
  • Component: javafx
  • Sub-Component: controls
  • Affected Version: 9,10
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2017-08-04
  • Updated: 2021-04-26
  • Resolved: 2018-04-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 Other
8u291Fixed openjfx11Fixed
Related Reports
Relates :  
Description
When running the test below a NPE is thrown when clicking in the grey comboBox. In the test custom skins for TabPane and ComboBox are set. Even if ComboBoxListViewSkin#setEditor is overriden, it does not appear in the stack trace - pretty weird. Tested with Java 9u175.

Test case:

import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class ComboSkinTest extends Application
{
  @Override
  public void start(Stage primaryStage)
  {
    Application.setUserAgentStylesheet(getClass().getResource("/test/css/style.css").toExternalForm());    
    Scene scene = new Scene(createContent(), 400, 400);
    primaryStage.setScene(scene);
    primaryStage.show();
  }

  public static void main(String[] args)
  {
    launch(args);
  }
  
  public Parent createContent()
  {
    final FlowPane comboPane = new FlowPane(10, 10);
    comboPane.getChildren().add(createComboBox(true, false));

    TabPane tabPane = new TabPane();
    addTab(tabPane, "ComboBox", comboPane);
    
    BorderPane p = new BorderPane();
    p.setCenter(tabPane);
    return p;
  }  
  
  private void addTab(TabPane tabPane, String name, Node content)
  {
    Tab tab = new Tab();
    tab.setText(name);
    tab.setContent(content);
    tabPane.getTabs().add(tab);    
  }

  private ComboBox<String> createComboBox(boolean readonly, boolean disabled)
  {
    ComboBox<String> combo = new ComboBox<String>();
    combo.setDisable(disabled);
    combo.setEditable(!readonly);
    return combo;      
  }  
}

import javafx.scene.control.TabPane;

public class TabPaneSkin extends javafx.scene.control.skin.TabPaneSkin
{
  public TabPaneSkin(TabPane tabPane)
  {
    super(tabPane);
  }   
}

public class ComboBoxListViewSkin<T> extends javafx.scene.control.skin.ComboBoxListViewSkin<T>
{
  public ComboBoxListViewSkin(ComboBox<T> comboBox)
  {
    super(comboBox);
  }
  
  @Override
  protected TextField getEditor()
  {
    return super.getEditor();
  }
 }


style.css:

.root {
  -fx-font: 11 Tahoma;
}

/******************************************************************************* 
 *                                                                             *
 * ComboBox                                                                    *
 *                                                                             *
 ******************************************************************************/

.combo-box{
    -fx-skin: "test.css.ComboBoxListViewSkin";
}

.combo-box-base{
    -fx-background-color: #CCC;
    -fx-background-radius: 4;
    -fx-padding: 0;
    -fx-border-insets: 0;
}

.combo-box-base:editable{	
    -fx-background-color: #FFF;
}

.combo-box-base:editable > .text-field {
    -fx-border-image-source: null;
    -fx-background-color: #EEE;
    -fx-padding: 1 0;
}

/*------------- combobox arrow -----------------------------------------------*/

.combo-box-base > .arrow-button > .arrow {
   -fx-padding: 4;
   -fx-background-position:center;
   -fx-background-size:auto;       
   -fx-shape: "M 0 0 H 7 L 3.5 4 z";
   -fx-background-color: #000;
}

/******************************************************************************* 
 *                                                                             *
 * TabPane                                                                     *
 *                                                                             *
 ******************************************************************************/
.tab-pane {
    -fx-skin: "test.css.TabPaneSkin";
    -fx-tab-min-height: 1.75em; /* 21 */
    -fx-tab-max-height: 1.75em; /* 21 */
    -fx-padding: 0;
}

Stack Trace:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
	at javafx.controls/javafx.scene.control.skin.ComboBoxListViewSkin.getEditor(ComboBoxListViewSkin.java:240)
	at javafx.controls/javafx.scene.control.skin.ComboBoxPopupControl.lambda$new$2(ComboBoxPopupControl.java:138)
	at javafx.base/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360)
	at javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
	at javafx.base/javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(ReadOnlyBooleanPropertyBase.java:72)
	at javafx.graphics/javafx.scene.Node$FocusedProperty.notifyListeners(Node.java:8132)
	at javafx.graphics/javafx.scene.Scene$12.invalidated(Scene.java:2186)
	at javafx.base/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
	at javafx.base/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
	at javafx.graphics/javafx.scene.Scene$KeyHandler.setFocusOwner(Scene.java:4043)
	at javafx.graphics/javafx.scene.Scene$KeyHandler.requestFocus(Scene.java:4090)
	at javafx.graphics/javafx.scene.Scene$KeyHandler.access$1700(Scene.java:4029)
	at javafx.graphics/javafx.scene.Scene.requestFocus(Scene.java:2150)
	at javafx.graphics/javafx.scene.Node.requestFocus(Node.java:8293)
	at javafx.controls/com.sun.javafx.scene.control.behavior.ComboBoxBaseBehavior.show(ComboBoxBaseBehavior.java:282)
	at javafx.controls/com.sun.javafx.scene.control.behavior.ComboBoxBaseBehavior.mouseReleased(ComboBoxBaseBehavior.java:240)
	at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
	at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
	at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
	at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
	at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3876)
	at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1300(Scene.java:3604)
	at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1874)
	at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2613)
	at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
	at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434)
	at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
	at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
	at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
	at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
	at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:189)
	at java.base/java.lang.Thread.run(Thread.java:844)
Comments
Looks good to me too. +1
13-04-2018

This looks good to me. +1
13-04-2018

Root Cause : ------------------ The test provided by [~wzberger] has unearthed an interesting issue with ComboBoxListViewSkin. With the test provided, the ComboBox custom skin creation through css results in ComboBoxListViewSkin constructor calling Node.applyCss() - which creates a default skin for ComboBox - So there are two skins created with listeners attached. This results in one of the skin returning null on getSkinnable() that gets invoked through listener. Calling sequence is : ComboBoxListViewSkin constructor -> updateButtonCell() -> updateDisplayArea() -> displayNode.applyCss() Fix: --- Avoid ComboBoxListViewSkin constructor creating another object of ComboBoxListViewSkin (indirectly through displayNode.applyCss()) Webrev : --------- http://cr.openjdk.java.net/~aghaisas/fx/8185854/webrev.0/ Request you to review.
04-04-2018