【问题标题】:JavaFX virtual keyboard overlaps nodesJavaFX 虚拟键盘重叠节点
【发布时间】:2015-03-14 20:53:47
【问题描述】:

我有一个关于在 Windows 8.1 支持触控的电脑上使用虚拟键盘的问题。当文本字段以 java 开关为焦点时,我设法显示虚拟键盘:

-Dcom.sun.javafx.isEmbedded=true -Dcom.sun.javafx.virtualKeyboard=javafx

我在 JavaFX Virtual Keyboard doesn't show1 上找到了方法。

但是当键盘显示出来时,它会与键盘下方的节点重叠。

根据我读到的内容,http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/embed.htm,它不应该那样工作。

有人遇到过这种问题吗?

当我运行测试应用程序时,它全屏显示并显示嵌入式虚拟键盘,因为文本字段具有焦点。在这种情况下,文本字段在我“隐藏”键盘之前是不可见的。我不确定这是不是正确的方法,所以我需要帮助。

java -Dcom.sun.javafx.isEmbedded=true -Dcom.sun.javafx.virtualKeyboard=javafx application.TestVKB

public class TestVKB  extends Application{

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

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

        TextField tfComment = new TextField();
        tfComment.setPromptText("Enter comment");

        BorderPane borderPane = new BorderPane();
        borderPane.setBottom(tfComment);

        Scene scene = new Scene(borderPane);

        stage.setScene(scene);
        stage.setMaximized(true);
        stage.show();
    }
}

点击字段用户名或密码后

如果有任何建议,我将不胜感激。提前致谢。

【问题讨论】:

  • 有重叠的屏幕截图会很有用
  • 我添加了进一步的解释,因为目前我由于缺乏声誉而无法上传图片
  • 现在尝试上传图片。
  • 谢谢。我已经上传了图片。我错过了什么?

标签: java javafx-8 virtual-keyboard


【解决方案1】:

正如我在第一个答案中已经指出的那样,虚拟键盘嵌入在 PopupWindow 中,在不同的阶段创建,并显示在当前阶段的顶部。

-Dcom.sun.javafx.vk.adjustwindow=true 选项起作用,移动主舞台,使控件可见且没有重叠。

但是当这个输入控件位于主舞台的底部时,它会向上移动到屏幕的中心,留下一个很大的空白,显示后面的内容。

第二个答案给出了一个解决方案,将主舞台移动到所需的距离,没有任何间隙,同时考虑到虚拟键盘的淡入/淡出动画。

首先,在我们的场景中,我们在中心添加一个Button,在底部添加一个TextField。通过两个控件,我们可以轻松更改焦点并显示/隐藏键盘。

为了最大化舞台,我将使用getVisualBounds(),以便任务栏可见。

private PopupWindow keyboard;

private final Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
private final Rectangle2D bounds = Screen.getPrimary().getBounds();
private final double taskbarHeight=bounds.getHeight()-visualBounds.getHeight();

@Override
public void start(Stage stage) {
    TextField tfComment = new TextField();
    tfComment.setPromptText("Enter comment");

    BorderPane borderPane = new BorderPane(new Button("Click"));
    borderPane.setBottom(tfComment);

    Scene scene = new Scene(borderPane);

    stage.setScene(scene);
    stage.setX(visualBounds.getMinX());
    stage.setY(visualBounds.getMinY());
    stage.setWidth(visualBounds.getWidth());
    stage.setHeight(visualBounds.getHeight());
    stage.show();
}

我们需要在新舞台出现时找到它。与Scenic View 一样,我们将使用已弃用的方法来获取有效窗口:

private PopupWindow getPopupWindow() {

    @SuppressWarnings("deprecation") 
    final Iterator<Window> windows = Window.impl_getWindows();

    while (windows.hasNext()) {
        final Window window = windows.next();
        if (window instanceof PopupWindow) {
            if(window.getScene()!=null && window.getScene().getRoot()!=null){ 
                Parent root = window.getScene().getRoot();
                if(root.getChildrenUnmodifiable().size()>0){
                    Node popup = root.getChildrenUnmodifiable().get(0);
                    if(popup.lookup(".fxvk")!=null){
                        return (PopupWindow)window;
                    }
                }
            }
            return null;
        }
    }
    return null;
}

