【问题标题】:JavaFX TextField focusProperty lost on touchScrollEventJavaFX TextField focusProperty 在 touchScrollEvent 上丢失
【发布时间】:2016-02-02 07:48:16
【问题描述】:

如果用户使用下面显示的代码点击我的扩展TextField,我将显示一个键盘。用鼠标滚动时,您不会失去焦点到TextField,但是当通过触摸滚动时,焦点会丢失——当然键盘也会消失。有没有办法在 touchScroll 上获得与 mouseScroll 上相同的行为?如果用户通过触摸滚动,我不希望键盘消失!

focusedProperty().addListener(new ChangeListener<Boolean>() {

        @Override
        public void changed(final ObservableValue<? extends Boolean> observable, final Boolean oldValue,
                final Boolean newValue) {

                KeyboardUtils.INSTANCE.setVisible(newValue);
        }
    });

【问题讨论】:

    标签: java scroll javafx touch focus


    【解决方案1】:

    这是非常基本的先生,当您使用 Touchscroll 滚动时,您肯定会触摸可滚动的 Pane 区域,并且通过触摸 Pane requestFocus(),因此您的 TextField 将失去焦点。

    所以要解决它,如果您通过使用该窗格或节点的滚动侦听器检测到触摸,或者转到 setOnTouchStationary() 或 setOnTouchReleased(),则将焦点发送回您的 TextField,以帮助调整您的可见性键盘而不是躺在TextField 的焦点上。

    编辑

    试试这个

    Node lastFocusedNode =null; // lastly known node to have focus
    //now every node or child in your ScrollPane or Scrollable parent 
    //that you care about will have a focusable listener-including
    // your textfield
    textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
    @Override
    public void changed(
            ObservableValue<? extends Boolean> observable,
                    Boolean oldValue, Boolean newValue) {
                    if(!newValue){//if they loose focus
                        lastFocusedNode = textField;
                        //if they loose focus attach them to lastFocusedNode
                    }
                }
            });
     //the above saves you iterations
    

    然后,当您的 ScrollPane/scrollable 节点接收焦点时,您将它们设置为 lastFocusedNode,因为它只是允许滚动。

    sp.focusedProperty().addListener(new InvalidationListener() {               
                @Override
                public void invalidated(Observable observable) {
                    if (lastFocusedNode != null) {
                        lastFocusedNode.requestFocus();
                    }
                }
            });
    

    以上假设您的 ScrollPane 除了滚动之外不会做任何消耗......

    如果您的 ScrollPane/scrollable 父级不采用该假设,那么 您采用这种方法 - 检测用户在触摸 Scrollable Node 的内容区域后何时滚动 - 这仅在用户在触摸后尝试滚动时才有效。

    //approach loaded
    final InvalidationListener lis = new InvalidationListener() {               
    @Override
    public void invalidated(Observable observable) {
        //here it is changing
        if(sp.isFocused())
            lastFocusedNode.requestFocus();//take the focus away
        }
    };
    

    使用上述失效监听器,您将其设置在 hvalueProperty() 和 vvalueProperty() 或您的 ScrollPane - 您使用的是哪个 Scrollable 父级?

    sp.hvalueProperty().addListener(lis);
    sp.vvalueProperty().addListener(lis);
    

    那么你就完成了。以上任何一种解决方案都会导致没问题

    编辑 2

    据我所知,TouchEvent 适用于支持触控的计算机,所以也许可以使用MouseEvent,您可以检测到Pane.setOnMousePressed(); 等等等

    希望对你有帮助

    【讨论】:

    • 感谢您的回答,所以对于每个 TouchEvent,我需要遍历窗格的所有子项以获取已聚焦的节点? (由于 TouchEvent 请求 Focus,这仍然可能吗?然后在发布时我 requestFocus 呢?但这真的不是表现不佳吗??
    • 请您发表评论吗?
    • 非常感谢,这真的很有帮助
    猜你喜欢
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多