JavaFX虚拟键盘与节点重叠 [英] JavaFX virtual keyboard overlaps nodes
问题描述
我有一个关于在Windows 8.1上在支持触摸的PC上使用虚拟键盘的问题.当使用java开关对文本字段进行聚焦时,我设法显示了虚拟键盘:
i have a question about using virtual keyboard on touch supported pc with Windows 8.1. I have managed to show the virtual keyboard when textfield is focused with java switch:
-Dcom.sun.javafx.isEmbedded=true -Dcom.sun.javafx.virtualKeyboard=javafx
我在 JavaFX虚拟键盘未显示上找到了解决方法 1 .
I found how to that on JavaFX Virtual Keyboard doesn't show1.
但是当键盘显示出来时,它与键盘下方的节点重叠.
But when the keyboard show's up, it overlapps nodes below the keyboard.
根据我的阅读, http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/embed.htm ,它不应该那样工作.
According to what I read, http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/embed.htm, it should't be working like that.
有人有处理此类问题的经验吗?
Does anyone have any experience with that kind of problem?
当我运行测试应用程序时,它以全屏显示,并且正在显示嵌入式虚拟键盘,因为文本字段具有焦点.在这种情况下,直到我隐藏"键盘后,文本字段才可见.我不确定这是否是正确的方法,所以我需要帮助.
When i run the test application it shows in full screen and embedded virtual keyboard is showing, becasue the textfield has focus. The textfield in this case is not visible until i "hide" the keyboard. I am not sure that this is the right approach so i need help please.
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();
}
}
点击字段后的用户名或密码
After click in field username or password
如果有任何建议,我将不胜感激.预先感谢.
I would be grateful for any advice. Thanks in advance.
推荐答案
正如我在第一个答案中指出的那样,虚拟键盘嵌入在PopupWindow
中,在不同的阶段创建,并显示在顶部您当前阶段的状态.
As I've already pointed out in my first answer, the virtual keyboard is embedded in a PopupWindow
, created in a different stage, and displayed on top of your current stage.
选项-Dcom.sun.javafx.vk.adjustwindow=true
起作用,移动主舞台,以便控件可见并且没有重叠.
The option -Dcom.sun.javafx.vk.adjustwindow=true
works, moving the main stage so the control is visible and there is no overlapping.
但是,当此输入控件位于主界面的底部时,它将向上移动到屏幕的中心,从而留下一个很大的空白区域,以显示后面的内容.
But when this input control is located at the bottom of the main stage, this is moved up to the center of the screen leaving a big empty gap that shows whatever is behind.
第二个答案提供了一种解决方案,可以将主舞台仅移动所需的距离,而没有任何间隙,同时还要考虑虚拟键盘的淡入/淡出动画.
This second answer gives a solution to move the main stage just the required distance, without any gap, also taking into account the fade in/out animations of the virtual keyboard.
对于初学者,在我们的场景中,我们在中心添加Button
,在底部添加TextField
.通过两个控件,我们可以轻松更改焦点并显示/隐藏键盘.
For starters, in our scene, we add a Button
on the center, and the TextField
on the bottom. With two controls we can change the focus easily and show/hide the keyboard.
为了最大化该阶段,我将使用getVisualBounds()
,以便任务栏可见.
To maximize the stage I'll use getVisualBounds()
, so the taskbar can be visible.
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 一样,我们将使用不赞成使用的方法来获取有效的窗口:
We need to find the new stage when it's shown. In the same way as Scenic View, we'll use a deprecated method to get a valid window:
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;
}
当文本字段获得焦点时,我们将调用此方法:
We'll call this method when the textfield gets the focus:
...
stage.show();
tfComment.focusedProperty().addListener((ob,b,b1)->{
if(keyboard==null){
keyboard=getPopupWindow();
}
});
}
一旦有了窗口,我们就可以聆听其位置的变化并相应地移动主舞台:
Once we have the window, we can listen to changes in its position and move the main stage accordingly:
....
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);
});
});
}
});
}
请注意,代替上移舞台,另一个选择是调整其大小(如果控件内有足够的空间).
Note that instead of moving up the stage, another option will be resizing it (if there is enough space within the controls).
在这种情况下,文本字段将成为焦点,并且虚拟键盘将完全显示:
This will be the case where the textfield gets the focus and the virtual keyboard is fully shown:
这篇关于JavaFX虚拟键盘与节点重叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!