在JavaFX中对齐虚拟键盘的键[重复]

Posted

技术标签:

【中文标题】在JavaFX中对齐虚拟键盘的键[重复]【英文标题】:Aligning keys for a virtual keyboard in JavaFX [duplicate] 【发布时间】:2021-07-14 17:32:20 【问题描述】:

我在 JavaFX 中为一个刽子手风格的游戏设计了一个简单的虚拟键盘。唯一的问题是我无法正确对齐第二行和第三行,就像真正的键盘设计一样(例如,A 键几乎在 Q 和 W 的中间)。 键盘是使用 GridPane 简单实现的,每个字符都有一个按钮。 有没有办法插入一点空白? 老实说,我想过堆叠三个GridPane,每行一个,然后添加正确的偏移量作为空白文本,但这在我看来有点强迫,所以我想知道是否有一种“更清洁”的做法它。 这是我的代码:

package gui;

import game.GameManager;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;

public class VirtualKeyboard extends HBox 
    private final GridPane pane;
    private final GameManager gameManager;
    private static final char[] orderedKeys = 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P',
                                                'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L',
                                                'Z', 'X', 'C', 'V', 'B', 'N', 'M';

    public VirtualKeyboard(GameManager gameManager) 
        this.pane = new GridPane();
        this.gameManager = gameManager;
        this.getChildren().add(pane);
        setup();
    

    @Override
    public void setPrefSize(double v, double v1) 
        super.setPrefSize(v, v1);
        pane.setPrefSize(v, v1);
    

    private void setup() 
        var qButton = new Button("Q");
        var wButton = new Button("W");
        var eButton = new Button("E");
        var rButton = new Button("R");
        var tButton = new Button("T");
        var yButton = new Button("Y");
        var uButton = new Button("U");
        var iButton = new Button("I");
        var oButton = new Button("O");
        var pButton = new Button("P");
        var aButton = new Button("A");
        var sButton = new Button("S");
        var dButton = new Button("D");
        var fButton = new Button("F");
        var gButton = new Button("G");
        var hButton = new Button("H");
        var jButton = new Button("J");
        var kButton = new Button("K");
        var lButton = new Button("L");
        var zButton = new Button("Z");
        var xButton = new Button("X");
        var cButton = new Button("C");
        var vButton = new Button("V");
        var bButton = new Button("B");
        var nButton = new Button("N");
        var mButton = new Button("M ");

        setRowIndexes(0, qButton, wButton, eButton, rButton, tButton, yButton, uButton, iButton, oButton, pButton);
        setRowIndexes(1, aButton, sButton, dButton, fButton, gButton, hButton, jButton, kButton, lButton);
        setRowIndexes(2, zButton, xButton, cButton, vButton, bButton, nButton, mButton);

        buttonSetup(qButton, wButton, eButton, rButton, tButton, yButton, uButton, iButton, oButton, pButton,
                aButton, sButton, dButton, fButton, gButton, hButton, jButton, kButton, lButton,
                zButton, xButton, cButton, vButton, bButton, nButton, mButton);

        pane.getChildren().addAll(
                qButton, wButton, eButton, rButton, tButton, yButton, uButton, iButton, oButton, pButton,
                aButton, sButton, dButton, fButton, gButton, hButton, jButton, kButton, lButton,
                zButton, xButton, cButton, vButton, bButton, nButton, mButton);
    

    private void buttonSetup(Button... buttons) 
        var keyCounter = 0;
        for (Button button : buttons) 
            button.setPrefSize(60.0, 60.0);
            int finalKeyCounter = keyCounter;
            button.setOnMouseClicked(mouseEvent -> gameManager.guess(orderedKeys[finalKeyCounter]));
            button.getStyleClass().add("keyboard-button");
            button.getStylesheets().add("file:stylesheets/virtual-keyboard.css");
            keyCounter++;
            //TODO: add in stylesheet and remove
            button.setStyle("-fx-font-size: 22; -fx-font-weight: bold");

        
    

    private void setRowIndexes(int row, Button... buttons) 
        var column = 0;
        for (Button button : buttons) 
            GridPane.setConstraints(button, column, row);
            column++;
        
    


【问题讨论】:

你可以简化这个问题来改进它,以及添加你尝试过的东西(比如你想要避免的 3 个单独的堆叠网格窗格) 很抱歉,我没有说我已经这么想并想避免它,它完全不在我的脑海里。我编辑了这个问题。 您可能希望使用SceneBuilder 直观地创建您的设计,然后将结果保存到 FXML。即使您最终没有使用 FXML,它也可以帮助您了解布局窗格和约束的组合可以使您获得所需的行为。 请注意,JavaFX 有一个in-built virtual keyboard,它可以是shown and hidden on demand,在您的情况下可能可用也可能不可用。 这个答案也是displays a custom virtual keyboard,显示可能适合您的目的,或者作为起点可能会有点过于简单。 【参考方案1】:

我认为使用单个网格是不正确的,因为第一个元素总是垂直对齐的。

也许尝试使用 3 个堆叠的 GridPanes 并修改您添加的第一个元素的大小以偏移“A”键的起始位置。像这样构造的label 是隐形的吗?

 Label label = new Label();
 GridPane.setConstraints(label, ...);

生成的网格看起来有点像这样

GRID1 =                        [Q]...
GRID2 = [invisible skinny label][A][S]...
GRID3 = [invisible less skinny   ][Z][X]...

如果您真正想要使用单个网格,您可能需要确定垂直对齐是否是网格的必需属性,在这种情况下,您必须跨越多个每个按钮位置的网格单元格。 跨越多个单元格是我不确定 GridPane 是否可以实现的属性。(但我还是解释了这个想法,所以也许你可以发明它:))

这是一个单一的网格布局的想法,其中跨越单元格是可能的。按钮跨度为 4 宽,“A-row-spacer”跨度为 1 宽,“Z-row-spacer”跨度为 3 宽。如果标准宽度为 4 宽,则 W 不会出现在 Z 上方。

|   |   |
[Q ][W ]...
_[A ][S ]...
___[Z ][X ]...
|   |   |

【讨论】:

老实说我已经想过这样做,但我希望你们能引导我找到一个更简单的解决方案,因为堆叠三个 GridPanes 对我来说似乎有点强迫。不过我是编程新手,所以如果你说这不是一个糟糕的解决方案,我肯定会尝试。 插入带有空白标签的单元格可以解决问题吗?你知道我是否可以连续修改一个单元格的宽度吗? 您的想法可能是正确的,但由于单元格共享所有相同的尺寸,例如,A 键将与 W 键对齐(这也是不正确的)。实际上,在上面的评论中,我在问是否可以连续调整一个单元格的大小(这样在上面的答案中调整“下划线”的大小将最终将 A 放在 Q 和 W 之间的中间,并且不只是在 W 下。 是的,一个元素可以跨越 GridPane 中的多个单元格,但是如果单元格共享相同的宽度,对齐问题仍然相同:A 最终会位于 W 之下. 您可以将列数加倍,并使每个键跨两列。然后在备用行上启动第 1 列而不是第 0 列中的键。或者,并且可能更清洁,您可以在备用行上使用 translate X 转换。这也会产生部分移位,更接近真实键盘。

以上是关于在JavaFX中对齐虚拟键盘的键[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用javascript捕获在android虚拟键盘上键入的键

游戏手柄 + 键盘虚拟摇杆

在 Android 虚拟键盘上捕获 KeyEvent

android中的虚拟键盘问题

Android - 在画布上创建虚拟键盘

使用 C#/Windows API 的虚拟键盘 - 发送键输入,但不获取焦点