Javafx中的选择性子变换

Javafx中的选择性子变换,java,javafx,transformation,Java,Javafx,Transformation,我想知道是否有可能将父转换选择性地应用于javafx中的子节点 据我所知,当一个节点被转换时,所述节点的所有子节点也被转换 我的问题是:是否可以禁用子级中的父级转换类型,以便在父级转换时只传递选定类型的转换 与此类似: 我希望在不旋转文本的情况下旋转组节点,但我希望文本位置受旋转的影响 希望我已经解释清楚了 当前,当组被变换时,我只是对文本应用相反的旋转,但现在扩展我的场景图使这变得更加复杂。简言之,否:组的变换总是传播到它的所有子级 但是,我认为这里您只希望文本的rotate属性是组的ro

我想知道是否有可能将父转换选择性地应用于javafx中的子节点

据我所知,当一个节点被转换时,所述节点的所有子节点也被转换

我的问题是:是否可以禁用子级中的父级转换类型,以便在父级转换时只传递选定类型的转换

与此类似:

我希望在不旋转文本的情况下旋转组节点,但我希望文本位置受旋转的影响

希望我已经解释清楚了



当前,当组被变换时,我只是对文本应用相反的旋转,但现在扩展我的场景图使这变得更加复杂。

简言之,否:组的变换总是传播到它的所有子级

但是,我认为这里您只希望文本的rotate属性是组的rotate属性的负数:

text.rotateProperty().bind(group.rotateProperty().multiply(-1));
由于
rotateProperty
定义了围绕节点中心的旋转,因此当组旋转时,它(及其所有子节点)将围绕其中心旋转,然后绑定确保文本围绕其中心以相反方向旋转

如果你想要更一般的东西,它会变得有点棘手。一种可能的方法是观察要保持水平的文本父级的
localToSceneTransform
。该属性表示将父对象中的坐标映射到场景中坐标的累积变换。然后,可以在父对象的局部坐标空间中获取一条水平线,将其变换到场景中,并查看它创建的角度。然后,您希望将文本旋转此角度的负值

下面是一个演示:

