2016-05-08 18 views
0

Ich habe ein Programm mit einem Raumschiff (großer Kreis), das eine Kugel (kleiner Kreis) abfeuert, die nach einiger Zeit verschwindet. Jedes Mal, wenn es über einen bestimmten Teil des Codes läuft, erzeugt es einen Fehler (, aber es läuft weiter).Fehler: Ausnahme im Thread "JavaFX Application Thread"

Ich bin sicher, so dass das Problem in den folgenden Zeilen ist

private ArrayList<Bullet> bullets = new ArrayList<Bullet>(); 
//[...] 
for (Bullet bullet : bullets) { 
    if (bullet.getLoops() > 50) { 

    bullets.remove(bullet); // specially in this line, 
          // because if I delete this, the error doesn't show up! 
          // I think it has something to do with the ArrayList. 

    } else { 
    bullet.next(); 
    gc.strokeOval(bullet.getX() - 3, bullet.getY() - 3, 6, 6); 
    } 
} 

und das ist der Fehler, den ich bekommen:

Exception in thread "JavaFX Application Thread" java.util.ConcurrentModificationException 
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) 
    at java.util.ArrayList$Itr.next(ArrayList.java:851) 
    at sample.Main$4.handle(Main.java:131) 
    at javafx.animation.AnimationTimer$AnimationTimerReceiver.lambda$handle$484(AnimationTimer.java:57) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javafx.animation.AnimationTimer$AnimationTimerReceiver.handle(AnimationTimer.java:56) 
    at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:357) 
    at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267) 
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:506) 
    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:745) 

ich Ihnen gerne andere Informationen zu liefern, benötigt auf anfordern.

Prost. (Sorry für mein Englisch, ich bin aus Deutschland, aber ich habe Englisch seit einigen Jahren in der Schule.)

PS: wenn jemand den vollständigen Code des Mainclass benötigt:

package sample; 

import javafx.animation.AnimationTimer; 
import javafx.application.Application; 
import javafx.event.EventHandler; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.canvas.Canvas; 
import javafx.scene.canvas.GraphicsContext; 
import javafx.scene.input.KeyEvent; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.paint.Color; 
import javafx.scene.text.Font; 
import javafx.scene.text.FontWeight; 
import javafx.stage.Stage; 

import java.util.ArrayList; 

public class Main extends Application { 

    private Player p = new Player(100, 100, 0); 
    private ArrayList<Bullet> bullets = new ArrayList<Bullet>(); 

    private static boolean left; 
    private static boolean right; 
    private static boolean up; 
    private static boolean down; 
    private static boolean shoot; 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     FXMLLoader.load(getClass().getResource("sample.fxml")); 
     primaryStage.setTitle("Hello World"); 
     Group root0 = new Group(); 
     Scene theScene = new Scene(root0, 500, 500); 
     primaryStage.setScene(theScene); 
     Canvas canvas = new Canvas(500, 500); 
     root0.getChildren().add(canvas); 


     theScene.setOnMouseMoved(
       new EventHandler<MouseEvent>() { 
        public void handle(MouseEvent e) { 
         Vector a = new Vector(p.getX(), -p.getY()); 
         Vector b = new Vector(e.getX(), -e.getY()); 
         Vector c = new Vector(p.getX(), -p.getY() + 1); 
         p.setRotation(Vector.getAngle(a, b, c)); 
        } 
       } 
     ); 
     theScene.setOnKeyPressed(
       new EventHandler<KeyEvent>() { 
        public void handle(KeyEvent e) { 
         String code = e.getCode().toString(); 
         if (code.equals("A")) { 
          left = true; 
         } 
         if (code.equals("D")) { 
          right = true; 
         } 
         if (code.equals("W")) { 
          up = true; 
         } 
         if (code.equals("S")) { 
          down = true; 
         } 
         if (code.equals("SPACE")) { 
          if (!PlayerShot()) shoot = true; 
         } 
        } 
       } 
     ); 
     theScene.setOnKeyReleased(
       new EventHandler<KeyEvent>() { 
        public void handle(KeyEvent e) { 
         String code = e.getCode().toString(); 
         if (code.equals("A")) { 
          left = false; 
         } 
         if (code.equals("D")) { 
          right = false; 
         } 
         if (code.equals("W")) { 
          up = false; 
         } 
         if (code.equals("S")) { 
          down = false; 
         } 
         if (code.equals("SPACE")) { 
          shoot = false; 
         } 
        } 
       } 
     ); 
     GraphicsContext gc = canvas.getGraphicsContext2D(); 

