隐藏javaFX ColorPicker会导致NullPointerException

时间:2017-03-30 01:19:03

标签: java javafx lambda javafx-8

在我的分形图像生成程序中,我允许用户通过显示javafx.scene.control.ColorPicker来编辑屏幕图像的颜色,如下面的代码所示。

在顶部我设置了一个事件处理程序,允许用户隐藏ColorPicker和GridPane包装它。从某种意义上说,这可以发生预期的行为,但同时JVM会抛出NullPointerException。堆栈跟踪主要是指javafx类,而不是我执行的类。

我已经玩过代码并搜索了stackoverflow等等,但是这个让我很难过。

有人可以帮我诊断病因吗? (代码和堆栈跟踪如下。)

scene.setOnKeyPressed(ev2 -> {
    if (ev2.getCode().equals(KeyCode.ENTER)) {
        System.out.println("\nEnter pressed, panel should hide...");
        huePanel.setVisible(false);     // press Enter to kill panel
        huePanel.getChildren().clear();
        root.getChildren().removeAll(huePanel);
    }
});     

huePanel = new GridPane();
huePanel.setAlignment(Pos.TOP_CENTER);
root.getChildren().addAll(huePanel);
int cl = colours[colourscheme].length;
Rectangle[] squares = new Rectangle[cl];
ColorPicker[] pickers = new ColorPicker[cl];

for (int i = 0; i < cl; i++) {
    int squareSize = width / 20;
    squares[i] = new Rectangle(squareSize, squareSize, colours[colourscheme][i]);
    squares[i].setStroke(BLACK);
    squares[i].setStrokeWidth(2.0);
    GridPane.setRowIndex(squares[i], (i / 8) * 2);
    GridPane.setColumnIndex(squares[i], i % 8);

    pickers[i] = new ColorPicker(colours[colourscheme][i]);
    GridPane.setRowIndex(pickers[i], (i / 8) * 2 + 1);
    GridPane.setColumnIndex(pickers[i], i % 8);

    huePanel.getChildren().addAll(squares[i], pickers[i]);
}
for (int j = 0; j < cl; j++) {
    indexOfColourToModify = j;
    pickers[j].setOnAction(ev1 -> {
            ColorPicker cp = (ColorPicker)(ev1.getSource());
            int k = huePanel.getChildren().indexOf(cp) / 2;     // really (idx-1)/2, as idx is odd
                                                                // due to squares[]
            Color c = cp.getValue();
            colours[colourscheme][k] = c;
            huePanel.requestLayout();
            System.out.println("\ncolours[" + colourscheme + "][" + k + "] set to " + c);
            paintImage(screenImage[screenImageIndex], realMinIts, realMaxIts);
        }
    );
}

=============================================== ==========================

Enter pressed, panel should hide...
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at com.sun.javafx.scene.control.skin.ComboBoxPopupControl.positionAndShowPopup(ComboBoxPopupControl.java:197)
    at com.sun.javafx.scene.control.skin.ComboBoxPopupControl.show(ComboBoxPopupControl.java:170)
    at com.sun.javafx.scene.control.skin.ColorPickerSkin.show(ColorPickerSkin.java:464)
    at com.sun.javafx.scene.control.skin.ComboBoxBaseSkin.handleControlPropertyChanged(ComboBoxBaseSkin.java:127)
    at com.sun.javafx.scene.control.skin.ColorPickerSkin.handleControlPropertyChanged(ColorPickerSkin.java:470)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase.lambda$registerChangeListener$61(BehaviorSkinBase.java:197)
    at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler$1.changed(MultiplePropertyChangeListenerHandler.java:55)
    at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
    at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(ReadOnlyBooleanPropertyBase.java:72)
    at javafx.beans.property.ReadOnlyBooleanWrapper.fireValueChangedEvent(ReadOnlyBooleanWrapper.java:103)
    at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
    at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:144)
    at javafx.scene.control.ComboBoxBase.setShowing(ComboBoxBase.java:185)
    at javafx.scene.control.ComboBoxBase.show(ComboBoxBase.java:391)
    at com.sun.javafx.scene.control.behavior.ComboBoxBaseBehavior.show(ComboBoxBaseBehavior.java:286)
    at com.sun.javafx.scene.control.behavior.ColorPickerBehavior.callAction(ColorPickerBehavior.java:82)
    at com.sun.javafx.scene.control.behavior.BehaviorBase.callActionForEvent(BehaviorBase.java:218)
    at com.sun.javafx.scene.control.behavior.ComboBoxBaseBehavior.callActionForEvent(ComboBoxBaseBehavior.java:136)
    at com.sun.javafx.scene.control.behavior.BehaviorBase.lambda$new$74(BehaviorBase.java:135)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$KeyHandler.process(Scene.java:3964)
    at javafx.scene.Scene$KeyHandler.access$1800(Scene.java:3910)
    at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040)
    at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:217)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:149)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$353(GlassViewEventHandler.java:248)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:247)
    at com.sun.glass.ui.View.handleKeyEvent(View.java:546)
    at com.sun.glass.ui.View.notifyKey(View.java:966)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139)
    at java.lang.Thread.run(Thread.java:745)

2 个答案:

答案 0 :(得分:0)

根据我的猜测 - 我没有从堆栈和你的代码中看到太多,除了它试图:

_popup.show(comboBoxBase.getScene().getWindow(),
                snapPosition(p.getX()),
                snapPosition(p.getY())); 

这可能是由于传播事件造成的。

如果您的ColorPicker具有焦点,则Enter将对其进行操作,但此时,它已从场景中删除。

尝试:

scene.setOnKeyPressed(ev2 -> {
    if (ev2.getCode().equals(KeyCode.ENTER)) {
        System.out.println("\nEnter pressed, panel should hide...");
        huePanel.setVisible(false);     // press Enter to kill panel
        huePanel.getChildren().clear();
        root.getChildren().removeAll(huePanel);
        ev2.consume();
    }
}); 

答案 1 :(得分:0)

我发现在Java 9(build 9.0.1 + 11)下不再抛出此异常。代码按预期工作。

所以我猜这是某种Java / JavaFX错误。