Reputation: 17
I wrote the following code for adding and deleting points or circles with mouse events. The next step is joining them with a line while I'm creating them (creating a polygon). I'm completely stuck and do not know where to start. I am looking for documentation but I will appreciate if somebody could point me in the right direction.
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);
}
}
Upvotes: 2
Views: 1423
Reputation: 778
I would add a change listener to the children of your pane, add a polygon to the pane and if there are more then 2 Circles, you redraw the 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);
}
}
You can also not use the change listener, but call the redraw whenever you add or delete a circle. In addition you can also add an onclick listener to each circle calling the delete function and deleting in a more efficient manner:
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);
}
}
If you want to only use one click handler you could also do it this way:
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();
}
});
Upvotes: 2