JavaFX

Библиотека для разработки графических приложений, была встроена в JDK 8, сейчас скачивается отдельно.

Отдаленно похожа на Flash и Silverlight. Раньше в Java использовалась библиотека Swing, она и дальше будет поддерживаться, но не будет развиваться. В Интернете очень много примеров про Swing.

Интерфейс, создаваемый в JavaFX не нативен, зато везде выглядит одинаково. JavaFX позволяет использовать в приложения стандартные элементы управления, например, кнопки, списки, прогресс бары, полосы прокрутки и т.п. Кроме этого, можно рисовать (как на Canvas из JavaScript), анимировать (элементы управления, рисунки). Можно стилизовать интерфейс с помощью CSS.

Можно задавать интерфейсы с помощью языка FXML, т.е. примерно как на HTML. FXML мы использовать не будем, вместо этого будем задавать интерфейс кодом на Java. Среды разработки типа IDEA, NetBeans позволяют рисовать интерфейс визуально - этим тоже не будем пользоваться.

Как устроено окно графического интерфейса

Node

Интерфейс состоит из Node (узлы). Есть один внешний Node, содержащий весь интерфейс. У узлов могут быть дети (children), подузлы. Например, Node “панель инструментов” может содержать подузлы “кнопка сохранения”, “кнопка открытия”, “подпанель”. Node “Подпанель” тоже может содержать подузлы в виде кнопок. Node “кнопка” не содержит подузлов, по крайней мере тех, которыми нам нужно пользоваться.

Parent extends Node

Это узлы, у которых есть подузлы. Например, панельки для кнопок имеют подузлы. А вот класс ImageView extends Node, не является Parent.

Group extends Parent, Region extends Parent

Group содержат подузлы и не имеют собственного размера. Размер группы автоматически вычисляется по размеру содержимого. Если двигать узлы внутри группы, то будет меняться и ее размер.

Region имеет размер (высоту, ширину), этот размер можно изменять. И Region можно стилизовать, указывая цвет фона и стиль рамки.

Control extends Region, Pane extends Region

Control - это элемент управления, например кнопка (Button), метка (Label). Pane - это панелька, на которой располагаются Node. При этом Pane позволяют изменять набор своих children. Pane позволяет управлять расположением children. Например, бывает HBox, VBox - это Pane, которые располагают детей, соотвественно, по горизонтали и по вертикали. Другой пример - BorderPane - в этой панели может быть пять детей. Слева, сверху, справа, снизу, посередине. Панелькой Pane тоже можно пользоваться, не обязательно именно HBox, VBox. Pane сама по себе никак не располагает компоненты, вам нужно будет вручную указывать координаты всех подузлов.

Preferred size

У всех Region хранится предпочитаемый размер. Это размер, который этот регион считает для себя оптимальным, чтобы показать все свое содержимое.

Например, для кнопки Preferred size - это размер (высота, ширина), при котором в нее помещается весь текст на кнопке, и не остается свободного пространства.

Когда Pane располагает элементы внутри себя, она часто использует предпочитаемые размеры для подузлов.

Ограничения (constraints)

С каждым узлом связан набор constraint. Мы сами задаем эти constraints, чтобы указать внешнему контейнеру (панельке Pane, которая содержит этот узел), как его располагать. Разные виды Pane понимают разные constraint. Например, BorderPane в качестве constraint просит указывать положение: сверху, снизу, слева, справа, посередине. VBox интересуется, где элемент хочет находиться: слева, справа, в середине, растянуться. (Можно VBox глобально настроить, чтобы, например, все подузлы были по центру, но можно отдельным узлам дать отдельные constraint).

Pane в JavaFX

https://docs.oracle.com/javase/13/javafx/api/javafx/scene/layout/Pane.html см. Direct known subclasses

HBox, VBox

Располагают элементы, соответственно, по горизонтали или вертикали.

Ограничения:

В общем случае все ограничения устанавливаются так. Т.е. с помощью статических методов класса панельки.

BorderPane

Подходит для расположения узлов слева, справа, сверху, снизу, по центру. Не более пяти, можно меньше, например, только центр и низ.

Ограничения

для указания ограничения, где находится элемент можно написать проще, чем стандартный способ через BorderPane.set...(узел, где). Можно написать: borderPane.setCenter(узел);, borderPane.setLeft(узел); и т.п.

FlowPane

Панелька располагает элементы слева направо, друг за другом, если место по горизонтали не хватает, то элемент переносится на следующую “строку”.

Можно устанавливать пропуски между элементами hgap, vgap.

Можно выкладывать элементы не по горизонтали, а по вертикали, это свойство orientation.

GridPane

Узлы располагаются по сетке. При добавлении каждого узла обязательно должно быть указано ограничение, в каком месте сетки он находится. Для этого можно использовать рассмотренный выше способ установки ограничений, т.е. GridPane.setRowIndex() GridPane.setColumnIndex(). Либо можно воспользоваться вспомогательным методом: gridpane.add(узел, столб, строка).

Для подузлов есть и другие ограничения, вот несколько:

Ограничения для строк, столбцов

Ограничения можно указать еще и для строк и столбцов отдельно. Это нужно, например, если вы хотите, чтобы у вас было два столбика по 50% ширины. Или вы хотите, чтобы первый столбец имел ширину, которую предпочитают его дети. А второй столбец - растягивался по ширине.

Как этого добиться:

    GridPane gridpane = new GridPane();

    // можно указать при создании ограничения для столбца его минимальный, предпочитаемый
    // и максимальный размеры.
    ColumnConstraints column1 = new ColumnConstraints(100, 100, Double.MAX_VALUE);
    // после создания ограничения для столбца можно его изменить, например,
    // заставить растягиваться по горизонтали
    column1.setHgrow(Priority.ALWAYS);

    // или можно указать только предпочитаемый размер
    ColumnConstraints column2 = new ColumnConstraints(100);

    // можно вообще ничего не указывать при создании ограничения на столбец,
    // если вы не хотите его ограничивать
    ColumnConstraints column0 = new ColumnConstraints();

    //добавить ограничения в панель
    gridpane.getColumnConstraints().addAll(column0, column1, column2);

еще несколько Pane

TilePane - примерно как FlowPane, но все элементы одного размера. Подходит для галереии изображений, например. Или списка элементов папки.

StackPane - элементы располагаются друг над другом. Т.е. элементы перекрывают друг друга.