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

时间:2014-04-22 20:06:19

标签: java javafx fxml

我试图用Javafx制作屏幕键盘进行布局。我使用Scene Builder制作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这样的按钮。

1 个答案:

答案 0 :(得分:22)

根据字体大小调整大小

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

按钮调整规则

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

  1. 从按钮button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE)中删除maxSize约束。这是必需的,因为按钮的默认约束是其最大大小是其首选大小,因此它不会自动增长以填充可用空间。
  2. 将按钮的首选大小设置为您想要的大小。当您使用屏幕键盘时,实现此目的的一种方法是增加或减少字体大小,然后按钮将自动调整大小。
  3. 如果您想在按钮中添加其他填充,则可以在CSS中使用-fx-padding或在代码中使用button.setPadding(new Insets(...))
  4. 将按钮放在可调整大小的父级中。
  5. 确保实际调整了可调整大小的父级(类似StackPane的内容会自动调整大小以填充可用区域,我不会非常使用AnchorPane,因此我不熟悉其调整大小的行为)。
  6. 为了更好地理解JavaFX中的布局管理,我建议您查看过去的JavaOne Interface Layout with JavaFX 2.0 presentation

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

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

    chooserlarge choosersmall

    考虑使用JavaFX虚拟键盘

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

    embedded keyboard

    Oracle JavaFX forums上就此主题进行了一些讨论。

    JavaFX是开源的,因此即使您不直接使用内置虚拟键盘,也可以查看JavaFX source以了解如何实施。

    示例虚拟键盘代码

    示例代码演示在桌面上使用内置JavaFX虚拟键盘&#34;环境。

    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

    keyboard.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));
                }
            }
        }
    
    }