     Font theFont = Font.font("Helvetica", FontWeight.BOLD, 24); 
     gc.setFont(theFont); 
     gc.setStroke(Color.BLACK); 
     gc.setLineWidth(1); 

     new AnimationTimer() { 
      public void handle(long currentNanoTime) { 
       // Clear the canvas 
       gc.setFill(new Color(0.85, 0.85, 1.0, 1.0)); 
       gc.fillRect(0, 0, 500, 500); 

       int x = p.getX(); 
       int y = p.getY(); 
       if (left && x >= 16) { 
        p.setX(x - 3); 
       } 
       if (right && x <= 500 - 16) { 
        p.setX(x + 3); 
       } 
       if (up && y >= 16) { 
        p.setY(y - 3); 
       } 
       if (down && y <= 500 - 16) { 
        p.setY(y + 3); 
       } 
       if (shoot) { 
        bullets.add(new Bullet(p.getX(), p.getY(), p.getRotationInVelocity(), p)); 
        shoot = false; 
       } 
       gc.setStroke(Color.BLUE); 
       gc.strokeLine(p.getX(), p.getY(), p.getX() + Math.sin(p.getRotation()) * 16, p.getY() - Math.cos(p.getRotation()) * 16); 
       gc.strokeOval(p.getX() - 16, p.getY() - 16, 32, 32); 
       gc.setStroke(Color.RED); 
       for (Bullet bullet : bullets) { 
        if (bullet.getLoops() > 50) { 
         bullets.remove(bullet); 
        } else { 
         bullet.next(); 
         gc.strokeOval(bullet.getX() - 3, bullet.getY() - 3, 6, 6); 
        } 
       } 
      } 
     }.start(); 

     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 

    // Hat der Spieler gerade eben schon geschossen? 
    public boolean PlayerShot() { 
     for (Bullet bullet : bullets) { 
      if(bullet.getShooter() == p)return true; 
     } 
     return false; 
    } 
} 

die anderen Klassen behandeln nur ein paar int-und Doppel-vars

+0

öffentliche Leere nächste() { x + = velocity.getY() * 5; y + = -velocity.getX() * 5; Schleifen ++; } // Dies ist der Code, der die Vorwärtsbewegung behandelt und wenn ich ihn lösche kommt er nicht zu dem Teil mit dem "bullets.remove (bullet);" also kann es nicht erscheinen als. Aber das ist nicht die Lösung, die ich will! – doej1367

+0

danke trotzdem :)! – doej1367

Antwort

1

Sie können das nicht tun. Sie erhalten eine ConcurrentModificationException.

Was ist ein ConcurrentModificationException?

Von offiziellen Javadoc:

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

Grundsätzlich die Sie iterieren Ihrer Liste. Wenn Sie an einem Punkt entscheiden, ein Element zu entfernen, kann dies zu einem unvorhersehbaren Verhalten führen. Um dies zu vermeiden, wird diese Ausnahme ausgelöst.

Wie kann ich es beheben?

Verwenden Sie einfach eine Iterator statt, um Ihre ArrayList zu fahren. Iterator verwendet die Methoden add(T element) und remove(T element).

+0

Sie denken so? Iterator bulletsI = bullets.iterator(); while (bulletsI.hasNext()) { if (bulletsI.next(). GetLoops()> 50) { bullets.remove (bulletsI.next()); } sonst { bulletsI.next(). Next(); gc.strokeOval (bulletsI.next(). GetX() - 3, bulletsI.next(). GetY() - 3, 6, 6); } } es wirft nur noch mehr Fehler bei mir – doej1367

+1

Aber danke! half mir ein wenig weiter zu wissen, dass ich auf dem richtigen Weg bin – doej1367

+0

Nein. Sie rufen next() auch mal. Sie sollten es einmal pro Iteration aufrufen. Mit Next() wird der Iterator zum nächsten Element in der Liste wechseln.Wenn Sie 5 Mal pro Iteration anrufen, nachdem Sie überprüft haben, dass er mindestens ein Element hat, kann ich sehen, warum Sie mehr Fehler bekommen. Tun Sie dies nach der while: Bullet currentElement = bulletsI.next(); und dann mach dein Zeug auf dieses Objekt, ohne next() woanders anzurufen. – Aurasphere

Verwandte Themen