Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

VBox и HBox

Элементы окна не расставляют по координатам вручную — их кладут в контейнеры (layout panes). Контейнер сам вычисляет, где и какого размера будет каждый узел, и пересчитывает всё при изменении размера окна. Самые простые контейнеры — VBox (столбец) и HBox (строка).

VBox — столбец

VBox ставит узлы друг под другом. Число в конструкторе — расстояние между ними в пикселях:

// src/main/java/com/example/notes/App.java — фрагмент start()
VBox root = new VBox(8);
root.getChildren().addAll(
        new Label("Купить молоко"),
        new Label("Позвонить Олегу"),
        new Label("Прочитать книгу"));
root.setPadding(new Insets(16));

В окне появятся три надписи столбиком в левом верхнем углу. getChildren() — список дочерних узлов контейнера, setPadding задаёт внутренний отступ от краёв окна. Insets лежит в пакете javafx.geometry.

HBox — строка

HBox ставит узлы в ряд слева направо. Узлы можно передать прямо в конструктор после расстояния:

// src/main/java/com/example/notes/App.java — фрагмент start()
HBox root = new HBox(8, new Button("Добавить"), new Button("Удалить"));
root.setAlignment(Pos.CENTER_RIGHT);
root.setPadding(new Insets(16));

Две кнопки встанут рядом у правого края окна, посередине по высоте. setAlignment выравнивает содержимое: Pos.TOP_LEFT (по умолчанию), Pos.CENTER, Pos.BOTTOM_RIGHT и другие.

Растягивание

По умолчанию узел в HBox получает свой «естественный» размер. Чтобы поле ввода заняло всё свободное место, ему задают приоритет роста:

// src/main/java/com/example/notes/App.java — фрагмент start()
HBox.setHgrow(titleField, Priority.ALWAYS);

Для VBox то же делает VBox.setVgrow.

Первый экран записной книжки

Соберём столбец из заголовка, строки с полем и кнопкой и надписи внизу:

// src/main/java/com/example/notes/App.java
package com.example.notes;
 
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
 
public class App extends Application {
 
    @Override
    public void start(Stage stage) {
        Label header = new Label("Мои заметки");
 
        TextField titleField = new TextField();
        titleField.setPromptText("Заголовок заметки");
        Button addButton = new Button("Добавить");
 
        HBox form = new HBox(8, titleField, addButton);
        HBox.setHgrow(titleField, Priority.ALWAYS);
 
        VBox root = new VBox(12, header, form, new Label("Заметок пока нет"));
        root.setPadding(new Insets(16));
 
        stage.setTitle("Заметки");
        stage.setScene(new Scene(root, 640, 480));
        stage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
}

Запустите mvn javafx:run. Сверху — надпись «Мои заметки», под ней поле ввода и кнопка «Добавить». Поле растянуто на всю ширину и растёт вместе с окном, кнопка остаётся у правого края. Ниже — «Заметок пока нет». При запуске курсор уже стоит в поле, поэтому подсказка «Заголовок заметки» скрыта: серый текст появится, когда фокус уйдёт на кнопку, например по клавише Tab.

Частая ошибка

Один и тот же узел нельзя добавить в контейнер дважды. Код new VBox(label, label) падает с ошибкой java.lang.IllegalArgumentException: Children: duplicate children added: parent = VBox@101b462. Узел может стоять только в одном месте графа сцены: если нужны две одинаковые надписи, создайте два объекта Label.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.