javafx 自动调整大小和按钮填充

标签 java javafx fxml

我正在尝试使用 Javafx 制作一个屏幕键盘用于布局。我正在使用场景生成器来制作 FXML 文件。

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.text.*?>

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="186.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
  <children>
    <VBox layoutX="0.0" layoutY="0.0" prefHeight="186.0" prefWidth="600.0" rotate="0.0" spacing="2.0">
      <children>
        <HBox minHeight="33.0" prefHeight="33.0" prefWidth="600.0" spacing="2.0">
          <children>
            <Label maxWidth="-Infinity" prefHeight="33.0" prefWidth="35.0" text="Milk" textAlignment="CENTER" />
            <Label maxWidth="-Infinity" prefHeight="33.0" text="Mister" />
            <Label maxWidth="-Infinity" prefHeight="35.0" text="Minimum" />
          </children>
          <padding>
            <Insets left="5.0" />
          </padding>
        </HBox>
        <HBox prefHeight="29.0" prefWidth="600.0">
          <children>
            <Button minWidth="29.0" mnemonicParsing="false" prefHeight="27.0" prefWidth="29.0" text="Esc" textAlignment="CENTER" underline="false">
              <font>
                <Font size="9.0" />
              </font>
            </Button>
            <Button mnemonicParsing="false" text="`" textAlignment="CENTER" />
            <Button mnemonicParsing="false" text="1" />
            <Button mnemonicParsing="false" text="2" />
            <Button mnemonicParsing="false" text="3" />
            <Button mnemonicParsing="false" text="4" />
            <Button mnemonicParsing="false" text="5" />
            <Button mnemonicParsing="false" text="6" />
            <Button mnemonicParsing="false" text="7" />
            <Button mnemonicParsing="false" text="9" />
            <Button mnemonicParsing="false" text="0" />
            <Button mnemonicParsing="false" text="-" />
            <Button mnemonicParsing="false" text="=" />
            <Button mnemonicParsing="false" text="Backspace" />
          </children>
        </HBox>
        <HBox prefHeight="57.0" prefWidth="600.0">
          <children>
            <VBox minHeight="50.0" prefHeight="78.0" prefWidth="505.0" HBox.hgrow="ALWAYS">
              <children>
                <HBox prefHeight="29.0" prefWidth="-1.0">
                  <children>
                    <Button mnemonicParsing="false" prefHeight="27.0" text="Tab" />
                    <Button mnemonicParsing="false" text="q" />
                    <Button mnemonicParsing="false" text="w" />
                    <Button mnemonicParsing="false" text="e" />
                    <Button mnemonicParsing="false" text="r" />
                    <Button mnemonicParsing="false" text="t" />
                    <Button mnemonicParsing="false" text="y" />
                    <Button mnemonicParsing="false" text="u" />
                    <Button mnemonicParsing="false" text="i" />
                    <Button mnemonicParsing="false" text="o" />
                    <Button mnemonicParsing="false" text="p" />
                    <Button mnemonicParsing="false" text="[" />
                    <Button mnemonicParsing="false" text="]" />
                  </children>
                </HBox>
                <HBox minHeight="-1.0" prefHeight="28.0" prefWidth="-1.0">
                  <children>
                    <Button mnemonicParsing="false" prefWidth="71.0" text="Caps" />
                    <Button mnemonicParsing="false" text="a" />
                    <Button mnemonicParsing="false" text="s" />
                    <Button mnemonicParsing="false" text="d" />
                    <Button mnemonicParsing="false" text="f" />
                    <Button mnemonicParsing="false" text="g" />
                    <Button mnemonicParsing="false" text="h" />
                    <Button mnemonicParsing="false" text="j" />
                    <Button mnemonicParsing="false" text="k" />
                    <Button mnemonicParsing="false" text="l" />
                    <Button mnemonicParsing="false" text=";" />
                    <Button mnemonicParsing="false" text="'" />
                    <Button mnemonicParsing="false" text="\\" />
                  </children>
                </HBox>
              </children>
            </VBox>
            <Button mnemonicParsing="false" prefHeight="57.0" prefWidth="132.0" text="Enter" />
          </children>
        </HBox>
        <HBox prefHeight="27.000099999997474" prefWidth="600.0">
          <children>
            <Button mnemonicParsing="false" prefWidth="85.0" text="Shift" />
            <Button mnemonicParsing="false" text="z" />
            <Button mnemonicParsing="false" text="x" />
            <Button mnemonicParsing="false" text="c" />
            <Button mnemonicParsing="false" text="v" />
            <Button mnemonicParsing="false" text="b" />
            <Button mnemonicParsing="false" text="n" />
            <Button mnemonicParsing="false" text="m" />
            <Button mnemonicParsing="false" text="," />
            <Button mnemonicParsing="false" text="." />
            <Button mnemonicParsing="false" text="/" />
            <Button mnemonicParsing="false" text="^" />
            <Button mnemonicParsing="false" prefWidth="56.0" text="Shift" />
            <Button mnemonicParsing="false" text="Del" />
          </children>
        </HBox>
        <HBox prefHeight="29.0" prefWidth="600.0" VBox.vgrow="ALWAYS">
          <children>
            <Button mnemonicParsing="false" text="Fn" />
            <Button mnemonicParsing="false" text="Ctrl">
              <HBox.margin>
                <Insets />
              </HBox.margin>
            </Button>
            <Button mnemonicParsing="false" text="Win" />
            <Button mnemonicParsing="false" text="Alt" />
            <Button mnemonicParsing="false" prefWidth="105.0" text="Space" HBox.hgrow="ALWAYS" />
            <Button mnemonicParsing="false" text="Alt" />
            <Button mnemonicParsing="false" prefWidth="-1.0" text="Ctrl" textAlignment="LEFT" />
            <Button mnemonicParsing="false" text="&lt;" />
            <Button mnemonicParsing="false" text="v" />
            <Button mnemonicParsing="false" text="&gt;" />
            <Button mnemonicParsing="false" text="Menu" />
          </children>
        </HBox>
      </children>
    </VBox>
  </children>
