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
Располагают элементы, соответственно, по горизонтали или вертикали.
Ограничения:
- hgrow (HBox.setHgrow(узел, …)) ctrl + (shift) + space устанавливается, растягивать ли место под соответствующий узел.
- margin - отступы. HBox.setMargin(узел, …)
В общем случае все ограничения устанавливаются так. Т.е. с помощью статических методов класса панельки.
BorderPane
Подходит для расположения узлов слева, справа, сверху, снизу, по центру. Не более пяти, можно меньше, например, только центр и низ.
Ограничения
- alignment - где расположен элемент внутри отведенной области, если его нельзя растянуть на всю область
- margin - отступы для элемента
BorderPane.setMargin(узел, ...)
- обязательное ограничение: где элемент, слева, снизу и т.п.
для указания ограничения, где находится элемент можно написать проще, чем стандартный способ
через BorderPane.set...(узел, где)
. Можно написать: borderPane.setCenter(узел);
,
borderPane.setLeft(узел);
и т.п.
FlowPane
Панелька располагает элементы слева направо, друг за другом, если место по горизонтали не хватает, то элемент переносится на следующую “строку”.
Можно устанавливать пропуски между элементами hgap, vgap.
Можно выкладывать элементы не по горизонтали, а по вертикали, это свойство orientation.
GridPane
Узлы располагаются по сетке.
При добавлении каждого узла
обязательно должно быть указано
ограничение, в каком месте
сетки он находится. Для этого
можно использовать рассмотренный выше способ установки ограничений,
т.е. GridPane.setRowIndex()
GridPane.setColumnIndex()
. Либо можно воспользоваться вспомогательным методом:
gridpane.add(узел, столб, строка)
.
Для подузлов есть и другие ограничения, вот несколько:
- halignment, valignment - где располагать элемент в клетке таблицы, по вертикали и горизонтали
- fillHeight, fillWidth - должны ли элементы растягиваться на весь размер клетки (по умолчанию: должны)
- margin - собственные отступы.
Ограничения для строк, столбцов
Ограничения можно указать еще и для строк и столбцов отдельно. Это нужно, например, если вы хотите, чтобы у вас было два столбика по 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 - элементы располагаются друг над другом. Т.е. элементы перекрывают друг друга.