2016-03-22 12 views
2

Ich schrieb den folgenden Code zum Hinzufügen und Löschen von Punkten oder Kreisen mit Mausereignissen. Der nächste Schritt besteht darin, sie mit einer Linie zu verbinden, während ich sie erstelle (ein Polygon erzeugend). Ich bin völlig fest und weiß nicht, wo ich anfangen soll. Ich suche nach Unterlagen, aber ich werde es zu schätzen wissen, wenn mir jemand in die richtige Richtung zeigen könnte.Joining Punkte mit javaFX

package application; 

//import all needed classes 
import javafx.collections.ObservableList; 
import javafx.scene.input.MouseButton; 
import javafx.application.Application; 
import javafx.scene.shape.Circle; 
import javafx.scene.layout.Pane; 
import javafx.scene.paint.Color; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 
import javafx.scene.Node; 

public class Main extends Application { 

    // using the base class of layout panes 
    Pane pane = new Pane(); 

    @Override 
    public void start(Stage primaryStage) { 

     // what to do when the mouse is clicked 
     pane.setOnMouseClicked(e -> { 
      double drawX = e.getX();// position of mouse in X axle 
      double drawY = e.getY();// position of mouse in y axle 

      if (e.getButton() == MouseButton.PRIMARY) {// get the position of the mouse point when user left click 
       Circle circle = makeCircle(drawX, drawY);// using the makeCircle method to draw the circle where the mouse is at the click 
       pane.getChildren().add(circle); 
      } else if (e.getButton() == MouseButton.SECONDARY) { 
       deleteCircle(drawX, drawY);// using the deleteCircle function to delete the circle if right click on the circle 
      } 

     }); 

     // container to show all context in a 500px by 500px windows 
     try { 
      Scene scene = new Scene(pane, 500, 500);// size of the scene 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    // method to draw the circle when left click 
    private Circle makeCircle(double drawX, double drawY) { 
     Circle circle = new Circle(drawX, drawY, 7, Color.CORAL);// create the circle and its properties(color: coral to see it better) 
     circle.setStroke(Color.BLACK);// create the stroke so the circle is more visible 
     return circle; 
    } 

    // method to delete the circle using the ObservableList class 
    private void deleteCircle(double deletX, double deleteY) { 

     // loop to create my list of circles 'til this moment 
     ObservableList<Node> list = pane.getChildren(); 
     for (int i = list.size() - 1; i >= 0; i--) { 
      Node circle = list.get(i); 

      // checking which circle I want to delete 
      if (circle instanceof Circle && circle.contains(deletX, deleteY)) { 
       pane.getChildren().remove(circle); 
       break; 
      } 
     } 
    } 

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

Antwort

2

würde ich eine Änderung Zuhörer an die Kinder Ihrer Bereich hinzufügen, fügen Sie ein Polygon auf die Scheibe, und wenn es mehr als zwei Kreise sind, neu zu zeichnen Sie das Polygon:

public class Main extends Application { 

    // using the base class of layout panes 
    Pane pane = new Pane(); 
    Polygon polygon = new Polygon(); 

    @Override 
    public void start(Stage primaryStage) { 

     // what to do when the mouse is clicked 
     pane.setOnMouseClicked(e -> { 
      double drawX = e.getX();// position of mouse in X axle 
      double drawY = e.getY();// position of mouse in y axle 

      if (e.getButton() == MouseButton.PRIMARY) {// get the position of the mouse point when user left click 
       Circle circle = makeCircle(drawX, drawY);// using the makeCircle method to draw the circle where the mouse is at the click 
       pane.getChildren().add(circle); 
      } else if (e.getButton() == MouseButton.SECONDARY) { 
       deleteCircle(drawX, drawY);// using the deleteCircle function to delete the circle if right click on the circle 
      } 

     }); 

     pane.getChildren().add(polygon); 

     pane.getChildren().addListener(new ListChangeListener<Node>() { 
      @Override 
      public void onChanged(Change<? extends Node> c) { 
       int numOfCircles = pane.getChildren().size() - 1; 
       if (numOfCircles >= 2) { 
        polygon.setStroke(Color.BLACK); 
        polygon.getPoints().clear(); 
        for (int i = 0; i <= numOfCircles; i++) { 
         Node node = pane.getChildren().get(i); 
         if (node.getClass() == Circle.class) { 
          polygon.getPoints().addAll(
            ((Circle) node).getCenterX(), 
            ((Circle) node).getCenterY() 
          ); 
         } 
        } 
        System.out.println(polygon.getPoints()); 
       } 
      } 
     }); 

     // container to show all context in a 500px by 500px windows 
     try { 
      Scene scene = new Scene(pane, 500, 500);// size of the scene 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    // method to draw the circle when left click 
    private Circle makeCircle(double drawX, double drawY) { 
     Circle circle = new Circle(drawX, drawY, 7, Color.CORAL);// create the circle and its properties(color: coral to see it better) 
     circle.setStroke(Color.BLACK);// create the stroke so the circle is more visible 
     return circle; 
    } 

    // method to delete the circle using the ObservableList class 
    private void deleteCircle(double deletX, double deleteY) { 

     // loop to create my list of circles 'til this moment 
     ObservableList<Node> list = pane.getChildren(); 
     for (int i = list.size() - 1; i >= 0; i--) { 
      Node circle = list.get(i); 

      // checking which circle I want to delete 
      if (circle instanceof Circle && circle.contains(deletX, deleteY)) { 
       pane.getChildren().remove(circle); 
       break; 
      } 
     } 
    } 

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

} 

Sie können auch Verwenden Sie den Change-Listener nicht, sondern rufen Sie das Redraw immer dann auf, wenn Sie einen Kreis hinzufügen oder löschen. Darüber hinaus können Sie auch einen Onclick Zuhörer zu jedem Kreis ruft die Löschfunktion und Löschen in einer effizienteren Weise hinzufügen:

public class Main extends Application { 

    // using the base class of layout panes 
    Pane pane = new Pane(); 
    Polygon polygon = new Polygon(); 

    @Override 
    public void start(Stage primaryStage) { 

     // what to do when the mouse is clicked 
     pane.setOnMouseClicked(e -> { 
      double drawX = e.getX();// position of mouse in X axle 
      double drawY = e.getY();// position of mouse in y axle 

      if (e.getButton() == MouseButton.PRIMARY) {// get the position of the mouse point when user left click 
       Circle circle = makeCircle(drawX, drawY);// using the makeCircle method to draw the circle where the mouse is at the click 
       pane.getChildren().add(circle); 
       circle.setOnMouseClicked(event -> { 
        deleteCircle(circle); 
        // consume event so that the pane on click does not get called 
        event.consume(); 
       }); 
       redrawPolygon(); 
      } 

     }); 

     polygon = new Polygon(); 
     polygon.setFill(Color.TRANSPARENT); 
     polygon.setStroke(Color.BLACK); 
     pane.getChildren().add(polygon); 

     // container to show all context in a 500px by 500px windows 
     try { 
      Scene scene = new Scene(pane, 500, 500);// size of the scene 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    // method to draw the circle when left click 
    private Circle makeCircle(double drawX, double drawY) { 
     Circle circle = new Circle(drawX, drawY, 7, Color.CORAL);// create the circle and its properties(color: coral to see it better) 
     circle.setStroke(Color.BLACK);// create the stroke so the circle is more visible 
     return circle; 
    } 

    private void redrawPolygon() { 
     int numOfCircles = pane.getChildren().size() - 1; 
     if (numOfCircles > 0) { 
      polygon.getPoints().clear(); 
      for (int i = 0; i <= numOfCircles; i++) { 
       Node node = pane.getChildren().get(i); 
       if (node.getClass() == Circle.class) { 
        polygon.getPoints().addAll(
          ((Circle) node).getCenterX(), 
          ((Circle) node).getCenterY() 
        ); 
       } 
      } 
     } 
    } 

    private void deleteCircle(Circle circle){ 
     pane.getChildren().remove(circle); 
     redrawPolygon(); 
    } 

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

} 

Wenn Sie nur einen Klick-Handler verwenden, könnte man es auch tun, um diese Art und Weise:

pane.setOnMouseClicked(e -> { 

     if (e.getTarget().getClass() == Circle.class) { 
      deleteCircle((Circle)e.getTarget()); 
     } else { 
      Circle circle = makeCircle(e.getX(), e.getY());// using the makeCircle method to draw the circle where the mouse is at the click 
      pane.getChildren().add(circle); 
      redrawPolygon(); 
     } 

    }); 
+0

Vielen Dank! Ich schätze deine Hilfe sehr. Ich werde es versuchen, wenn ich heute nach Hause komme. – gnimm

+0

Es funktioniert super. Jetzt ist mein nächster Schritt, dass ich nicht möchte, dass die Linien sich kreuzen. Ich weiß, dass ich einen Algorithmus verwenden muss. Weiß jemand, wie der Algorithmus heißt und/oder wie er in meinem Code implementiert ist? – gnimm

+0

Es gibt andere Lösungen für diesen On-Stack-Überlauf. [hier ist mein eigenes aber] (https://gist.github.com/anonymous/8b4a0e85ccf897d9cec0). Was ich tue berechnet ein Zentrum und dann den Winkel aller Punkte im Vergleich zu diesem Zentrum. Danach sortiere ich nach Winkel und zeichne das Polygon mit der sortierten Liste. [Dies ist eine andere Lösung] (http://stackoverflow.com/questions/14263284/create-non-intersecting-polygon-passing-through-all-given-points). – JohnRW