同时旋转和翻译在javafx中无法正常工作

时间:2015-06-07 15:38:23

标签: graphics javafx javafx-8 drag

我已经从 圈子 构建了以下“系统”。
<登记/> Snapshot of the System

我正试图在系统中实现两个转换。

  1. 当拖动绿色圆圈时,绿色和蓝色圆圈都应围绕红色中心沿着拖动方向旋转。
  2. 拖动红色中心时,应相应拖动整个系统(如整体)。

  3. 我试图实施它但遇到问题
    单独完成时,两种过渡都很好 即,当应用程序启动时,您尝试拖动绿色圆圈,整个系统完全围绕红色圆圈旋转。
    同样,在启动时,拖动红色圆圈时,一切都被拖得很好。 的
    当这些拖曳中的任何一个在另一个之后被尝试时,形状会彼此远离!
    请指出可能导致此行为的原因。
    欢迎任何其他实现转换的方式,因为我还是JavaFx中的Animations的新手,显然不是解决问题的最佳代码。

    以下是我的代码:

        import javafx.application.Application;
        import javafx.scene.Scene;
        import javafx.scene.layout.Pane;
        import javafx.scene.paint.Color;
        import javafx.scene.shape.Circle;
        import javafx.scene.shape.Line;
        import javafx.scene.transform.Rotate;
        import javafx.scene.transform.Translate;
        import javafx.stage.Stage;
        public class SpindleAndWheel extends Application
        {
    
        Circle circle;
        Circle oppositeCircle;
        Circle pivot;
        Line spindle;
    
        Rotate rotateCircle, rotateOppositeCircle;
        Translate translateCircle, translateOppositeCircle;
        Translate translateCircleBack, translateOppositeCircleBack;
        Translate dragTranslateCircle, dragTranslatePivot, dragTranslateOppositeCircle, dragTranslateSpindle;
    
        double dragInitX, dragInitY;
        double dragInitTheta;
        double theta1,theta2;
        double angleOfRotation;
    
        double dragPivotInitX,dragPivotInitY,systemDragOffsetX,systemDragOffsetY;
        double dragTranslateCircleBackupX,dragTranslatePivotBackupX, dragTranslateOppositeCircleBackupX, dragTranslateSpindleBackupX;
        double dragTranslateCircleBackupY,dragTranslatePivotBackupY, dragTranslateOppositeCircleBackupY, dragTranslateSpindleBackupY;
    
        @Override
        public void start(Stage primaryStage) throws Exception
        {
            Stage stage = new Stage();
    
    
            stage.setMinHeight(500);
            stage.setMinWidth(500);
    
            Pane root = new Pane();
    
            circle = new Circle(150, 150, 30);
            oppositeCircle = new Circle(350, 350, 30);
            pivot = new Circle(250, 250, 5);
            spindle = new Line(150, 150, 350, 350);
    
        /**************** Initializing Shapes **********/
            circle.setFill(Color.GREEN.deriveColor(1, 1, 1, 0.35));
            circle.setStroke(Color.GREEN);
            oppositeCircle.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.35));
            oppositeCircle.setStroke(Color.BLUE);
            pivot.setFill(Color.RED.deriveColor(1, 1, 1, 0.35));
            pivot.setStroke(Color.RED);
            spindle.setStrokeWidth(3);
            spindle.setStroke(Color.BLACK.deriveColor(1, 1, 1, 0.35));
        /****************************************************/
    
        /**************** Initializing Animations **********/
            rotateCircle = new Rotate(0, 0, 0);
            translateCircle = new Translate(0, 0);
            translateCircleBack = new Translate(0, 0);
            dragTranslateCircle = new Translate(0, 0);
    
            rotateOppositeCircle = new Rotate(0, 0, 0);
            translateOppositeCircle = new Translate(0, 0);
            translateOppositeCircleBack = new Translate(0, 0);
            dragTranslateOppositeCircle = new Translate(0, 0);
    
    
            dragTranslatePivot = new Translate(0, 0);
            dragTranslateSpindle = new Translate(0, 0);
        /****************************************************/
    
        /**************** Adding Animations **************/
            circle.getTransforms().addAll(translateCircle, rotateCircle, translateCircleBack, dragTranslateCircle);
            oppositeCircle.getTransforms().addAll(translateOppositeCircle, rotateOppositeCircle, translateOppositeCircleBack, dragTranslateOppositeCircle);
            pivot.getTransforms().addAll(dragTranslatePivot);
            spindle.getTransforms().addAll(dragTranslateSpindle);
        /****************************************************/
            Scene scene = new Scene(root);
    
            stage.setScene(scene);
    
    
            root.getChildren().addAll(circle,oppositeCircle,pivot,spindle);
            stage.show();
    
    
    
        /** Get angle of point of click with
         * point of rotation, before drag begins **/
            circle.setOnMousePressed(event -> {
                dragInitX = event.getSceneX();
                dragInitY = event.getSceneY();
                dragInitTheta = angleOfRotation + dragInitTheta;
    
                double initialSlope;
                double pointOfRotationX,pointOfRotationY;
                pointOfRotationY = pivot.getCenterY() + dragTranslatePivot.getY();
                pointOfRotationX = pivot.getCenterX() + dragTranslatePivot.getX();
    
                initialSlope = Math.atan((dragInitY - (pointOfRotationX)) / (dragInitX - (pointOfRotationY)));
    
                theta1 = Math.toDegrees(initialSlope);
    
                if (dragInitX < pointOfRotationX)
                    theta1 = (360 + theta1) % 360;
                else
                    theta1 = 180 + theta1;
    
            });
        /********************************************/
    
        /** Get angle of point of drags with
        * point of rotation, when the drag is on **/
           circle.setOnMouseDragged(event -> {
               double finalSlope;
               double pointOfRotationX,pointOfRotationY;
               pointOfRotationY = pivot.getCenterY() + dragTranslatePivot.getY();
               pointOfRotationX = pivot.getCenterX() + dragTranslatePivot.getX();
    
               finalSlope = Math.atan((event.getSceneY() - (pointOfRotationX)) / (event.getSceneX() - (pointOfRotationY)));
               theta2 = Math.toDegrees(finalSlope);
    
    
               if (event.getSceneX() < pointOfRotationX)
                   theta2 = (360 + theta2) % 360;
               else
                   theta2 = 180 + theta2;
    
               angleOfRotation = theta2 - theta1;
    
               translateCircle.setX(pointOfRotationX);
               translateCircle.setY(pointOfRotationY);
               rotateCircle.setAngle(angleOfRotation + dragInitTheta);
               translateCircleBack.setX(-pointOfRotationX);
               translateCircleBack.setY(-pointOfRotationY);
    
               translateOppositeCircle.setX(pointOfRotationX);
               translateOppositeCircle.setY(pointOfRotationY);
               rotateOppositeCircle.setAngle(angleOfRotation + dragInitTheta);
               translateOppositeCircleBack.setX(-pointOfRotationX);
               translateOppositeCircleBack.setY(-pointOfRotationY);
    
               spindle.setRotate(angleOfRotation + dragInitTheta);
           });
        /********************************************/
    
    
    
        /** Relocate the whole system when the point of
         * rotation is dragged **/
            pivot.setOnMousePressed(event -> {
                dragPivotInitX = event.getSceneX();
                dragPivotInitY = event.getSceneY();
    
                dragTranslateCircleBackupX = dragTranslateCircle.getX();
                dragTranslateCircleBackupY = dragTranslateCircle.getY();
                dragTranslatePivotBackupX = dragTranslatePivot.getX();
                dragTranslatePivotBackupY = dragTranslatePivot.getY();
                dragTranslateOppositeCircleBackupX = dragTranslateOppositeCircle.getX();
                dragTranslateOppositeCircleBackupY = dragTranslateOppositeCircle.getY();
                dragTranslateSpindleBackupX = dragTranslateSpindle.getX();
                dragTranslateSpindleBackupY = dragTranslateSpindle.getY();
            });
    
            pivot.setOnMouseDragged(event -> {
                systemDragOffsetX = event.getSceneX() - dragPivotInitX;
                systemDragOffsetY = event.getSceneY() - dragPivotInitY;
    
                dragTranslateCircle.setX(dragTranslateCircleBackupX + systemDragOffsetX);
                dragTranslateCircle.setY(dragTranslateCircleBackupY + systemDragOffsetY);
                dragTranslatePivot.setX(dragTranslatePivotBackupX+ systemDragOffsetX);
                dragTranslatePivot.setY(dragTranslatePivotBackupY+ systemDragOffsetY);
                dragTranslateOppositeCircle.setX(dragTranslateOppositeCircleBackupX+ systemDragOffsetX);
                dragTranslateOppositeCircle.setY(dragTranslateOppositeCircleBackupY+ systemDragOffsetY);
                dragTranslateSpindle.setX(dragTranslateSpindleBackupX+ systemDragOffsetX);
                dragTranslateSpindle.setY(dragTranslateSpindleBackupY + systemDragOffsetY);
    
            });
        /********************************************/
    
        }
    
        public static void main(String[] args)
        {
            launch(args);
        }
    
    
    }
    

