代码之家  ›  专栏  ›  技术社区  ›  yukashima huksay

如何在javafx中更改按键的旋转方向

  •  0
  • yukashima huksay  · 技术社区  · 9 年前

    我有两个圆圈,如果按右键,我想顺时针旋转它们,如果按左键,则逆时针旋转,但我的代码无法工作。

    import javafx.animation.*;
    import javafx.application.Application;
    import javafx.beans.property.SimpleIntegerProperty;
    import javafx.geometry.Bounds;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.effect.GaussianBlur;
    import javafx.scene.layout.*;
    import javafx.scene.media.Media;
    import javafx.scene.media.MediaPlayer;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Circle;
    import javafx.scene.shape.Rectangle;
    import javafx.scene.shape.Shape;
    import javafx.scene.text.Font;
    import javafx.scene.transform.Rotate;
    import javafx.stage.Popup;
    import javafx.stage.Stage;
    import javafx.util.Duration;
    
    import static java.lang.Math.cos;
    import static java.lang.Math.sin;
    
    public class Main extends Application {
        public static final double CIRCLES_CENTER_X = 600;
        public static final double CIRCLES_CENTER_Y = 450;
        public static final double CIRCLES_RADIUS = 15;
        public static final double CIRCLES_DISTANCE = 300;
        public static final double GAME_HEIGHT = 700;
        public static final double GAME_WIDTH = 1200; 
    
        private Stage primaryStage;
    
        public static void main(String[] args) {
            Application.launch(args);
        }
    
        @Override
        public void start(Stage primaryStage) {
            this.primaryStage = primaryStage;
            primaryStage.setMinWidth(GAME_WIDTH);
            primaryStage.setMinHeight(GAME_HEIGHT);
                        final Scene scene;
            BorderPane root = new BorderPane();
            scene = new Scene(root, Main.GAME_WIDTH, Main.GAME_HEIGHT); 
    
            Circle orangeCircle = new Circle(Main.CIRCLES_CENTER_X + Main.CIRCLES_DISTANCE / 2 * cos(0),
                    Main.CIRCLES_CENTER_Y + Main.CIRCLES_DISTANCE / 2 * sin(0),
                    Main.CIRCLES_RADIUS, Color.ORANGE);
            Circle yellowCircle = new Circle(Main.CIRCLES_CENTER_X - Main.CIRCLES_DISTANCE / 2 * cos(0),
                    Main.CIRCLES_CENTER_Y - Main.CIRCLES_DISTANCE / 2 * sin(0),
                    Main.CIRCLES_RADIUS, Color.YELLOW);
    
            Pane game = new Pane(orangeCircle, yellowCircle); 
            root.setCenter(game);
    
            SimpleIntegerProperty angle = new SimpleIntegerProperty(0);
            root.setOnKeyPressed(ke -> {
                if (ke.getCode().toString().equals("RIGHT")) {
                    angle.set(360);
                }
                if (ke.getCode().toString().equals("LEFT")) {
                    angle.set(-360);
                }
            });
            root.setOnKeyReleased(ke -> {
                if (ke.getCode().toString().equals("RIGHT")) {
                    angle.set(0);
                }
                if (ke.getCode().toString().equals("LEFT")) {
                    angle.set(0);
                }
            });
    
            Rotate orangeCircleRotation = new Rotate(0, Main.CIRCLES_CENTER_X, Main.CIRCLES_CENTER_Y);
            orangeCircle.getTransforms().add(orangeCircleRotation);
            Rotate yellowCircleRotation = new Rotate(0, Main.CIRCLES_CENTER_X, Main.CIRCLES_CENTER_Y);
            yellowCircle.getTransforms().add(yellowCircleRotation);
            Timeline rotationAnimation = new Timeline();
            rotationAnimation.setCycleCount(Timeline.INDEFINITE);
            angle.addListener((ov, old_val, new_val) -> {
                        System.out.println("fk");
                        rotationAnimation.stop();
                        while (rotationAnimation.getKeyFrames().size() > 0) {
                            rotationAnimation.getKeyFrames().remove(0);
                        }
                        rotationAnimation.getKeyFrames().add(
                                new KeyFrame(Duration.millis(2000),
                                        new KeyValue(orangeCircleRotation.angleProperty(), angle.getValue())));
                        rotationAnimation.getKeyFrames().add(
                                new KeyFrame(Duration.millis(2000),
                                        new KeyValue(yellowCircleRotation.angleProperty(), angle.getValue())));
                        rotationAnimation.play();
                    }
            );
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
    
        public Stage getPrimaryStage() {
            return primaryStage;
        }
    }
    

    它几乎可以正常工作,但当我按下一个键并释放它时,圆圈不会停止。他们只是开始向后转,直到最后一个旋转改变点,并不断重复,所以当我再次按键时,有时会跳。(因为向后转弯已经到了终点,从起点开始)(很难解释!你必须亲眼看到!) 有人知道如何解决或实现这一点吗?

    1 回复  |  直到 9 年前
        1
  •  1
  •   James_D    9 年前

    动画正在进行时,我不会尝试操纵关键帧。相反,您可以暂停/播放动画并更改速率。这里唯一的“问题”是,如果暂停,动画似乎会忽略速率的变化,因此您需要调用 play() 之前 setRate(...) .

    以下是修改后的SSCCE:

    import static java.lang.Math.cos;
    import static java.lang.Math.sin;
    
    import javafx.animation.KeyFrame;
    import javafx.animation.KeyValue;
    import javafx.animation.Timeline;
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.input.KeyCode;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.Pane;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Circle;
    import javafx.scene.transform.Rotate;
    import javafx.stage.Stage;
    import javafx.util.Duration;
    
    public class RotatingCircles extends Application {
        public static final double CIRCLES_CENTER_X = 600;
        public static final double CIRCLES_CENTER_Y = 450;
        public static final double CIRCLES_RADIUS = 15;
        public static final double CIRCLES_DISTANCE = 300;
        public static final double GAME_HEIGHT = 700;
        public static final double GAME_WIDTH = 1200; 
    
        private Stage primaryStage;
    
        public static void main(String[] args) {
            Application.launch(args);
        }
    
        @Override
        public void start(Stage primaryStage) {
            this.primaryStage = primaryStage;
            primaryStage.setMinWidth(GAME_WIDTH);
            primaryStage.setMinHeight(GAME_HEIGHT);
                        final Scene scene;
            BorderPane root = new BorderPane();
            scene = new Scene(root, GAME_WIDTH, GAME_HEIGHT); 
    
            Circle orangeCircle = new Circle(CIRCLES_CENTER_X + CIRCLES_DISTANCE / 2 * cos(0),
                    CIRCLES_CENTER_Y + CIRCLES_DISTANCE / 2 * sin(0),
                    CIRCLES_RADIUS, Color.ORANGE);
            Circle yellowCircle = new Circle(CIRCLES_CENTER_X - CIRCLES_DISTANCE / 2 * cos(0),
                    CIRCLES_CENTER_Y - CIRCLES_DISTANCE / 2 * sin(0),
                    CIRCLES_RADIUS, Color.YELLOW);
    
            Pane game = new Pane(orangeCircle, yellowCircle); 
            root.setCenter(game);
    
            Rotate orangeCircleRotation = new Rotate(0, CIRCLES_CENTER_X, CIRCLES_CENTER_Y);
            orangeCircle.getTransforms().add(orangeCircleRotation);
            Rotate yellowCircleRotation = new Rotate(0, CIRCLES_CENTER_X, CIRCLES_CENTER_Y);
            yellowCircle.getTransforms().add(yellowCircleRotation);
            Timeline rotationAnimation = new Timeline();
            rotationAnimation.setCycleCount(Timeline.INDEFINITE);
            rotationAnimation.getKeyFrames().add(new KeyFrame(Duration.seconds(2), new KeyValue(orangeCircleRotation.angleProperty(), 360)));
            rotationAnimation.getKeyFrames().add(new KeyFrame(Duration.seconds(2), new KeyValue(yellowCircleRotation.angleProperty(), 360)));
    
            root.setOnKeyPressed(ke -> {
               if (ke.getCode() == KeyCode.RIGHT) {
                   rotationAnimation.play();
                   rotationAnimation.setRate(1);
               } else if (ke.getCode() == KeyCode.LEFT) {
                   rotationAnimation.play();
                   rotationAnimation.setRate(-1);
               }
            });
            root.setOnKeyReleased(ke -> {
                rotationAnimation.pause();
            });
    
    
            primaryStage.setScene(scene);
            primaryStage.show();
    
            root.requestFocus();
        }
    
    
        public Stage getPrimaryStage() {
            return primaryStage;
        }
    }
    

    顺便说一句,在这段代码中,你真的不需要两个单独的旋转,因为它们是相同的。只需创建一个旋转并将其添加到两个圆的变换列表中。当然,在您的真实代码中可能会有所不同。。。