</AnchorPane>

看起来像这样:

enter image description here

但是当窗口大小改变时,内容却不会改变。我希望按钮增大/减小尺寸,直到适合窗口。开启Hgrow和Vgrow不起作用。

而且我找不到如何设置按钮上的填充。我想在不丢失文本的情况下使 Ctrl 这样的按钮变小。

最佳答案

根据字体大小调整大小

对于您的特定情况,不要尝试使用填充或其他布局约束来调整按钮大小,而是尝试调整用于虚拟的父布局容器的字体大小(-fx-font-size)键盘。如果您将字体尺寸调大,按钮将自动更改其首选尺寸以匹配此较大尺寸,并且所有文本将自动呈现并适合首选尺寸,并显示在该字体尺寸的建议填充布局中(这可能就是您想要的)。

按钮大小调整规则

基本上,调整按钮大小的规则是:

  1. 从按钮中删除 maxSize 约束,button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE)。这是必需的,因为按钮的默认约束是其最大尺寸是其首选尺寸,因此它不会自动增长以填充可用空间。
  2. 将按钮的首选尺寸设置为您想要的尺寸。当您使用屏幕键盘时,实现此目的的一种方法是增大或减小字体大小,然后按钮将自动调整大小。
  3. 如果您想在按钮中添加额外的填充,可以在 CSS 中使用 -fx-padding 或在代码中使用 button.setPadding(new Insets(...)) .
  4. 将按钮放在可调整大小的父级中。
  5. 确保可调整大小的父级实际调整了大小(像 StackPane 这样的东西会自动调整大小以填充可用区域,我不太使用 AnchorPane,所以我不熟悉它的调整大小行为)。

为了更好地理解 JavaFX 中的布局管理,我建议查看过去的 JavaOne Interface Layout with JavaFX 2.0 presentation

可调整大小的按钮网格示例

如果您希望继续尝试创建自己的实现,此 sample color chooser可能有帮助。颜色选择实现基于可调整大小的按钮的可调整大小的网格,因此当您更改颜色选择器网格的可用区域时,网格和网格中的按钮都会扩展或收缩。颜色选择器的代码不是基于 FXML 的,也不是直接实现您想要的键盘,但它确实演示了您在问题中询问时自动调整按钮大小的功能。

chooserlarge choosersmall

考虑使用 JavaFX 虚拟键盘

JavaFX 已经有 built-in virtual keyboard内置键盘没有官方支持和记录的公共(public) API,并且不保证在 Java 版本之间得到维护。但是,使用内置虚拟键盘可能仍然是比使用内置虚拟键盘更好的方法尝试创建自己的。创建高质量的通用虚拟键盘是一项相当艰巨的任务(IMO)。

embedded keyboard

Oracle JavaFX forums 上有一些关于此主题的讨论。 .

JavaFX是开源的,所以即使你不直接使用内置的虚拟键盘,也可以查看JavaFX source如果您愿意的话,看看它是如何实现的。

示例虚拟键盘代码

