JavaFX — это мощный инструмент для создания кроссплатформенных графических интерфейсов на Java. В этой статье разберём, как разработать простое приложение на JavaFX с использованием визуального редактора в двух популярных средах разработки. Также рассмотрим альтернативный подход — создание интерфейса вручную, без визуального редактора.
Что такое Java и JavaFX
Java — один из самых популярных языков программирования, появившийся в 1995 году. Его разработала компания Sun Microsystems, позднее приобретённая Oracle.
Код на Java транслируется в байт-код, который выполняется в среде виртуальной машины Java (JVM). Благодаря этому Java-приложения работают на любых операционных системах, где установлена JVM.
JavaFX появился в 2008 году как современная альтернатива Java Swing для создания графических интерфейсов. До восьмой версии Java и JavaFX распространялись вместе, но с Java 9 их разделили, и теперь JavaFX устанавливается отдельно.
Чтобы установить Java, перейдите на официальный сайт, выберите свою операционную систему и скачайте установочный пакет. Также можно воспользоваться OpenJDK — его открытой реализацией. JavaFX отдельно устанавливать не потребуется, так как при создании проектов мы будем использовать архетипы, автоматически загружающие необходимые зависимости.
Создаем приложение в среде IntelliJ IDEA
IntelliJ IDEA — это одна из самых популярных сред разработки на Java. С ее помощью можно создавать не только десктопные и веб-приложения, но и мобильные приложения для Android.
Установка среды и создание проекта
Скачать среду разработки можно здесь. Для работы потребуется версия Community Edition, которая распространяется бесплатно и разрабатывается сообществом. На указанной странице нужно выбрать свою операционную систему и загрузить установочный файл.
Для пользователей Windows и macOS процесс установки не вызывает сложностей, так как среда распространяется в виде стандартных установочных файлов .exe и .dmg. Достаточно запустить загруженный файл и следовать инструкциям.
На Linux среда разработки предоставляется в виде архива .tar.gz. Его необходимо загрузить и распаковать в удобное место, обычно в домашнюю директорию. После распаковки появится новая папка, в которой нужно перейти в каталог bin и запустить файл idea или idea.sh.
После успешного запуска среды разработки на экране появится окно приветствия.

Чтобы добавить значок запуска IDE в меню, нужно нажать на значок шестеренки в левом нижнем углу и выбрать пункт «Create Desktop Entry» в открывшемся списке. После этого можно перейти к созданию проекта. Нажав «New Project», откроется окно выбора типа проекта.

В левой панели в разделе Generators выбираем JavaFX. В правой части окна в поле Name вводим название проекта. В нашем случае это генератор примеров из таблицы умножения, поэтому на скриншоте уже указано соответствующее имя. Поле Location оставляем без изменений.
Далее выбираем язык — Java, а в качестве сборочной системы — Maven. Поле Group можно оставить по умолчанию, а два последних поля заполнятся автоматически. После этого нажимаем Next и переходим к следующему шагу.

Здесь ничего выбирать не нужно. Нажимаем на «Create» и перед нами появляется наш проект:

Теперь можно переходить к конструированию интерфейса.
Интерфейс
Пользовательский интерфейс приложения описывается в файле hello-view.fxml. Вот так он выглядит в среде разработки:

Внизу окна расположены две вкладки: Text и Scene Builder. Они позволяют переключаться между режимами отображения FXML-файла. По умолчанию файл открывается в текстовом режиме. Если переключиться на Scene Builder, интерфейс отобразится в визуальном формате.

Перед нами открывается визуальный редактор, позволяющий быстро создать пользовательский интерфейс, просто перетаскивая необходимые компоненты из палитры в левой панели на макет в центре.
Наш генератор примеров будет формировать новое задание при нажатии на кнопку. Сам пример будет отображаться в текстовой метке, а пользователь вводит ответ в специальное текстовое поле.
Взглянув на левую панель, можно увидеть структуру интерфейса. Сейчас он состоит из текстовой метки (Label) и кнопки (Button), которые упакованы в контейнер VBox. Этот контейнер располагает элементы в вертикальном порядке. Метка и кнопка уже добавлены, но пока не хватает текстового поля для ввода ответа.
Чтобы его добавить, раскрываем список Controls в левой панели, находим TextField и перетаскиваем его в верхнюю часть макета. В результате должно получиться следующее:

Теперь настроим размер текста в Label. Выделяем метку в структуре интерфейса, переходим в правую панель и в разделе Font выбираем стиль System Bold с размером 36px.

Для кнопки настроим отображаемый текст. Выделим ее в структуре и в правой панели в разделе Text пропишем слово «Проверить»:

Интерфейс готов. Теперь перейдем к логике приложения.
Логика
Если сейчас запустить наше приложение, то мы увидим это:

А после нажатия на кнопку окно примет такой вид:

Это неудивительно, ведь в интерфейс мы добавили только текстовое поле TextField, а сам исходный код на Java пока не изменился. Теперь пришло время внести необходимые правки!
Логика приложения хранится в двух файлах: HelloApplication.java и HelloController.java. Нас сейчас интересует именно HelloController, так как именно в нём реализовано управление интерфейсом.
Кстати, при необходимости файлы (включая FXML-файл) можно переименовать, чтобы их имена лучше соответствовали проекту. В среде разработки есть встроенный инструмент для переименования, который автоматически обновляет все ссылки на изменённый файл. Для этого нужно выделить файл в левой панели, нажать правой кнопкой мыши, выбрать Rename, ввести новое имя и нажать Refactor.
Теперь, сразу после объявления класса HelloController, необходимо объявить все UI-компоненты и переменные, которые будут использоваться в коде.
@FXML private Label l; @FXML private TextField tf; private int result;
Директива @FXML указывает, что объекты l и tf должны быть определены в FXML-файле и представлены там как идентификаторы. Вот содержимое FXML-файла:
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.geometry.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.text.*?> <VBox alignment="CENTER" prefHeight="485.0" prefWidth="487.0" spacing="20.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/17.0.12" fx:controller="io.jfxdevelop.multiplicationtable.HelloController"> <padding> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> </padding> <TextField fx:id="tf"/> <Label fx:id="l"> <font> <Font name="System Bold" size="36.0" /> </font></Label> <Button onAction="#onHelloButtonClick" text="Проверить" /> </VBox>
Не забывайте и об импортируемых классах в начале исходного кода. Здесь разработчики IDE постарались на славу! Импорт для Label уже присутствует, а вот импорт для TextField среда предложит добавить автоматически. Для этого достаточно использовать комбинацию клавиш Alt+Enter.
Теперь переходим к следующему шагу. У нас уже есть метод для обработки нажатий на кнопку, который называется onHelloButtonClick. Удалим содержимое этого метода, добавленное по умолчанию, и заменим его на следующий код:
int us; try { us = Integer.parseInt(this.tf.getText()); } catch (NumberFormatException e) { this.alertWindow("","Введите число!","Ошибка"); this.tf.requestFocus(); return; } if (us==result){ this.alertWindow("ВЕРНО!", this.l.getText() + "=" + us,"Результат"); }else { this.alertWindow("НЕВЕРНО!", "Верный ответ:\n " + this.l.getText() + "=" + this.result,"Результат"); } l.setText(multiplicationGenerator()); tf.setText(""); tf.requestFocus();
Среда выделит красным имена методов alertWindow и multiplicationGenerator, так как они ещё не определены. Давайте добавим эти методы:
private String multiplicationGenerator() { int a,b; final Random random = new Random(); do { a = random.nextInt(10); b = random.nextInt(10); }while (a==0||b==0||a==1||b==1); this.result = a * b; return a + " * " + b; } private void alertWindow(final String s, final String s1,final String s2) { final Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setTitle(s2); alert.setHeaderText(s); alert.setContentText(s1); alert.showAndWait(); }
Теперь давайте разберемся, как всё это работает. В обработчике нажатий происходит считывание ответа, введенного пользователем. Это осуществляется с помощью метода parseInt, который используется в конструкции try-catch. Такая конструкция необходима для обработки возможных исключений, например, если пользователь введет буквы или другие символы вместо цифр. После этого введенное значение сравнивается с правильным ответом на пример. В зависимости от результата выводится соответствующее сообщение с помощью метода alertWindow.
В методе alertWindow создается стандартное диалоговое окно, которое присутствует во многих фреймворках. В JavaFX оно создается с использованием класса Alert. В нашем случае мы используем информационный тип окна. Методы setTitle, setHeaderText и setContentText задают заголовок окна и два сообщения. Окно запускается методом showAndWait.
После того как пользователь закроет диалоговое окно, генерируется новый пример. Генерацию примера выполняет метод multiplicationGenerator. Случайные числа генерируются с помощью класса Random, а именно с помощью метода nextInt, который вызывается для объекта random. В цикле do-while случайные значения присваиваются переменным a и b, из которых затем формируется пример на умножение и возвращается как результат работы метода.
Но это еще не всё! Нам нужно сделать так, чтобы генерация примера происходила сразу же после запуска программы. Как это можно реализовать? В этом нам поможет метод initialize. Добавим его:
@Override public void initialize(URL url, ResourceBundle resourceBundle) { l.setText(multiplicationGenerator()); tf.requestFocus(); }
Теперь дополним строку с объявлением класса контроллера таким образом:
public class HelloController implements Initializable
Секция импортов после всех наших действий должна выглядеть так:
import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Alert; import javafx.scene.control.Label; import javafx.scene.control.TextField; import java.net.URL; import java.util.Random; import java.util.ResourceBundle;
Чтобы в заголовке окна отображалось название приложения, потребуется прописать его в файле HelloApplication.java. Вот так это должно выглядеть:
Scene scene = new Scene(fxmlLoader.load(), 320, 240); stage.setTitle("Таблица Умножения"); stage.setScene(scene);
Теперь можно попробовать запустить наш проект. Жмем на зеленый треугольник в тулбаре и видим примерно это:

Введем верный ответ. Получим:

А на следующий пример ответим неправильно:

Все работает, как надо! Далее рассмотрим создание приложений на JavaFX в среде Apache NetBeans.
Создаем приложение в среде Apache NetBeans
Apache NetBeans — ещё одна популярная среда разработки, которая поддерживает не только разработку приложений на Java, но и другие проекты, например, приложения на языке PHP.
Установка среды и создание проекта
Скачать среду можно на официальном сайте. Все просто: в разделе Installers and Packages выберите установщик или пакет, подходящий для вашей операционной системы. Затем скачайте его и установите любым удобным способом. После установки запускаем среду и начинаем создавать проект. Вот как выглядит главное окно нашей IDE:

Нажимаем на «New Project». Перед нами откроется такое окно:

Выбираем нужный тип проекта. В нашем случае это проект на JavaFX с разметкой FXML, создаваемый через архетипы сборочной системы Maven. Эти архетипы автоматически загружают все необходимые зависимости для проекта. Нажимаем «Next», и перед нами открывается следующее окно:

Как видно, название нашего проекта — DogAndCat. Это простое демонстрационное приложение, которое отображает изображения собаки и кота. Заполняем только поле с именем проекта, все остальные поля заполняются автоматически. Нажимаем кнопку Finish, и перед нами открывается проект. В данном случае открыт файл интерфейса:

Далее займемся созданием этого самого интерфейса.
Интерфейс
В отличие от IntelliJ IDEA, в Apache NetBeans нет встроенного визуального редактора для FXML. Поэтому нам придется использовать внешний редактор — Gluon Scene Builder, который можно скачать отсюда. Это тот же самый Builder, который поставляется с IntelliJ IDEA.
Интерфейс нашего приложения будет двухстраничным. В проекте есть два файла с описанием интерфейса (primary.fxml и secondary.fxml) и два соответствующих контроллера (PrimaryController и SecondaryController). Запускаем наш только что установленный Scene Builder:

И откроем в нем файл primary.fxml:

Дополним макет всего лишь одним компонентом. В палитре найдем контрол ImageView и перенесем его в верхнюю часть контейнера VBox. Должно получиться вот так:

Теперь добавим изображение. Его можно скачать с этого сайта. Рядом с fxml-файлами создадим папку images и в нее поместим изображение. При помощи поля Image в правой панели добавим изображение в ImageView. Макет теперь будет выглядеть так:

Сохраним макет при помощи меню File или при помощи комбинации клавиш Ctrl+S. Теперь открываем второй файл разметки и делаем все то же самое. Только изображение берем другое с того же сайта. В итоге, второй макет будет таким:

Логику приложения оставим без изменений. Запустим программу и увидим первую страницу:

Нажимаем на кнопку и перемещаемся на вторую страницу:

Если сейчас нажать кнопку на второй странице, то мы снова попадем на первую страницу. Теперь разберемся с тем, как создавать приложения на JavaFX без FXML.
Простое приложение без FXML
В стартовом окне среды выбираем «New Project». Откроется окно выбора типа проекта:
Выбираем простой проект на JavaFX из архетипов Maven. Нажимаем кнопку «Next» и двигаемся дальше:

Название проекта оставим по умолчанию. Нажимаем на «Finish» и видим перед собой новый проект:

Если сейчас запустить этот проект, то мы увидим такое окно:

Все содержимое окна — это простая текстовая метка Label, которая отображает информацию о текущих версиях Java и JavaFX. Немного скучновато, согласитесь. Давайте добавим кнопку, при нажатии на которую будет появляться эта надпись. Для этого изменим код в методе start файла App.java следующим образом:
var javaVersion = SystemInfo.javaVersion(); var javafxVersion = SystemInfo.javafxVersion(); var label = new Label(); var button = new Button("Show Info"); button.setOnAction((ActionEvent event) -> { label.setText("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + "."); }); var box = new VBox(10, label, button); box.setAlignment(Pos.CENTER); var scene = new Scene(new StackPane(box), 640, 480); stage.setScene(scene); stage.show();
Итак, метка у нас уже была, но по умолчанию она была пустой. Мы добавили кнопку и поместили её вместе с меткой в вертикальный контейнер VBox. На кнопку навесили обработчик нажатий, который обновляет текст в метке. Версии Java и JavaFX для отображения в метке берутся из класса SystemInfo, который содержится в файле SystemInfo.java:
public class SystemInfo { public static String javaVersion() { return System.getProperty("java.version"); } public static String javafxVersion() { return System.getProperty("javafx.version"); } }
Секция импортов в файле App.java с учетом новых компонентов будет выглядеть так:
import javafx.application.Application; import javafx.event.ActionEvent; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.stage.Stage;
Запустим наше приложение и увидим следующее:

После нажатия на кнопку:

Все работает! Ниже приводим несколько полезных ссылок для начинающих изучать JavaFX.
Полезные ссылки
- Введение в JavaFX — об API, архитектуре, потоках, жизненном цикле и так далее.
- Начало работы с JavaFX — официальная документация на английском языке.
- Руководство по JavaFX — про классы, графические элементы и прочее.
- Учебник по JavaFX — основные макеты, расширенные макеты, стилизация и тому подобное.