javafx компилируется, но не запускается

Вот код. Eclipse не выдаёт никаких ошибок на стадии компиляции. Всё по идее норм, но когда запускаю выдаёт ошибки.

package Asteroids.space;

import java.util.HashSet;
import java.util.Set;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Shape;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
import javafx.scene.shape.Polygon;


/**
 * JavaFX App
 */
public class App extends Application {
    
    Point2D size = new Point2D(1000, 800);
    Set<KeyCode> keysDown = new HashSet<>();
    int key (KeyCode k) {
        return keysDown.contains(k) ? 1 : 0;
    }

    @Override
    public void start(Stage stage) {
        Group gRoot = new Group();
        Scene scene = new Scene(gRoot, size.getX(), size.getY());
        
        stage.setScene(scene);
        stage.setTitle("Asteroids");
        scene.setFill(Color.BLACK);
        
        Label fpsLabel = new Label();
        fpsLabel.setTranslateX(2);
        fpsLabel.setTextFill(Color.WHITE);
        
        Group gGame = new Group();
        Ship ship = new Ship(gGame, size.multiply(0.5));
        gRoot.getChildren().addAll(gGame, fpsLabel);
        
        scene.setOnKeyPressed(new EventHandler<KeyEvent>() {

            @Override
            public void handle(KeyEvent event) {
                keysDown.add(event.getCode());              
            }
        });
        
        scene.setOnKeyReleased(new EventHandler<KeyEvent>() {

            @Override
            public void handle(KeyEvent event) {
                keysDown.remove(event.getCode());               
            }
        });
        
        AnimationTimer loop = new AnimationTimer() {
        double old = -1;
        double elapsedTime = 0;
            
            @Override
            public void handle(long nano) {
                if (old < 0) old = nano;
                double delta = (nano - old) / 1e9;

                old = nano;
                elapsedTime += delta;

                fpsLabel.setText(String.format("%.2f %.2f", 1/delta, elapsedTime));
                System.out.println(keysDown);
                
            }
        };
        loop.start();       
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}
    
    abstract class PhisicsObject {
        Point2D p, v;
        double theta, omega;
        Group root, transform;
        boolean alive;
        
        final static double TAU = Math.PI/2;
        
        public PhisicsObject(Group parent, Point2D p0, Point2D v0, double theta0, double omega0) {
            root = new Group();
            transform = new Group();
            root.getChildren().add(root);
            
            p = p0;
            v = v0;
            theta = theta0;
            omega = omega0;
            alive = true;
        }
        
        public void update (double delta) {
            p = p.add(v.multiply(delta));
            theta = (theta + omega * delta) % TAU;
            transform.getTransforms().clear();
            transform.getTransforms().addAll(
                    new Translate(p.getX(), p.getY()),
                    new Rotate(Math.toDegrees(theta))
                    );
        }
        
        public void destroy (Group parent) {
            parent.getChildren().remove(root);
            alive = false;
        }
        
        abstract Shape getShapeBounds();
        
        public boolean intersects (PhisicsObject po) {
            return alive && po.alive && 
                    !Shape.intersect(getShapeBounds(), po.getShapeBounds())
                    .getBoundsInLocal().isEmpty();
        }
        
        static Point2D vecAngle (double angle, double mag) {
            return new Point2D(Math.cos(angle), Math.sin(angle)).multiply(mag);
        }
        
        static double rand (double min, double max) {
            return Math.random() * (max - min) + min;
        }
        
}
   
    class Ship extends PhisicsObject {
        
        double trust = 150;
        Polygon pgon;
        
        public Ship(Group parent, Point2D p) {
            super(parent, p, Point2D.ZERO, 0, 0);
            pgon = new Polygon(0.7, 0, -0.7, -0.4, -0.7, 0.4);
            transform.getChildren().add(pgon);
            pgon.setStroke(Color.rgb(196, 237, 256));
            pgon.setStrokeWidth(0.1);
            pgon.getTransforms().add(new Scale(30, 30));
        }
        
        public void update (double delta, double omega, double throttle) {
            if (throttle != 0) {
                Point2D acc = vecAngle(theta, trust * throttle);
                v = v.add(acc.multiply(delta));
            } else {
                v = v.multiply(1 - 0.2 * delta);
            }
            this.omega = omega;
            super.update(delta);
        }
        
        public Shape getShapeBounds() {return pgon;}
        
    }

При запуске:

Gtk-Message: 09:45:02.446: Failed to load module "canberra-gtk-module"
Gtk-Message: 09:45:02.457: Failed to load module "pk-gtk-module"
Gtk-Message: 09:45:02.490: Failed to load module "canberra-gtk-module"
Gtk-Message: 09:45:02.490: Failed to load module "pk-gtk-module"
Exception in Application start method
java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1082)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.IllegalArgumentException: Children: cycle detected: parent = Group@7e0e5c0b, node = Group@7e0e5c0b
    at javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:551)
    at javafx.base/com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
    at Asteroids.space/Asteroids.space.PhisicsObject.<init>(App.java:106)
    at Asteroids.space/Asteroids.space.Ship.<init>(App.java:154)
    at Asteroids.space/Asteroids.space.App.start(App.java:50)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
    ... 1 more
Exception running application Asteroids.space.App

javafx я устанавливал на сам ПК. Подскажите, что нужно сделать, чтобы ошибки ушли?


Ответы (1 шт):

Автор решения: Nowhere Man

Ошибка вам сообщает о зацикливании в конструкторе класса PhisicsObject, как указал в комментарии @Дмитрий:

Caused by: java.lang.IllegalArgumentException: Children: cycle detected: parent = Group@7e0e5c0b, node = Group@7e0e5c0b
    at javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:551)
    at javafx.base/com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
    at Asteroids.space/Asteroids.space.PhisicsObject.<init>(App.java:106)

Код конструктора:

public PhisicsObject(Group parent, Point2D p0, Point2D v0, double theta0, double omega0) {
    root = new Group();
    transform = new Group();
    root.getChildren().add(root); // !!! Ошибка!
    // ...
}

Также в этом конструкторе игнорируется входной параметр родительского контейнера parent.

Вероятно, код следует исправить, чтобы была правильная связь между родителями и нодами:

public PhisicsObject(Group parent, Point2D p0, Point2D v0, double theta0, double omega0) {
    root = new Group();
    transform = new Group();
    root.getChildren().add(transform);
    parent.getChildren().add(root);
    
    p = p0;
    v = v0;
    theta = theta0;
    omega = omega0;
    alive = true;
}
→ Ссылка