JavaFX TextField focusProperty 在 touchScrollEvent 上丢失

JavaFX TextField focusProperty lost on touchScrollEvent

如果用户使用下面显示的代码点击我的扩展 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);
        }
    });

先生,这是非常基本的,当您使用 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 parent 不支持那个假设那么 当用户在触摸您的 Scrollable Node-this 的内容区域后滚动时,您使用此 approach-detect 仅当用户在触摸后尝试滚动时才有效。

//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 parent?

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

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

编辑 2

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

希望对您有所帮助