2016-07-25 27 views
0

Ich habe ein Programm, das eine einfache visuelle Quadtree erstellt erstellt - im Grunde beginnt mit einem Raster von 4 Rechtecken, die jeweils in eine kleinere Version eines Rasters unterteilt werden können enthält 4 kleinere Rechtecke. PROBLEM: Manchmal weigert sich einer der ursprünglichen 4 Quadrate zu teilen, während die anderen weiterarbeiten. Das Problem tritt nur auf, nachdem ich mehrmals versucht habe, mit der rechten Maustaste zu klicken, wenn das Raster bereits mit einem Basisquadrat kombiniert wurde, das nicht mehr kombiniert werden kann.Javafx Rechtecke in Quadtree werden nicht verschwinden/erstellt werden - mit Mouseevents

Ich habe eine .setOnMouseClicked() Handler auf jedem Quadrat, das meine divide() Methode auf der linken Maustaste und combine() auf der rechten Maustaste aufruft. Außerdem wird die Handler-Methode so eingestellt, dass geprüft wird, ob das Quadrat, das angeklickt wurde, zu einem Gitter aus Quadraten gehört, bevor es versucht, die Kombinationsmethode aufzurufen, und hier habe ich Mühe zu verstehen, was schief läuft.

Meine Theorien so weit:

  • Vielleicht bezieht sich die Frage auf, wie javafx visuelle Objekte behandelt, aber ich hoffte, dass .getChildren().remove(Object o); war der richtige Weg, um etwas von der Szene zu entfernen. Es scheint die meiste Zeit zu funktionieren.
  • Vielleicht ist die Art und Weise, die ich ändere, was angezeigt wird und nicht wirklich threadsicher ist, und dass die Verwendung eines eventHandler die Objektentfernung unterbricht - aber das Problem tritt auf, wenn ich sowohl langsam als auch schnell klicke.

die Klassenhierarchie besteht aus einer abstrakten Klasse Cell, die entweder ein oder ein GridSquare sein können. Entschuldigen Sie, dass ich hier viel Code gelöscht habe, aber javafx debugging verwirrte mich einige Male, also habe ich ehrlich gesagt keine Ahnung, welcher Teil des Codes dafür verantwortlich ist, also habe ich das Ganze eingefügt.

Cell.java:

public abstract class Cell { 
    int x, y, w, h, id; //id is a reference the index in a grid this cell belongs to - it's used when a square replaces itself with a grid 
    Pane pane; 
    Cell parent; 

    public Cell(Pane pane, Cell parent, int x, int y, int w, int h, int id) { 
     this.x = x; 
     this.y = y; 
     this.w = w; 
     this.h = h; 
     this.id = id; 
     this.pane = pane; 
     this.parent = parent; 
    } 

    public void divide(){} 
    public abstract void remove(); 
} 

Grid.java

public class Grid extends Cell { 
    Cell[] grid = new Cell[4]; 

    public Grid(Pane pane, Cell parent, int x, int y, int w, int h, int id) { 
     //The constructor works as it should, just some unnecessary maths to avoid confusion over rounding 
     super(pane, parent, x, y, w, h, id); 
     int ver = x + w/2; 
     int hor = y + h/2; 
     grid[0] = new Square(pane, this, x, y, w/2, h/2, 0); 
     grid[1] = new Square(pane, this, ver+1, y, x+w-1-ver, h/2, 1); 
     grid[2] = new Square(pane, this, x, hor+1, w/2, y+h-1-hor, 2); 
     grid[3] = new Square(pane, this, ver+1, hor+1, x+w-1-ver, y+h-1-hor, 3); 
    } 

    public void combine(){ 
     remove(); 
     parent = new Square(pane, parent, x, y, w, h, id); 
    } 

    public void remove(){ 
     for(Cell c : grid){ 
      c.remove(); 
     } 
    } 
} 

Square.java:

public class Square extends Cell { 
    Rectangle rect; 

