Josephus87
Josephus87

Reputation: 1178

JavaFX Confusing Stacktrace

My JavaFx app throwing an exception and does not point towards a single line of my own code. What does this mean?

It is confusing me because I encountered it a few times now without being able to reproduce. Once at booting, once at being idle (minimized) and returning back to the app, once at being idle (but still shown on screen) and returning back to the app.

The full code is too long, I can post little snippets that operate in the configuration. And some links to the complete app to get an overview what Im trying to make.

enter image description here

https://www.youtube.com/watch?v=Oev1IJZvAPw

https://github.com/JoostMeulenkamp/VPL

Snippet 1 (calculate function of a node that adds an item to the end of a list):

@Override
public void calculate() {

    //Get incoming data
    Object raw = inPorts.get(0).getData();
    Object item = inPorts.get(1).getData();

    //Finish calculate if there is no incoming data
    if (raw == null) {
        return;
    }

    //Check if all incoming data is in the correct format
    boolean hasError = false;
    if (!(raw instanceof List)) {
        System.out.println("This is not a list");
        hasError = true;
    }
    if (item instanceof List) {
        System.out.println("Just one item can be added at a time");
        hasError = true;
    }
    if (inPorts.get(1).connectedConnections.size() > 0
            && inPorts.get(0).connectedConnections.size() > 0) {
        Class listDataType = inPorts.get(0).connectedConnections.get(0).getStartPort().dataType;
        Class itemDataType = inPorts.get(1).connectedConnections.get(0).getStartPort().dataType;
        if (itemDataType.isAssignableFrom(listDataType)) {
            System.out.println("Element is not of same type as the list's");
            hasError = true;
        }
    }
    if (hasError) {
        return;
    }

    //Add item to end
    List source = (List) raw;

    //Create a new list when autoCheckBox is checked, otherwise add to existing 
    //HACK new list is created that is identical because otherwise data is not forwarded
    //When isClicked, check changes to empty circle
    if (this.autoCheckBox.isClicked()) {
        source.add(item);
        List target = new ArrayList();
        target.addAll(source);

        //Set outgoing data
        outPorts.get(0).setData(target);

    } else {
        List target = new ArrayList();
        target.addAll(source);
        target.add(item);

        //Set outgoing data
        outPorts.get(0).setData(target);
    }

}

Snippet 2 Calculate function of a node that outputs lists to a textfield.

    @Override
    public void calculate() {
        //Get controls and data
        TextArea area = (TextArea) controls.get(0);
        Object data = inPorts.get(0).getData();
        area.setText("");

        //Do Action
        if (inPorts.get(0).getData() != null && inPorts.get(0).connectedConnections.size() > 0) {
            //Set data type corresponding to source
            outPorts.get(0).dataType = inPorts.get(0).connectedConnections.get(0).getStartPort().dataType;
            outPorts.get(0).setName(inPorts.get(0).connectedConnections.get(0).getStartPort().getName());
            if (data instanceof List) {
                List list = (List) data;

                for (Object object : list) {
                    if (object == null) {
                        area.appendText("null");
                    } else {
                        area.appendText(object.toString() + "\n");
                    }
                }
            } else {
                area.setText(data.toString());
            }
        } else {
            //Set data type back to string
            outPorts.get(0).dataType = String.class;
            outPorts.get(0).setName("String");
            if (inPorts.get(0).isActive()) {
                area.setText("null");
            } else {
                area.setText("");
            }
        }

        //Set Data
        outPorts.get(0).setData(data);

//        System.out.println(outPorts.get(0).dataType);
    }

This exception stacktrace keeps repeating itself:

    Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException: -1
    at java.util.ArrayList.elementData(ArrayList.java:418)
    at java.util.ArrayList.get(ArrayList.java:431)
    at javafx.scene.Parent.updateCachedBounds(Parent.java:1591)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1535)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3559)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.updateCachedBounds(Parent.java:1596)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1535)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.impl_computeLayoutBounds(Node.java:3376)
    at javafx.scene.Group.impl_computeLayoutBounds(Group.java:165)
    at javafx.scene.Node$12.computeBounds(Node.java:3225)
    at javafx.scene.Node$LazyBoundsProperty.get(Node.java:9308)
    at javafx.scene.Node$LazyBoundsProperty.get(Node.java:9278)
    at javafx.scene.Node.getLayoutBounds(Node.java:3240)
    at javafx.scene.layout.AnchorPane.layoutChildren(AnchorPane.java:328)
    at javafx.scene.Parent.layout(Parent.java:1087)
    at javafx.scene.Scene.doLayoutPass(Scene.java:552)
    at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2397)
    at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
    at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:381)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:748)

Upvotes: 1

Views: 298

Answers (1)

Josephus87
Josephus87

Reputation: 1178

As James_D stated:

These kinds of errors can arise in some circumstances if you try to update UI elements from a background thread.

Every UI changing method is now called from the FX thread by Platform.runLater().

Upvotes: 1

Related Questions