import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class RotateGroupKeepTextAligned extends Application {   

    @Override
    public void start(Stage primaryStage) {
        BorderPane root = new BorderPane();
        StackPane container = new StackPane();
        Group outer = new Group();
        Rectangle outerRect = new Rectangle(0, 0, 400, 400);
        outerRect.setFill(Color.ANTIQUEWHITE);
        outer.getChildren().add(outerRect);

        Text outerText = new Text(5,  5, "Outer Group");
        Group inner = new Group();
        inner.relocate(10, 25);
        Text innerText = new Text(5, 5, "Inner Group");
        Rectangle rect = new Rectangle(50, 50, 150, 150);
        rect.setFill(Color.CORNFLOWERBLUE);
        Text fixedAlignmentText = new Text(100, 220, "Horizontal Text");

        inner.localToSceneTransformProperty().addListener((obs, oldT, newT) -> {
            // figure overall rotation angle of inner:
            Point2D leftScene = newT.transform(new Point2D(0, 0));
            Point2D rightScene = newT.transform(new Point2D(1, 0));

            double angle = Math.toDegrees(Math.atan2(rightScene.getY() - leftScene.getY(), rightScene.getX() - leftScene.getX()));

            fixedAlignmentText.setRotate(-angle);
        });

        outer.setStyle("-fx-background-color: antiquewhite;");
        outer.getChildren().addAll(outerText, inner);

        inner.setStyle("-fx-background-color: white;");
        inner.getChildren().addAll(innerText, rect, fixedAlignmentText);

        container.getChildren().add(outer);
        root.setCenter(container);

        VBox controls = new VBox(5,
                makeControls("Outer Group", outer),
                makeControls("Inner Group", inner));

        root.setBottom(controls);

        Scene scene = new Scene(root, 600, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Node makeControls(String title, Node node) {
        GridPane grid = new GridPane();

        Label label = new Label(title);
        Spinner<Double> rotateSpinner = new Spinner<>(0, 360, 0, 5);
        node.rotateProperty().bind(rotateSpinner.getValueFactory().valueProperty());
        rotateSpinner.getValueFactory().setWrapAround(true);

        Button up = createTranslateButton(node, Node::translateYProperty, -2, "^");
        Button down = createTranslateButton(node, Node::translateYProperty, 2, "v");
        Button left = createTranslateButton(node, Node::translateXProperty, -2, "<");
        Button right = createTranslateButton(node, Node::translateXProperty, 2, ">");

        grid.add(label, 0, 0, 3, 1);
        grid.add(new Label("Rotation:"), 0, 1, 1 ,2);
        grid.add(rotateSpinner, 1, 1, 1, 2);
        grid.add(up, 3, 1);
        grid.add(down, 3, 2);
        grid.add(left, 2, 1, 1, 2);
        grid.add(right, 4, 1, 1, 2);

        grid.setHgap(5);
        grid.setVgap(5);

        return grid ;
    }

    private Button createTranslateButton(Node node, Function<Node, DoubleProperty> property, double delta, String text) {
        Button button = new Button(text);
        button.setOnAction(e -> {
            DoubleProperty prop = property.apply(node);
            prop.set(prop.get() + delta);
        });
        return button ;
    }

    public static void main(String[] args) {
        launch(args);
    }
}
import java.util.function.function;
导入javafx.application.application;
导入javafx.beans.property.DoubleProperty;
导入javafx.geometry.Point2D;
导入javafx.scene.Group;
导入javafx.scene.Node;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.control.Label;
导入javafx.scene.control.Spinner;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.layout.GridPane;
导入javafx.scene.layout.StackPane;
导入javafx.scene.layout.VBox;
导入javafx.scene.paint.Color;
导入javafx.scene.shape.Rectangle;
导入javafx.scene.text.text;
导入javafx.stage.stage;
公共类RotateGroupKeepTextAligned扩展应用程序{
@凌驾
公共无效开始(阶段primaryStage){
BorderPane根=新的BorderPane();
StackPane容器=新的StackPane();
组外部=新组();
矩形outerRect=新矩形(0,0,400,400);
外部正确。设置填充(颜色。仿古白色);
outer.getChildren().add(outerRect);
Text outerText=新文本(5,5,“外部组”);
组内部=新组();
内。重新安置(10,25);
Text innerText=新文本(5,5,“内部组”);
矩形rect=新矩形(50,50,150,150);
直毛(颜色:矢车菊蓝);
文本固定对齐文本=新文本(100220,“水平文本”);
inner.LocalToScenetTransformProperty().addListener((obs、oldT、NETT)->{
//图内齿轮总旋转角度:
Point2D leftScene=newT.transform(新的Point2D(0,0));
Point2D rightScene=newT.transform(新的Point2D(1,0));
双角度=Math.toDegrees(Math.atan2(righscene.getY()-leftScene.getY(),righscene.getX()-leftScene.getX());
fixedAlignmentText.setRotate(-angle);
});
outer.setStyle(“-fx背景色:antiquewhite;”);
outer.getChildren().addAll(outerText,inner);
内部.setStyle(“-fx背景色:白色;”);
internal.getChildren().addAll(innerText、rect、fixedAlignmentText);
container.getChildren().add(外部);
root.setCenter(容器);
VBox控件=新的VBox(5,
makeControls(“外部组”,外部),
makeControls(“内部组”,内部));
根。setBottom(对照);
场景=新场景(root,600600);
初级阶段。场景(场景);
primaryStage.show();
}
私有节点makeControls(字符串标题、节点){
GridPane grid=新建GridPane();
标签=新标签(标题);
微调器旋转内部=新微调器(0,360,0,5);
node.rotateProperty().bind(rotateSpinner.getValueFactory().valueProperty());
rotateSpinner.getValueFactory().setWrapAround(true);
Button up=CreateTransaleButton(节点,节点::TranslateProperty,-2,“^”);
Button down=CreateTransaleButton(节点,节点::TranslateProperty,2,“v”);
按钮左=CreateTransaleButton(节点,节点::TranslateProperty,-2,“”);
添加(标签,0,0,3,1);
添加(新标签(“旋转”)、0、1、1、2;
添加(旋转内部,1,1,1,2);
网格。相加(加起来,3,1);
网格。添加(向下,3,2);
添加(左,2,1,1,2);
添加(右,4,1,1,2);
网格setHgap(5);
网格设置间隙(5);
返回网格;
}
私有按钮CreateTransaleButton(节点、函数属性、双增量、字符串文本){
按钮按钮=新按钮(文本);
按钮。设置操作(e->{
DoubleProperty prop=property.apply(节点);
道具设置(道具获取()+delta);
});
返回按钮;
}
公共静态void main(字符串[]args){
发射(args);
}
}

即使将旋转应用于组的根,此操作是否有效?否,在这种情况下,您需要
text.rotateProperty().bind(root.rotateProperty()…)要概括是很困难的,仅仅从几何的角度精确定义你的意思。啊,谢谢。看起来问题比我想象的要严重得多