    public Square(Pane pane, Cell parent, int x, int y, int w, int h, int id) { 
     super(pane, parent, x, y, w, h, id); 
     rect = new Rectangle(x, y, w, h); 
     rect.setFill(Color.RED); 
     pane.getChildren().add(rect); 
     rect.setOnMouseClicked(e ->{ 
      if(e.getButton().equals(MouseButton.PRIMARY)) 
       divide(); 
      else if(e.getButton().equals(MouseButton.SECONDARY) && parent != null && parent.getClass().equals(Grid.class)) 
       ((Grid)parent).combine(); 
     }); 
    } 

    @Override 
    public void divide(){ 
     if(w > 3 && h > 3){ 
      remove(); 
      if(parent != null && parent.getClass().equals(Grid.class)) 
       ((Grid)parent).grid[id] = new Grid(pane, parent, x, y, w, h, id); 
      else 
       parent = new Grid(pane, parent, x, y, w, h, id); 
     } 
    } 

    public void remove(){ 
     pane.getChildren().remove(rect); 
    } 
} 

In der Hauptdatei, die parent als null für die Basis initialisiert Cell zu signalisieren, dass es nicht von der Maus-Handler unterteilt werden können:

@Override 
public void start(Stage primaryStage) throws Exception { 
    Pane pane = new Pane(); 
    pane.setBackground(new Background(new BackgroundFill(Color.BLACK, null, null))); 
    cell = new Square(pane, null, 50, 50, 700, 700, 0); 
    cell.divide(); //cell is a Cell type instance variable 
    primaryStage.setTitle("SquareSception"); 
    primaryStage.setScene(new Scene(pane, 800, 800)); 
    primaryStage.show(); 
} 

Die skizzierte Quadrate trotz vieler links Klicks The outlined squares refuses to divide despite many left-clicks Die obere rechte Quadrat aufzuteilen weigert aufzuteilen verweigert, die anderen würden The top right square refuses to divide, the others would

+0

ich auch als in den Bildern erwähnen sollte ich meine Maus in der rechten oberen Bereich hält, wie ich mit der rechten Maustaste war, scheint wie eine Korrelation zwischen wo ich mit der rechten Maustaste klicke und Linksklick reagiert nicht mehr ... – Chexxor

Antwort

1

Zunächst sollten Sie die Art der parent-Grid .Dieses ändern vermeidet die unnötige Typprüfung. (Jeder Elternteil ist ein Grid nach allem.)

Das eigentliche Problem ist jedoch, dass Sie nie ordnungsgemäß aktualisieren das übergeordnete Gitter in Grid.combine.Sie benötigen dieses Update, um die remove Methode tun richtig alle untergeordneten Plätzen zu finden:

public void combine(){ 
    remove(); 
    Square newParent = new Square(pane, parent, x, y, w, h, id); 
    if (parent != null) { 
     parent.setChild(newParent); 
    } 
} 

public void setChild(Cell newChild) { 
    grid[newChild.id] = newChild; 
} 
+0

Ihre Antwort ist tot, aber ich brauche die Typüberprüfung, wie ich die Eltern zu einem neuen Platz während kombinieren() .. Ich hätte alles entfernen können, wenn ich nicht nach dem Basisfall suchen müsste, in dem es kein Elternteil gibt, oder mit anderen Worten, ich muss das äußere Gitter mit nur einem Quadrat kombinieren ... Das Eltern-Array auf die Index-ID setzen macht dann keinen Sinn. – Chexxor

+0

@Chexxor Ein "Quadrat" dient jedoch nicht wirklich als Elternteil. 'parent = new Square (Fenster, Eltern, x, y, w, h, id);' wird nichts erreichen, außer das Feld zu setzen. Anstatt ihn als übergeordnetes Element des aktuellen Knotens zu verwenden, ersetzen Sie in diesem Fall den aktuellen Knoten durch ein Quadrat der "Kombinieren" -Methode. Beachten Sie außerdem, dass Sie nach dem Entfernen des Rasters keine Möglichkeit haben, mit dem Raster zu interagieren. – fabian

+0

Nevermind, sah gerade einen Fehler in meiner Anpassung Ihres Codes: O Es sollte in der Tat funktionieren – Chexxor