JavaFX如何在单独的类中使用AnimationTimer?

问题描述 投票:-1回答:1

我已经看到很多在Main类中编写AnimationTimer和KeyListener的示例,但在另一个类中却没有。

我已经在“ VolleyController”中尝试过How to write a KeyListener for JavaFX,但是我不知道为什么它不起作用。

[首先,我使用KeyEvent来移动图像,就像第一个代码一样。第三个代码是我的Main类。我想重写第二种代码一样移动图像的方法。

但是我遇到了用第二代码编写的错误。我该如何处理?

import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;

public class VolleyController implements EventHandler<KeyEvent> {
    double pika1LocationY = 556;
    double pika2LocationY = 556;
    double pika1LocationX = 0;
    double pika2LocationX = 1050;

    boolean pika2MoveLeft = false;  
    boolean pika2MoveRight = false;
    boolean pika1MoveLeft = false;
    boolean pika1MoveRight = false;

    @FXML
    ImageView pika1,pika2,ball;

    @Override
    public void handle(KeyEvent e) {
        switch (e.getCode()) {
        case ESCAPE:
            Main.currentStage.setScene(Main.menuScene);
            break;
        case UP:
            break;
        case LEFT:
            pika2MoveLeft = true;
            break;
        case RIGHT:
            pika2MoveRight = true;
            break;
        case T:
            break;
        case F:
            pika1MoveLeft = true;
            break;
        case H:
            pika1MoveRight = true;
            break;

        }   
        move();
    }

    public void released(KeyEvent r) {
        switch (r.getCode()) {
        case LEFT:
            pika2MoveLeft = false;
            break;
        case RIGHT:
            pika2MoveRight = false;
            break;
        case F:
            pika1MoveLeft = false;
            break;
        case H:
            pika1MoveRight = false;
            break;
        }

    }

    public void move() {
        if(pika1MoveLeft && pika1.getLayoutX()>=0) 
            pika1.setLayoutX(pika1.getLayoutX()-10);
        if(pika1MoveRight && pika1.getLayoutX()<=440 ) 
            pika1.setLayoutX(pika1.getLayoutX()+10);
        if(pika2MoveLeft && pika2.getLayoutX()>600) 
            pika2.setLayoutX(pika2.getLayoutX()-10);
        if(pika2MoveRight && pika2.getLayoutX()<1050) 
            pika2.setLayoutX(pika2.getLayoutX()+10);
    }

}
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;

public class VolleyController implements EventHandler<KeyEvent> {
    double pika1LocationY = 556;
    double pika2LocationY = 556;
    double pika1LocationX = 0;
    double pika2LocationX = 1050;

    boolean pika2MoveLeft = false;  
    boolean pika2MoveRight = false;
    boolean pika1MoveLeft = false;
    boolean pika1MoveRight = false;

    @FXML
    ImageView pika1,pika2,ball;
                    //this gives me a syntax error about getScene(), but the following did not
    Main.currentStage.getScene().setOnKeyPressed(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent e) {

            switch (e.getCode()) {
            case ESCAPE:
                Main.currentStage.setScene(Main.menuScene);
                break;
            case UP:
                break;
            case LEFT:
                pika2MoveLeft = true;
                break;
            case RIGHT:
                pika2MoveRight = true;
                break;
            case T:
                break;
            case F:
                pika1MoveLeft = true;
                break;
            case H:
                pika1MoveRight = true;
                break;

            }   
    }}); //this told me to delete tokens

                  //this did not give me a syntax error
    Main.currentStage.getScene().setOnKeyReleased(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent r) {
            switch (r.getCode()) {
            case LEFT:
                pika2MoveLeft = false;
                break;
            case RIGHT:
                pika2MoveRight = false;
                break;
            case F:
                pika1MoveLeft = false;
                break;
            case H:
                pika1MoveRight = false;
                break;
            }
        }
    });

    AnimationTimer timer=new AnimationTimer() {
        @Override
        public void handle(long now)
        {   
            int pika1dx=0, pika2dx=0;

            if(pika1MoveLeft) pika1dx-=10;
            if(pika1MoveRight) pika1dx+=10;
            if(pika2MoveLeft) pika2dx-=10;
            if(pika2MoveLeft) pika2dx-=10;

            PikaMoveBy(pika1dx,pika2dx);

        }
    };

    timer.start();
}
public void PikaMoveBy(int pika1dx,int pika2dx)
{
    if(pika1dx==0 || pika2dx==0) return;

    final double pika1cx=pika1.getBoundsInLocal().getWidth()/2; 
    final double pika2cx=pika2.getBoundsInLocal().getWidth()/2;

    double pika1x=pika1cx+pika1.getLayoutX()+pika1dx;
    double pika2x=pika2cx+pika2.getLayoutX()+pika2dx;

    PikaMoveTo(pika1x, pika2x);

}