当文本框获得焦点时我们会调用这个方法:

    ...
    stage.show();

    tfComment.focusedProperty().addListener((ob,b,b1)->{
        if(keyboard==null){
            keyboard=getPopupWindow();
        }
    });
}

一旦我们有了窗口,我们就可以监听它的位置变化并相应地移动主舞台:

    ....
    stage.show();

    //findWindowExecutor.execute(new WindowTask());
    tfComment.focusedProperty().addListener((ob,b,b1)->{
        if(keyboard==null){
            keyboard=getPopupWindow();

            keyboard.yProperty().addListener(obs->{
                System.out.println("wi "+keyboard.getY());
                Platform.runLater(()->{
                    double y = bounds.getHeight()-taskbarHeight-keyboard.getY();
                    stage.setY(y>0?-y:0);
                });
            });
        }
    });
}

请注意,不是向上移动舞台,而是调整它的大小(如果控件中有足够的空间)。

这将是文本字段获得焦点并完全显示虚拟键盘的情况:

【讨论】:

    【解决方案2】:

    基本上,虚拟键盘嵌入在PopupWindow中,在不同的阶段创建,并显示在当前阶段的顶部,屏幕底部,无论触发键盘的InputControl在哪里位于。

    你可以在 FXVKSkin 类上看到:

    winY.set(screenBounds.getHeight() - VK_HEIGHT);
    

    但是,就在这之后,你可以找到这个:

    if (vkAdjustWindow) {
        adjustWindowPosition(attachedNode);
    }
    

    因此,您可以使用另一个命令行选项来移动舞台,以便节点(在本例中为文本字段)将位于屏幕的中心,您可以在不重叠的情况下键入:

    -Dcom.sun.javafx.vk.adjustwindow=true
    

    请注意,当文本框失去焦点时,键盘会被隐藏,并且舞台会再次移动到原来的位置:

    restoreWindowPosition(oldNode);
    

    我已经成功测试了这个选项,但是当你在屏幕底部有文本字段时,这会将你的舞台底部移动到屏幕的中心,在两个舞台之间留下很大的间隙(你会看到任何你在背景上)。

    我已经设法在新舞台上添加了一个监听器,并根据需要调整了位置。如果你有兴趣,我可以发布它。

    编辑

    请注意,如果舞台最大化,此命令行选项将不起作用。一个简单的解决方案是:

    Rectangle2D bounds = Screen.getPrimary().getBounds();
    stage.setX(bounds.getMinX());
    stage.setY(bounds.getMinY());
    stage.setWidth(bounds.getWidth());
    stage.setHeight(bounds.getHeight());
    stage.show();
    

    【讨论】:

    • 首先感谢您的回复。我已经为调整窗口添加了开关,但没有区别。键盘仍然重叠。你能这么好心并发布你的解决方案吗?非常感谢。
    • 原因是stage.setMaximized(true)。我已经用有效的解决方案编辑了我的答案。
    • 已经尝试过,它确实像您描述的那样工作。舞台设置在屏幕的中心,并在键盘之间留有间隙。你是如何将监听器实现到新阶段的?它将“原始”舞台向上移动只是为了键盘的高度或调整它的大小?
    • 好吧,这取决于你,你可以调整舞台的大小(如果你在控件中有足够的空间)或者你可以将它移动到键盘的高度。
    • 我想弄清楚在哪里/如何在新阶段实现监听器,所以我会知道,键盘是可见的/显示的,但是....你能给我一些指示吗?我应该看 FXVK(Skin) 还是其他地方?
    【解决方案3】:

    我喜欢这个解决方案,但就我而言,我更喜欢使用显示的方法 getPopupWindow 移动键盘,我在文本字段上创建了一个侦听器并直接更改了键盘的位置。

    textField.focusedProperty().addListener((ob, b, b1) -> {
            if (keyboard == null) {
                keyboard = getPopupWindow();
    
                keyboard.setHideOnEscape(Boolean.TRUE);
                keyboard.setAutoHide(Boolean.TRUE);
                keyboard.centerOnScreen();
                keyboard.requestFocus();
                keyboard.sizeToScene();
    
            }
    
            Platform.runLater(() -> {
                keyboard.setY(**NEW_POSITION_OF_KEYBOARD**);
            });
    
    
        });     
    

    【讨论】:

      猜你喜欢
      • 2015-01-02
      • 1970-01-01
      • 2017-07-16
      • 1970-01-01
      • 2015-01-02
      • 1970-01-01
      • 2020-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多