演示在“桌面”环境中使用内置 JavaFX 虚拟键盘的示例代码。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class EmbeddedSample extends Application {
    @Override public void start(Stage stage) {
        stage.setScene(new Scene(new StackPane(new TextField("xyzzy")), 200, 100));
        stage.getScene().setOnMouseClicked(e -> stage.hide());
        stage.show();
    }

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

运行示例代码如下:

java -Dcom.sun.javafx.virtualKeyboard=javafx -Dcom.sun.javafx.touch=true EmbeddedSample

根据字体大小调整大小的示例虚拟键盘代码

keyslarger keyssmall

键盘.css

.key {
    -fx-base: antiquewhite;
}

.key-row {
    -fx-spacing: 0.333333em;
}

.keyboard {
    -fx-spacing: 0.333333em;
    -fx-padding: 0.333333em;
    -fx-font-family: monospace;
}

ResizableKeyboardSample.java

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.geometry.*;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class ResizableKeyboardSample extends Application {
    public static void main(String[] args) throws Exception {
        launch(args);
    }

    String[] chars = {
            "qwertyuiop",
            "asdfghjkl",
            "zxcvbnm"
    };

    public void start(final Stage stage) throws Exception {
        Keyboard keyboard = new Keyboard();

        VBox layout = new VBox(20);
        layout.setPadding(new Insets(10));
        layout.getChildren().setAll(
                createControls(keyboard),
                keyboard
        );

        Scene scene = new Scene(layout, 1000, 400);
        scene.getStylesheets().add(
                getClass().getResource(
                        "keyboard.css"
                ).toExternalForm()
        );

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

    private Node createControls(Keyboard keyboard) {
        Slider fontSize = new Slider(8, 40, Font.getDefault().getSize());
        keyboard.fontSizeProperty().bind(fontSize.valueProperty());
        fontSize.setShowTickLabels(true);
        fontSize.setShowTickMarks(true);
        fontSize.setMajorTickUnit(2);
        fontSize.setMinorTickCount(0);

        Label typedData = new Label();
        keyboard.lastKeyTextProperty().addListener((observable, oldText, newText) ->
                typedData.setText(typedData.getText() + newText)
        );

        VBox layout = new VBox(10);
        layout.getChildren().setAll(
                new Label("Keyboard Size"),
                fontSize,
                typedData
        );
        layout.setMinSize(VBox.USE_PREF_SIZE, VBox.USE_PREF_SIZE);

        return layout;
    }

    class Keyboard extends VBox {
        private DoubleProperty fontSize = new SimpleDoubleProperty(Font.getDefault().getSize());

        public double getFontSize() {
            return fontSize.get();
        }

        public DoubleProperty fontSizeProperty() {
            return fontSize;
        }

        public void setFontSize(double fontSize) {
            this.fontSize.set(fontSize);
        }

        private ReadOnlyStringWrapper lastKeyText = new ReadOnlyStringWrapper();

        public String getLastKeyText() {
            return lastKeyText.get();
        }

        public ReadOnlyStringProperty lastKeyTextProperty() {
            return lastKeyText.getReadOnlyProperty();
        }

        public Keyboard() {
            setAlignment(Pos.BOTTOM_CENTER);
            setMinSize(VBox.USE_PREF_SIZE, VBox.USE_PREF_SIZE);
            getStyleClass().add("keyboard");

            onFontSizeChange(fontSize.getValue());
            fontSize.addListener((observable, oldValue, newValue) ->
                onFontSizeChange(newValue)
            );

            for (String row: chars) {
                HBox keyRow = new HBox();
                keyRow.getStyleClass().add("key-row");

                keyRow.setAlignment(Pos.CENTER);
                for (char c: row.toCharArray()) {
                    KeyButton key = new KeyButton(Character.toString(c));
                    keyRow.getChildren().add(key);
                }
                getChildren().add(keyRow);
            }
        }

        private void onFontSizeChange(Number newValue) {
            setStyle("-fx-font-size: " + newValue + "px;");
        }

        class KeyButton extends Button {
            public KeyButton(String text) {
                super(text);
                getStyleClass().add("key");

                setMinSize(Button.USE_PREF_SIZE, Button.USE_PREF_SIZE);
                setMaxSize(Button.USE_PREF_SIZE, Button.USE_PREF_SIZE);

                setOnAction(event -> lastKeyText.set(text));
            }
        }
    }

}

关于javafx 自动调整大小和按钮填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23229149/

相关文章:

java - 即使使用 MathContext 也会出现非终止十进制错误

java - 从具有 BIT 列的 HSQLDB 表中进行选择

java - JavaFX 2 提供哪些功能?与 Java Applet 或 Silverlight 等相关技术相比,其实现有多成熟?

java - 使用带有 while 循环的 ToggleButton JavaFX

java - 使用 GMapsFX 和 FXML 时如何初始化 Google map API key ?

Java:JScrollPane 覆盖 JFrame 光标设置,但仅在启动时

java - 有没有办法修复这个无效的模块名称错误?

java - 在 FXML Controller 类中找不到可注入(inject)字段

JavaFX 屏幕分辨率缩放

java - 具有自定义属性的 JCR 新节点类型