首页 > 解决方案 > 如何在子场景中选择形状以允许我进行转换

问题描述

我目前正在使用 javafx 中的一个程序,该程序询问用户圆柱体的半径和高度,一旦用户点击添加,它就会在子场景中创建一个圆柱体。我想知道如何将 setonmouseclicked 事件处理程序与圆柱体结合起来,这样我就可以选择那个圆柱体并进行编辑,例如缩放它、旋转它等,然后我可以转到下一个形状并单击那个然后我可以对下一个进行缩放、旋转等操作。目前,当我询问用户并添加气缸时会发生这种情况。

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);

    });

标签: user-interfacejavafx3dcontrolsshapes

解决方案


如何选择节点

“我如何区分我点击的是哪个圆柱体,以便我可以对那个特定的圆柱体进行更改?”

你不知道,JavaFX 节点选择实现会为你做到这一点。当你在一个对象上设置一个点击处理程序时,它会在对象被点击的时候被调用,所以当它被调用的时候,你就知道用户点击了这个对象。

如何保存选择

创建形状时,为其创建单击处理程序,并在单击节点时为所选节点设置一个字段。

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);
}

如何修改选定的项目

要定义您希望对选定节点执行操作的情况,例如更改半径,然后您可以执行以下操作:

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);
        }
    }
); 

如何将选定节点中的值设置到控件

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

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

示例节点选择应用程序

以下示例应用程序演示了此处讨论的概念示例:

尽管演示示例是 2D 的,但节点选择和随后通过控件修改项目属性的概念对于 2D 和 3D 没有什么不同。

如何处理多项选择

如果您希望添加多个选择,可以一次选择多个节点,那么它会更复杂一些。您可以使用以下答案中定义的一些概念(链接的问题适用于 2D,但 3D 在这方面并没有真正的不同)。

如何处理深度排序和模糊节点

因为它是 3D 的,所以对象可以具有 z 深度,并且可以进行深度排序。如果一个对象在另一个对象的后面,为了允许通过鼠标选择被遮挡的对象,您将需要一种机制来允许用户将遮挡的对象移开(例如,通过选择并拖动它们来移动它们) ,或将场景旋转到另一个视点,用户希望单击的对象不再被遮挡(有关如何完成此类事情的信息超出了此答案的范围)。

获取详细的选择信息

如果您需要有关被拾取的东西的更多信息,例如被拾取的节点上的点(在 3D 空间中),或者被拾取的节点的面或纹理坐标,那么您可以使用pickResult API。提供了一个教程:

但是,出于您的目的,真正需要的只是一个不查询选择结果的节点的简单单击处理程序。


推荐阅读