Junaid Ali
Junaid Ali

Reputation: 107

Mouseclick Event on Multiple Nodes

In the exercise, when the rectangle is clicked on, a circle is displayed with in the boundary of rectangle. But when right mouseButton is pressed on circle it should be removed. I have used an ArrayList to store the circles being added. But how will I know that which circle is clicked on? And then the Click event should be invoked for that circle to remove it.

package sample;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.input.MouseButton;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
import javafx.scene.control.Label;
import java.util.ArrayList;
import javafx.scene.text.Font;
import javafx.scene.layout.Pane;

public class Main extends Application {

    private ArrayList < Circle > circles = new ArrayList<>();
    private Rectangle rectangle = new Rectangle( 200, 100, 1000, 600 );

    private Label[] label = new Label[2];
    private int counter = 0;

    private Pane pane = new Pane();

    @Override
    public void start( Stage stage ) throws Exception {
        rectangle.setFill( Color.WHITE );
        rectangle.setStroke( Color.BLACK );
        rectangle.setStrokeWidth( 1 );

        rectangle.setOnMouseClicked( e -> {
            if( e.getButton() == MouseButton.PRIMARY ) {
                // e.getX and e.getY will place the circle at the location of cursor click
                AddCircle( e.getX(), e.getY() );
            }
        });

        // will format the labels to be added on the pane
        formatLabels();

        pane.getChildren().addAll( label[0], label[1], rectangle );
        Scene scene = new Scene( pane, 1200, 650, Color.ANTIQUEWHITE );
        stage.setScene( scene );
        stage.setTitle( "Add and Remove Circles" );
        stage.show();
    }

    public void AddCircle( double X, double Y ) {
        Circle circle = new Circle( X, Y, 10 );
        circle.setFill( Color.WHITE );
        circle.setStroke( Color.BLACK );
        circle.setStrokeWidth( 1 );

        // adds circle object at value of counter
        circles.add( counter, circle );
        // setting id for object
        circles.get( counter ).setId( "" + counter );
        // adding circle from list into the pane
        pane.getChildren().add( circles.get( counter ) );

        // incrementing the counter after circle object is added
        ++counter;
    }

    private void formatLabels() {
        label[0] = new Label();
        label[0].setTranslateX( 20 );
        label[0].setTranslateY( 20 );
        label[0].setText( "Press Left Mouse key to add a circle" );
        label[0].setFont( Font.font( "Calibri", FontWeight.BLACK, FontPosture.REGULAR, 15 ) );

        label[1] = new Label();
        label[1].setTranslateX( 20 );
        label[1].setTranslateY( 40 );
        label[1].setText( "Press Right key on a circle to remove it" );
        label[1].setFont( Font.font( "Calibri", FontWeight.BLACK, FontPosture.REGULAR, 15 ) );
    }

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

Upvotes: 1

Views: 1015

Answers (1)

fabian
fabian

Reputation: 82491

Storing the circles in a list seems unnecessary to me, since the only time you do read accesses to it is when you get a reference to the circle you just added to the list and circle already contains that reference (AddCircle method).

To make a circle removable, simply add a onMouseClicked handler to it. The Circle is available as event target:

private final EventHandler<MouseEvent> removeHandler = evt -> {
    if (evt.getButton() == MouseButton.SECONDARY) {
        // remove clicked node (the circle) as child of pane
        this.pane.getChildren().remove(evt.getTarget());
    }
};

public void AddCircle(double X, double Y) {
    Circle circle = new Circle(X, Y, 10);
    circle.setFill(Color.WHITE);
    circle.setStroke(Color.BLACK);
    circle.setStrokeWidth(1);

    // setting id for object
    circle.setId("" + counter);

    // allow circle removal via mouse click
    circle.setOnMouseClicked(removeHandler);

    // adding circle into the pane
    pane.getChildren().add(circle);

    // incrementing the counter after circle object is added
    ++counter;
}

Note that primary and secondary mouse button may not be the left and right mouse buttons, e.g. if the mouse settings change the mouse to a left handed mouse.

Upvotes: 2

Related Questions