【问题标题】:Keyboard's arrow in JavaFXJavaFX 中的键盘箭头
【发布时间】:2016-10-14 23:30:55
【问题描述】:

又是我!我有一门大炮,现在我正在尝试用键盘的箭头移动它。我不明白为什么代码不起作用?我哪里错了? 谢谢!

public class SchermataGiocoController {

private Parent Menu, Avvio;
private TranslateTransition tt;
private Cannone cannone;
private Aereo aereo;
private Proiettile proiettile;
private RotateTransition rt;

@FXML
private Circle circle;

@FXML
private Button exit;

@FXML
private ImageView cannone_im;

@FXML
private ImageView carro;

@FXML
private AnchorPane SchermataGioco;

@FXML
private ImageView aereo_im;

@FXML
private Button menu;

@FXML
private Button home;

@FXML
void initialize() {
    assert exit != null : "fx:id=\"exit\" was not injected: check your FXML file 'SchermataGioco.fxml'.";
    assert cannone_im != null : "fx:id=\"cannone_im\" was not injected: check your FXML file 'SchermataGioco.fxml'.";
    assert carro != null : "fx:id=\"carro\" was not injected: check your FXML file 'SchermataGioco.fxml'.";
    assert SchermataGioco != null : "fx:id=\"SchermataGioco\" was not injected: check your FXML file 'SchermataGioco.fxml'.";
    assert aereo_im != null : "fx:id=\"aereo_im\" was not injected: check your FXML file 'SchermataGioco.fxml'.";
    assert up != null : "fx:id=\"up\" was not injected: check your FXML file 'SchermataGioco.fxml'.";
    assert menu != null : "fx:id=\"menu\" was not injected: check your FXML file 'SchermataGioco.fxml'.";
    assert down != null : "fx:id=\"down\" was not injected: check your FXML file 'SchermataGioco.fxml'.";
    assert home != null : "fx:id=\"home\" was not injected: check your FXML file 'SchermataGioco.fxml'.";

    //creazione di un oggetto Cannone
    cannone = new Cannone(129, 96, 0, 340); //Cannone = cannone
    //creazione di un oggetto Proiettile 
    proiettile = new Proiettile(16, 16, 0, 340); //proiettile = bullet
    //inizializzazione dei vari metodi
    TranslateTransition();
    moveUp();
    moveDown();
    goHome();       
}
    //Method to change scene and back to home
  public void goHome() {
    home.setOnAction((ActionEvent event) -> {           
        try {               
            FXMLLoader loader = new FXMLLoader();               
            loader.setLocation(Game.class.getResource("/game/view/Avvio.fxml"));         

            Avvio = (Parent) loader.load();                
            home.getScene().getWindow().hide();
        } catch (IOException ioe) {
            ioe.getMessage();
        }           
        Stage stage = new Stage();
        stage.setScene(new Scene(Avvio));
        stage.show();
    });
}
  @FXML
public void moveUp() {       
    cannone_im.getScene().setOnKeyPressed((KeyEvent ke) -> {
        if (ke.getCode().equals(KeyCode.RIGHT)) {
            rt = new RotateTransition(Duration.millis(100), cannone_im);
             if (cannone_im.getRotate() > -70) {
                rt.setAxis(Z_AXIS);                   
                rt.setByAngle(cannone_im.getRotate());                    
                rt.setToAngle(cannone_im.getRotate() - 5);
            } else {                    
                rt.setToAngle(-70);
            }
        }            
        rt.play();
    });
}

错误是 root 不能为空。谢谢!

【问题讨论】:

    标签: java javafx


    【解决方案1】:

    更新后:你的代码有几个问题。

    1) 当Node 获得焦点时触发键事件

    您的ImageView 将没有焦点,因此KeyEvent 永远不会被解雇。

    解决方案:直接将监听器添加到您的Scene。

    这个答案是一个很好的参考:How to write a KeyListener for JavaFX

    2) 你不应该使用setOnKeyReleased

    特别是在游戏中,如果事件只是在您释放键时触发,这真的很令人沮丧。

    解决方案:改用setOnKeyPressed。

    3)当你在初始化时调用moveUp(),它不应该有@FXML注解

    @FXML 注解表示您希望将此函数用作 FXML 文件中的引用。但是这个方法只是创建了监听器而不是监听器本身。

    解决办法:从moveUp()中去掉@FXML注解

    和这个问题有关:Lambda functions with FXML in JavaFX8

    4) 在附加监听器之前,您应该确保sceneProperty 不为空

    解决办法:听一下sceneProperty的ImageView的变化。

    最终的解决方案可能是这样的:

    // The @FXML annotation is removed!
    public void moveUp() {       
        cannone_im.sceneProperty().addListener(new ChangeListener<Scene>() {
    
            @Override
            public void changed(ObservableValue<? extends Scene> observable, Scene oldValue, Scene newValue) {
    
                if(newValue != null){
                    cannone_im.getScene().setOnKeyPressed((KeyEvent ke) -> {
                        if (ke.getCode().equals(KeyCode.RIGHT)) {
                            rt = new RotateTransition(Duration.millis(100), cannone_im);
                            if (cannone_im.getRotate() > -70) {
                                rt.setAxis(Z_AXIS);                    
                                rt.setByAngle(cannone_im.getRotate());
                                 rt.setToAngle(cannone_im.getRotate() - 5);
                            } else {                    
                                rt.setToAngle(-70);
                            }
                        }
                        rt.play();
                    });
                }
            }
        });
    }
    

    【讨论】:

    • 完美!非常感谢!
    • 我试过运行你的代码,但是,如果我写“cannone_im.getScene().setOnKeyPressed((KeyEvent ke)-> .....”我在尝试时会出错在设置我对飞机速度 ecc 的偏好后更改我的场景。为什么?你能告诉我如何在我的代码中添加一个 keyListener 吗?我已经查看了你链接的帖子,但我对 lambda 函数很感兴趣.
    • 请使用当前代码和您遇到的错误更新问题。
    • 为你更新了答案。
    猜你喜欢
    • 1970-01-01
    • 2020-06-20
    • 2018-12-13
    • 1970-01-01
    • 2013-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    相关资源
    最近更新 更多