javafx автоматическое изменение размера и заполнение кнопок
Я пытаюсь сделать экранную клавиатуру с 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="<" />
<Button mnemonicParsing="false" text="v" />
<Button mnemonicParsing="false" text=">" />
<Button mnemonicParsing="false" text="Menu" />
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>
Который выглядит так:
Но когда размер окна изменяется, содержимое не изменяется. Я хочу, чтобы кнопки увеличивали / уменьшали размер, пока он не уместится в окне. Включение Хгроу и Вгроу не сработало.
И я не могу найти, как установить отступы на кнопках. Я хочу сделать кнопки типа Ctrl меньше, не теряя текст.
1 ответ
Размер в зависимости от размера шрифта
Для вашего конкретного случая вместо того, чтобы пытаться изменить размер кнопок с помощью отступов или дополнительных ограничений макета, попробуйте настроить размер шрифта (-fx-font-size
) используется для родительского контейнера макета для вашей виртуальной клавиатуры. Если вы увеличите размер шрифта, кнопки автоматически изменят свой предпочтительный размер, чтобы соответствовать этому большему размеру, плюс весь текст будет автоматически визуализирован и подогнан под предпочтительный размер и будет отображаться в предлагаемом макете отступа для этого размера шрифта (что, вероятно, то, что вы хотите).
Правила изменения размера кнопок
В основном правила для изменения размера кнопки:
- Удалить ограничение maxSize из кнопки,
button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE)
, Это необходимо, поскольку ограничение по умолчанию для кнопки заключается в том, что ее максимальный размер равен предпочтительному размеру, поэтому он не увеличивается автоматически, заполняя доступное пространство. - Получите предпочтительный размер кнопки, чтобы быть размером, который вы хотите. Поскольку вы делаете экранную клавиатуру, один из способов добиться этого - увеличить или уменьшить размер шрифта, после чего кнопка автоматически изменит свой размер.
- Если вы хотите дополнительный отступ в кнопке, вы можете использовать
-fx-padding
в CSS илиbutton.setPadding(new Insets(...))
в коде. - Поместите кнопку в родительский размер с изменяемым размером.
- Удостоверьтесь, что изменяемый размер родительского элемента действительно изменен (что-то вроде StackPane будет автоматически изменено, чтобы заполнить доступную область, я не очень часто использую AnchorPane, поэтому я не знаком с его поведением изменения размера).
Чтобы лучше понять управление компоновкой в JavaFX, я рекомендую просмотреть предыдущую макет интерфейса JavaOne с презентацией JavaFX 2.0.
Образец сетки с изменяемым размером кнопки
Если вы хотите продолжить пытаться создать свою собственную реализацию, этот пример выбора цвета может быть полезным. Реализация выбора цвета основана на сетке с изменяемыми размерами и кнопками с изменяемыми размерами, поэтому при изменении области, доступной для сетки выбора цвета, сетка и кнопки в сетке расширяются или сжимаются. Код для выбора цвета не основан на FXML, и при этом он не реализует непосредственно клавиатуру, которая вам нужна, но он демонстрирует автоматическое изменение размера кнопок, как вы спрашивали в своем вопросе.
Рассмотрите возможность использования виртуальной клавиатуры JavaFX
JavaFX уже имеет встроенную виртуальную клавиатуру. Встроенная клавиатура не имеет официально поддерживаемого и документированного публичного API и не поддерживается между версиями Java. Тем не менее, использование встроенной виртуальной клавиатуры может быть лучше, чем пытаться создать свою собственную. Создание качественной виртуальной клавиатуры общего назначения - довольно сложная задача (IMO).
На форумах 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
Пример кода виртуальной клавиатуры для изменения размера в зависимости от размера шрифта
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));
}
}
}
}