public void PikaMoveTo(double pika1x, double pika2x)
{
    final double pika1cx=pika1.getBoundsInLocal().getWidth()/2;
    final double pika2cx=pika2.getBoundsInLocal().getWidth()/2;

    if(pika1x-pika1cx>=0 && pika1x+pika1cx<450 && pika2x-pika2cx>600 && pika2x+pika2cx<1050)
    {
        pika1.relocate(pika1x-pika1cx, pika1_lct_y);
        pika2.relocate(pika2x-pika2cx, pika2_lct_y);
    }
}
import java.net.URL;
import java.util.ResourceBundle;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class Main extends Application {

    public static Stage currentStage;
    public static Scene menuScene;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        currentStage=primaryStage;
        Parent root=FXMLLoader.load(getClass().getResource("Menu.fxml"));
        Scene MenuScene = new Scene(root);
        currentStage.setScene(MenuScene); //use setScene() to switch the scene
        currentStage.setTitle("PikaVolley");
        currentStage.show();

    }
}
animation javafx keyevent
1个回答
0
投票

要获取键句柄和AnimationTimer,请使用简单的FXML(Volley.fxml):

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>

<VBox spacing="10.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="test.VolleyController">
   <children>
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="248.0" text="Press Start.Use Arows to set direction" />
      <Pane  prefHeight="250.0" prefWidth="250.0">
         <children>
            <ImageView fx:id="ball" fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true" />
         </children>
      </Pane>
      <Button fx:id="startBtn" mnemonicParsing="false" onAction="#start" text="Start" />
   </children>
</VBox>

及其控制器(请参阅注释):

import javafx.animation.AnimationTimer;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;

public class VolleyController implements EventHandler<KeyEvent> {

    //always use publicly available resources when posting
    private static final String BALL = "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/32x32/Circle_Red.png";
    boolean moveRight = false, moveLeft = false, moveUp = false, moveDown = false;
    private static final int DX = 1, DY = 1;

    @FXML
    ImageView ball;
    @FXML 
    Button startBtn;

    @FXML
    void initialize(){
        ball.setImage(new Image(BALL)); //initialize image view
    }

    @FXML
    void start(){

        ball.getScene().setOnKeyPressed(this);  //add Key press and release handlers to scene
        ball.getScene().setOnKeyReleased(this);

        //construct and invoke AnimationTimer
        AnimationTimer timer = new AnimationTimer(){
            @Override
            public void handle(long now) {
                move();  //repeatedly invoke move
            }
        };
        timer.start();

        startBtn.setDisable(true);
    }

    @Override
    public void handle(KeyEvent e) {
         moveRight = false; moveLeft = false;  moveUp = false; moveDown = false;
        //change movement directions based on key events
        switch (e.getCode()) {
            case UP:
                moveUp = true;
                break;
            case LEFT:
                moveLeft = true;
                break;
            case RIGHT:
                moveRight = true;
                break;
            case DOWN:
                moveDown = true;
                break;
        }
    }

    //move if any of the direction control booleans is true
    private void move() {
        if(moveLeft) {
            ball.setLayoutX(ball.getLayoutX()-DX);
        }else  if(moveRight) {
            ball.setLayoutX(ball.getLayoutX()+DX);
        }else if(moveDown) {
            ball.setLayoutY(ball.getLayoutY()+DY);
        }else if(moveUp) {
            ball.setLayoutY(ball.getLayoutY()-DY);
        }
    }
}

使用:进行测试

public class Main extends Application {

    @Override
    public void start(Stage currentStage) throws Exception {

        Parent root=FXMLLoader.load(getClass().getResource("Volley.fxml"));
        currentStage.setScene(new Scene(root));
        currentStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.