web-dev-qa-db-ja.com

javafxの自動サイズ変更とボタンのパディング

レイアウトに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のようなボタンをテキストを失わずに小さくしたい。

6
Jeroen

フォントサイズに基づくサイズ設定

特定のケースでは、パディングや追加のレイアウト制約を使用してボタンのサイズを変更するのではなく、仮想キーボードの親レイアウトコンテナに使用されるフォントサイズ(_-fx-font-size_)を調整してみてください。フォントサイズを大きくすると、ボタンはこの大きいサイズに一致するように自動的に優先サイズを変更します。さらに、すべてのテキストが自動的にレンダリングされ、優先サイズ内に収まり、そのフォントサイズの推奨パディングレイアウトで表示されます(これはおそらくあなたが望むものです)。

ボタンのサイズ変更ルール

基本的に、ボタンのサイズを変更するためのルールは次のとおりです。

  1. ボタンbutton.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE)からmaxSize制約を削除します。ボタンのデフォルトの制約は、ボタンの最大サイズが優先サイズであり、使用可能なスペースを埋めるために自動的に拡大しないため、これが必要です。
  2. ボタンの希望のサイズを希望のサイズに設定します。オンスクリーンキーボードを使用している場合、これを実現する1つの方法は、フォントサイズを増減することです。そうすると、ボタンのサイズが自動的に決まります。
  3. ボタンに追加のパディングが必要な場合は、CSSでは_-fx-padding_を使用するか、コードではbutton.setPadding(new Insets(...))を使用できます。
  4. サイズ変更可能な親にボタンを配置します。
  5. サイズ変更可能な親のサイズが実際に変更されていることを確認します(StackPaneのようなものは、使用可能な領域を埋めるために自動的にサイズ変更されます。AnchorPaneはあまり使用しないため、サイズ変更の動作に慣れていません)。

JavaFXでのレイアウト管理をよりよく理解するために、過去のJavaOneを表示することをお勧めします JavaFX 2.0プレゼンテーションを使用したインターフェイスレイアウト

サイズ変更可能なボタングリッドサンプル

独自の実装を作成し続ける場合は、この サンプルカラーチューザー が役立つ場合があります。色選択の実装は、サイズ変更可能なボタンのサイズ変更可能なグリッドに基づいているため、色選択グリッドで使用可能な領域を変更すると、グリッドとグリッド内のボタンの両方が拡大または縮小します。カラーチューザーのコードはFXMLベースではなく、必要なキーボードを直接実装していませんが、質問で質問したときにボタンの自動サイズ設定を示しています。

chooserlargechoosersmall

JavaFX仮想キーボードの使用を検討してください

JavaFXにはすでに 組み込みの仮想キーボード があります。 組み込みキーボードには、公式にサポートおよび文書化されたパブリックAPIがなく、Javaバージョン間で維持されることが保証されていません。ただし、組み込みの仮想キーボードを使用する方が、独自の仮想キーボードを作成するよりも優れたアプローチである可能性があります。高品質の汎用仮想キーボードを作成することは、かなり難しい作業です(IMO)。

embedded keyboard

Oracle JavaFXフォーラム で、このトピックに関するいくつかの議論があります。

JavaFXはオープンソースであるため、組み込みの仮想キーボードを直接使用しない場合でも、必要に応じて JavaFXソース を確認して実装方法を確認できます。

サンプル仮想キーボードコード

「デスクトップ」環境での組み込み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
_

フォントサイズに基づいてサイズを変更するためのサンプル仮想キーボードコード

keyslargerkeyssmall

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

}
_
24
jewelsea