Как написать приложение на JavaFX: гид для начинающих

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.

После успешного запуска среды разработки на экране появится окно приветствия.

7173cea3f4e54039470e938536c7a8d7.png

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

b5b1121a701ca486bec624921c631d98.png

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

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

40b8dfa1a985c58de8920061fdd899f2.png

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

98432ce5f78a2a154337b7c2f065783f.png

Теперь можно переходить к конструированию интерфейса.

Интерфейс

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

4019c1015f412c2eab494ea5a424cbd9.png

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

90b00888ebb194b1176a2cdc530faa3e.png

Перед нами открывается визуальный редактор, позволяющий быстро создать пользовательский интерфейс, просто перетаскивая необходимые компоненты из палитры в левой панели на макет в центре.

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

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

Чтобы его добавить, раскрываем список Controls в левой панели, находим TextField и перетаскиваем его в верхнюю часть макета. В результате должно получиться следующее:

62567384ce3494e84b18005ef018e6e3.png

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

a0da0ce8e4654b81d20c24a6bc0dd3e0.png

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

02bcd25c02e99ea74e4571b5345bfdff.png

Интерфейс готов. Теперь перейдем к логике приложения.

Логика

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

6137a37d7b86969a7d334ce58e7338ed.png

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

af909b2f456f18cf89190a25a6500606.png

Это неудивительно, ведь в интерфейс мы добавили только текстовое поле 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-файла:









  
    
  
   

  
  

Не забывайте и об импортируемых классах в начале исходного кода. Здесь разработчики 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);

Теперь можно попробовать запустить наш проект. Жмем на зеленый треугольник в тулбаре и видим примерно это:

cf698003a44aa36d9e08363ba1c94f12.png

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

92b957b264d50aec8949ffe6f3c9d234.png

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

726c76e1dcc7cf64584fc30094f5fa17.png

Все работает, как надо! Далее рассмотрим создание приложений на JavaFX в среде Apache NetBeans.

Создаем приложение в среде Apache NetBeans

Apache NetBeans — ещё одна популярная среда разработки, которая поддерживает не только разработку приложений на Java, но и другие проекты, например, приложения на языке PHP.

Установка среды и создание проекта

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

973cdfec9121c4d335d0790461858c62.png

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

fa9be0f905632881c2bca29904956e04.png

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

2cbad254cde0a2ad4d124b18df31b785.png

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

b1c4c75e630a2fe03a16740e25bfecce.png

Далее займемся созданием этого самого интерфейса.

Интерфейс

В отличие от IntelliJ IDEA, в Apache NetBeans нет встроенного визуального редактора для FXML. Поэтому нам придется использовать внешний редактор — Gluon Scene Builder, который можно скачать отсюда. Это тот же самый Builder, который поставляется с IntelliJ IDEA.

Интерфейс нашего приложения будет двухстраничным. В проекте есть два файла с описанием интерфейса (primary.fxml и secondary.fxml) и два соответствующих контроллера (PrimaryController и SecondaryController). Запускаем наш только что установленный Scene Builder:

d1f11aa13d9a844c70f5a13900b4540a.png

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

afdf3b243cac4917694474681b376f20.png

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

c2e4b8cc1d6586502b0f4ed3a1882b81.png

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

945f86acbd6016ffbb2f559dbdf14ee9.png

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

81a8ee72a136e645417d17ed7122a21e.png

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

d556aafa78bac8d14cfde3becc334fe2.png

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

d1dbd24cb60b64133501eba8bf49be8c.png

Если сейчас нажать кнопку на второй странице, то мы снова попадем на первую страницу. Теперь разберемся с тем, как создавать приложения на JavaFX без FXML.

Простое приложение без FXML

В стартовом окне среды выбираем «New Project». Откроется окно выбора типа проекта:

2fd23ebaa2c796c9c5dc3d6544396c90.png

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

a78ed0e58a812a9477dc3b8820b3cd41.png

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

48b0f67e3290d9490f014563730e418a.png

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

3be5906fa802dea681214956abfccde9.png

Все содержимое окна — это простая текстовая метка 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;

Запустим наше приложение и увидим следующее:

208cb8d6c9c2b1b951819facea9639c1.png

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

883e5cdeb5240607f473f4299e29c546.png

Все работает! Ниже приводим несколько полезных ссылок для начинающих изучать JavaFX.

Полезные ссылки

  • Введение в JavaFX — об API, архитектуре, потоках, жизненном цикле и так далее.

  • Начало работы с JavaFX — официальная документация на английском языке.

  • Руководство по JavaFX — про классы, графические элементы и прочее.

  • Учебник по JavaFX — основные макеты, расширенные макеты, стилизация и тому подобное.

Обучиться с нуля на программиста и растить навыки до техлида или архитектора ПО можно на магистратуре МИФИ и Skillfactory по направлению «Программная инженерия». Оттачивайте навыки на реальных задачах от бизнеса и набирайтесь опыта.

Habrahabr.ru прочитано 7344 раза