2 个答案:

答案 0 :(得分:2)

很好的方法,但正如您已经发现的那样,它有一个主要缺点:应用一次转换后,另一种转换效果不佳。原因在于您定义转换的方式。此外,分配如此多的转换会导致复杂的系统,难以保留。

我的建议要简单得多:只需将所有形状包裹在一个Group中,然后转换此组,在拖动轴时将其平移,或在拖动圆圈时将其旋转到轴上。请注意,您可以在此处使用setPivotX()setPivotY()来指示实际的旋转点。

正如您所看到的,您只需要进行两次转换,更重要的是,您不会有任何副作用,无论是否以任何顺序应用它们。

修改

正如OP正确指出的那样,旋转计算中存在错误。为了完整起见,我编辑了我的答案以显示正确的代码。

private Circle circle;
private Circle oppositeCircle;
private Circle pivot;
private Line spindle;

private Group group;

private Rotate rotateGroup;
double dragInitTheta;
double theta1,theta2;
double angleOfRotation;

private Translate translateGroup;
private double dragTranslateGroupBackupX, dragTranslateGroupBackupY;  
private double dragPivotInitX,dragPivotInitY,systemDragOffsetX,systemDragOffsetY;

@Override
public void start(Stage stage){
    circle = new Circle(150, 150, 30);
    oppositeCircle = new Circle(350, 350, 30);
    pivot = new Circle(250, 250, 5);
    spindle = new Line(150, 150, 350, 350);

    group = new Group(circle,oppositeCircle,pivot,spindle);

/**************** Initializing Shapes **********/
    circle.setFill(Color.GREEN.deriveColor(1, 1, 1, 0.35));
    circle.setStroke(Color.GREEN);
    oppositeCircle.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.35));
    oppositeCircle.setStroke(Color.BLUE);
    pivot.setFill(Color.RED.deriveColor(1, 1, 1, 0.35));
    pivot.setStroke(Color.RED);
    spindle.setStrokeWidth(3);
    spindle.setStroke(Color.BLACK.deriveColor(1, 1, 1, 0.35));
