JavaFX学习笔记——用法技巧总结(五)

如何正确监听键盘事件

问题

对于一个事件的触发,这里摘取JavaFx China对于常用的鼠标事件和键盘事件的描述


当一个动作发生时,系统根据内部规则决定哪一个Node是事件目标。规则如下:

● 对于键盘事件,事件目标是已获取焦点的Node。

● 对于鼠标事件,事件目标是光标所在位置处的Node。


对于一个可输入可聚焦的类似于textField的对象,键盘事件的使用也完全没有任何问题,因为用的是ActionEvent,不再赘述。

但倘若有如下场景,需要为一个不可聚焦的circle注册一个Y快捷键,让你单击Y键使得circle半径增大一倍,你可能会编写如下代码


     Circle circle = new Circle(100,100,50);

        Pane pane = new Pane();

        ObservableList<Node> list = pane.getChildren();

        list.add(circle);
       
        //注册快捷键明显用lambda表达式创建匿名对象更合适
        circle.setOnKeyTyped(e->{

         if(e.getCode() == KeyCode.Y)

                circle.setRadius(circle.getRadius()*2);

});


运行后界面如下

你会发现如何按Y键这个圆也没有变大

分析

你通过查询API文档中对setOnKeyType的描述,


Defines a function to be called when this Node or its child Node has input focus and a key has been typed. The function is called only if the event hasn't been already consumed during its capturing or bubbling phase.


你会留意到红色注明的地方,猜想事件无响应的原因就是没有focus,对circle调用输出isFocused()结果为false,证实了我们的猜想


  System.out.println(circle.isFocused())


机智的你可能会查到使用requestFocus来手动让circle获取焦点,从而可以正常监听键盘事件,但结果……


  circle.requestFocus();

  System.out.println(circle.isFocused())



纳尼!明明上一句代码requestFocus紧接着输出怎么还是false,md一定是requestFocus没用,这JavaFX什么鬼!

并非requestFocus无用,而是JavaFX的另一个机制在作怪(具体测试方法就是不断变换上述代码的位置):焦点只能在stage.show()了之后才能获取,而且默认由stage.setScene(scene)中的scene获取。所以circle.requestFocus()要在scene.setOnKeyType中进行才有用

结论

1.对于快键键这类需要全局监听的键盘事件,对scene进行setOnKeyType,然后根据e.getCode的值来调用相应的方法

2.对于确实需要让该子节点获得焦点的情况,需要其他可顺利触发的事件的处理器中node.requestFocus()来开启这个node子节点的键盘监听

猜你喜欢

转载自blog.csdn.net/weixin_40861847/article/details/84225676