1

I currently am working on a program in javafx that asks the user for radius and height of a cylinder and once the user hits add, it creates a cylinder in the subscene. I was wondering how I can combine the setonmouseclicked event handler with the cylinder so that way I can choose that one cylinder and make edits like scaling it, rotating it, etc. and then i can go to the next shape and click on that one and then i can do stuff like scale, rotate, etc to the next one. Currently this is what happens when i ask a user and they add the cylinder.

Button addCyl=new Button("Add Cylinder");

    addCyl.setOnAction(event -> {
        String cylRadius=cylRadiusInput.getText();
        String cylHeight=cylHeightInput.getText();

        Double Radius=Double.parseDouble(cylRadius);
        Double Height=Double.parseDouble(cylHeight);

        Cylinder cylinder=new Cylinder(Radius, Height);

        shapeGroup.getChildren().add(cylinder);

    });
  • 1
    Have you tried adding `cylinder.setOnMouseClicked(...)` in the handler you got? – SedJ601 Dec 13 '19 at 20:10
  • I could do that but how would i differentiate each cylinder since my program adds as many as the user wants. And if i click on the specific shape I want my buttons to scale, tranlsate, rotate, etc to affect just the object clicked on until i choose some other object – Paul Anthony Morillo Dec 13 '19 at 20:16
  • 1
    I am not sure I understand your response. Try want I suggest. It should work. – SedJ601 Dec 13 '19 at 20:17
  • So basically when a user adds the cylinder to the subscene, they can still add another cylinder and another but its all from the Cylinder cylinder initialization. So how do i differentiate between which cylinder im clicking on so i can make changes to that specific one? – Paul Anthony Morillo Dec 13 '19 at 20:21
  • 3
    "how do i differentiate between which cylinder im clicking on so i can make changes to that specific one?" -> You don't, the JavaFX node picking implementation will do that for you. When you set a click handler on an object, it will be invoked when the object is clicked on, so when it is invoked, you know that the user has clicked on the object. – jewelsea Dec 13 '19 at 20:31
  • 1
    wow that ideology flew right over my head. I was def overthinking it! Thank you everyone! – Paul Anthony Morillo Dec 13 '19 at 20:33

1 Answers1

3

How to pick a node

"how do i differentiate between which cylinder im clicking on so i can make changes to that specific one?"

You don't, the JavaFX node picking implementation will do that for you. When you set a click handler on an object, it will be invoked when the object is clicked on, so when it is invoked, you know that the user has clicked on the object.

How to save a selection

When you create the shape, create a click handler for it, and, when the node is clicked, set a field for the selected node.

private Group shapeGroup = new Group():
private Cylinder selectedNode;

// omitted ... add shapeGroup to sub-scene

private void addNode() {
    Cylinder cylinder = new Cylinder(radius, height);
    cylinder.setOnMouseClicked(e -> {
        selectedNode = cylinder;
    });
    shapeGroup.getChildren().add(cylinder);
}

How to modify a selected item

To define what happens you want to take an action on the selected node, say change the radius, then you can do something like below:

private Slider radius = new Slider(10, 100, 20);

// omitted ... add radius control to scene

radius.valueProperty().addListener(
    (observable, oldValue, newValue) -> {
        if (selectedNode != null) {
            selectedNode.setRadius(newValue);
        }
    }
); 

How to set values from a selected node to your controls

If you wish, when a node is selected, you can set the value of your controls to the current value for the selected node, e.g.

cylinder.setOnMouseClicked(e -> {
    selectedNode = cylinder;
    radius.setValue(selectedNode.getRadius());
});

Sample node selection app

An example of the concepts discussed here is demoed in the following sample app:

Even though the demo example is in 2D, the concepts for node selection and subsequent modification of item properties by controls are no different for 2D and 3D.

How to handle multiple selections

If you wish to add multiple selection where multiple nodes may be selected at once, then it is a bit more complex. You can use some of the concepts defined in the answers below (linked question is for 2D, but 3D isn't really different in this regards).

What to do about depth sorting and obscured nodes

Because it is 3D, the objects can have z-depth, and are subject to depth sorting. If one object is behind another object, to allow the obscured object to be selected by mouse, you will need to have a mechanism to allow the user to move the obscuring objects out of the way (e.g. by selecting and dragging them to move them), or to rotate the scene to another viewpoint where the object the user wishes to click is no longer obscured (info on how to accomplish these kind of things is out of scope for this answer).

Getting detailed pick info

If you needed more info about the thing being picked, e.g. the point (in 3D space) on the node which was picked, or what face or texture co-ordinate of the node was picked then you can use the pickResult API. A tutorial for this is provided:

However, for your purposes, a simple click handler for the node which does not query the pick result is all that is really needed.

jewelsea
  • 150,031
  • 14
  • 366
  • 406