/****************************************************/

/**************** Initializing Transforms **********/
    rotateGroup = new Rotate(0, 0, 0);
    translateGroup = new Translate(0, 0);
/****************************************************/

/**************** Adding Transforms **************/
    group.getTransforms().addAll(translateGroup,rotateGroup);
/****************************************************/
    Pane root = new Pane(group);
    Scene scene = new Scene(root,500,500);

    stage.setScene(scene);
    stage.show();

/** Get angle of point of click with
 * point of rotation, before drag begins **/
    circle.setOnMousePressed(event -> {
        dragInitTheta = angleOfRotation + dragInitTheta;
        double pointOfRotationX = pivot.getCenterX() + translateGroup.getX();
        double pointOfRotationY = pivot.getCenterY() + translateGroup.getY();


        double initialSlope = Math.atan((event.getSceneY() - pointOfRotationY) / (event.getSceneX() - pointOfRotationX));
        theta1 = Math.toDegrees(initialSlope);

        if (event.getSceneX() < pointOfRotationX)
            theta1 = (360 + theta1) % 360;
        else
            theta1 = 180 + theta1;

    });
/********************************************/

/** Get angle of point of drags with
* point of rotation, when the drag is on **/
   circle.setOnMouseDragged(event -> {
        double pointOfRotationX = pivot.getCenterX() + translateGroup.getX();
        double pointOfRotationY = pivot.getCenterY() + translateGroup.getY();
        double finalSlope = Math.atan((event.getSceneY() - pointOfRotationY) / (event.getSceneX() - pointOfRotationX));
        theta2 = Math.toDegrees(finalSlope);

        if (event.getSceneX() < pointOfRotationX)
            theta2 = (360 + theta2) % 360;
        else
            theta2 = 180 + theta2;

        angleOfRotation = theta2 - theta1;
        rotateGroup.setPivotX(pivot.getCenterX());
        rotateGroup.setPivotY(pivot.getCenterY());
        rotateGroup.setAngle(angleOfRotation + dragInitTheta);
   });
/********************************************/

/** Relocate the whole system when the point of
 * rotation is dragged **/
    pivot.setOnMousePressed(event -> {
        dragPivotInitX = event.getSceneX();
        dragPivotInitY = event.getSceneY();

        dragTranslateGroupBackupX = translateGroup.getX();
        dragTranslateGroupBackupY = translateGroup.getY();
    });

    pivot.setOnMouseDragged(event -> {
        systemDragOffsetX = event.getSceneX() - dragPivotInitX;
        systemDragOffsetY = event.getSceneY() - dragPivotInitY;

        translateGroup.setX(dragTranslateGroupBackupX + systemDragOffsetX);
        translateGroup.setY(dragTranslateGroupBackupY + systemDragOffsetY);

    });
/********************************************/

}

答案 1 :(得分:1)

José Pereda 精彩答案!! 更好的方法。
了解很多新东西。
只需要做一个简单的修正。
在计算阻力点的斜率时,还需要考虑(pivot)中(translateGroup.getY(),translateGroup.getX())的偏移量。 .getCenterY(),pivot.getCenterX())

以下是José的代码,其中包含上述更正。

PXOR