Время на прочтение15 мин
Количество просмотров29K
Привет! Я Виктор Барсуков, Java-разработчик в Lamoda. В этой статье я хочу рассказать о разработке десктопного Java-приложения, что из этого получилось и что можно было бы сделать иначе.
В 2019 году в России ввели обязательную маркировку ряда товаров. В связи с этим малому бизнесу пришлось покупать и настраивать дорогие по меркам МСП (то есть, малых и средних предпринимателей) программы и оборудование.
У меня есть такие знакомые, и из общения с ними я знаю, что в России малому бизнесу и без маркировки хватает забот. Поэтому решил внести посильный вклад в развитие МСП. Но какой вклад может сделать программист? Написать программу. Программу с одной-единственной функцией — печатью кодов маркировки, которая должна помочь соблюсти требования новых законов и избежать непомерных штрафов.
Предыстория проекта
С 2019 года в РФ введена обязательная маркировка ряда товаров. Более подробно об этом можно узнать на сайте Честного Знака. На момент старта маркировки было много нерешенных вопросов, которые озвучивались в профильных чатах. Малым предприятиям требовалось приобретать и настраивать достаточно дорогие программные решения. В результате многие покупали 1С со всем его богатым набором функций исключительно ради печати DataMatrix-кодов.
Мне показалось, что ситуацию вполне можно исправить, написав программу с единственной функцией — печать кодов маркировки. Собственно, с этого все и началось.
Дисклеймер: сразу оговорюсь, что проект делается в свободное от основной работы время, поэтому глубоко исследовать разные технологии было некогда. Часто приходилось выбирать не самое оптимальное решение, а первое, которое показалось приемлемым, и с хорошо описанной документацией.
Используемые технологии
Так как я Java-разработчик, то неудивительно, что в первую очередь рассматривался знакомый язык. Конечно, Java чаще всего ассоциируется с разработкой бэкенда, но я решил попробовать его для десктопа.
При разработке десктопного приложения на Java выбор в принципе стоит между JavaFx и Swing. JavaFx показался дружелюбным в разработке, поэтому выбор пал на него. Swing все-таки считается устаревшей технологией и даже Oracle говорит о замене Swing на JavaFx.
Изначально проект был на Java 8, потому что у него еще есть поддержка JavaFx. В более старших версиях эту функцию убрали, поэтому потребуются определенные танцы с бубном для запуска приложения. Ниже опишу, как удалось обойтись без них и продолжить поддерживать актуальный стек.
Сборка дистрибутива
Первые версии приложения поставлялись как fat-jar со всеми зависимостями, но это оказалось неудобно. Целевая аудитория — малые предприниматели, у которых уровень владения компьютером чаще всего на уровне пользователя, изредка — продвинутого пользователя. Для них оказалось весьма проблематично устанавливать Java правильной версии, а потом запускать приложение через bat-файл.
Сначала я рекомендовал сборку Java от Liberica: после инсталляции она связывает зависимости, и приложение запускается просто по двойному клику мыши. Но даже после этого при вводе запроса «barCodesFX» Google продолжал автоматом подсказывать «как запустить». К счастью, сейчас ситуация поменялась.
Эта подсказка натолкнула меня на мысль, что приложение должно запускаться через exe-файл по двойному клику без установки дополнительного ПО. Или же это ПО должно ставиться автоматом.
В поисках решения нашелся проект Launch4j. Он позволяет создавать exe-файл, выступающий в роли «стартера» для основного jar-приложения. При этом JRE «правильной» версии помещается в состав дистрибутива и не требует отдельной установки. Это увеличило размер дистрибутива, но в век безлимитного интернета лишние 70 Мб для удобства пользователя не кажутся критичными.
Отдельная благодарность команде Liberica, которая поставляет сборки JRE с подключенными модулями JavaFx — это сильно облегчает запуск приложения.
Сам exe-файл создается при сборке после добавления плагина в maven-проект.
<plugin>
<groupId>com.akathist.maven.plugins.launch4j</groupId>
<artifactId>launch4j-maven-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>l4j-clui</id>
<phase>compile</phase>
<goals><goal>launch4j</goal></goals>
<configuration>
<headerType>gui</headerType>
<outfile>target/BarCodesFX.exe</outfile>
<jar>barCodesFX.jar</jar>
<icon>src/main/resources/microQR.ico</icon>
<downloadUrl>https://download.oracle.com/java/17/archive/jdk-17.0.1_windows-x64_bin.msi</downloadUrl>
<errTitle>Launching error</errTitle>
<dontWrapJar>true</dontWrapJar>
<jre>
<path>%PWD%/jre-17.0.1</path>
<jdkPreference>preferJdk</jdkPreference>
<initialHeapPercent>20</initialHeapPercent>
<maxHeapPercent>80</maxHeapPercent>
</jre>
<versionInfo>
<fileVersion>0.0.0.0</fileVersion>
<txtFileVersion>${version}</txtFileVersion>
<fileDescription>BarCodesFX-${version}</fileDescription>
<copyright>Barsukov Viktor</copyright>
<productVersion>0.0.0.0</productVersion>
<txtProductVersion>${version}</txtProductVersion>
<productName>BarCodesFX</productName>
<internalName>BarCodesFX</internalName>
<originalFilename>BarCodesFX.exe</originalFilename>
</versionInfo>
<messages>
<startupErr>Startup error</startupErr>
<bundledJreErr>Bundled Jre Error</bundledJreErr>
<jreVersionErr>Jre Version Error</jreVersionErr>
<launcherErr>Launcher Error</launcherErr>
</messages>
</configuration>
</execution>
</executions>
</plugin>
Через несколько недель после компоновки дистрибутива был обнаружен задокументированный баг: если в пути к exe-файлу есть названия папок на национальных языках (то есть на любом, кроме английского), то приложение не запускается. К счастью, проект Launch4j в целом живой и этот баг пофиксили.
Далее zip-архив вручную упаковывается в SFX-архив и выкладывается в SourceForge. Теперь пользователь может спокойно скачать единственный установочный exe-файл, несколько раз нажать ОК
и Далее
и получить работающую программу.
Функциональность расширяется: подключаю Spring и СУБД
Проект развивался по классическому Agile: вначале скейт, потом самокат, потом велосипед. На старте основная функциональность заключалась в печати датаматриксов. Потом добавилось генерирование XML-файлов, а в самой программе появились настройки.
Изначально настройки хранились в файле и подтягивались с запуском приложения, однако для пользователей это было неудобно и неочевидно. Затем все переехало в графический интерфейс, но тут начались проблемы с общим доступом к файлу настроек и стало понятно, что не хватает базы данных. Для создания БД мне захотелось использовать знакомый фреймворк, а не писать все с нуля, поэтому я подключил к проекту Spring.
К счастью, есть проект JavaFX Weaver, который решает проблемы получения колючей проволоки путем скрещивания ежа и ужа: контроллеры превращаются в бины, dependency injection становятся доступными и становятся доступными прочие плюшки Spring. Но главное — не требуется полностью переписывать все приложение.
В качестве базы данных была выбрана H2. Она легковесная и не требует установки. Пользователь просто запускает приложение и все работает без предварительной установки СУБД.
Добавление шаблонизатора
Проект изначально был опенсорсный, поэтому довольно быстро набрал популярность. Но конкуренты не дремлют: для увеличения трафика коммерческие компании создавали свои бесплатные решения. И у этих решений было одно ключевое преимущество — возможность создавать в удобном графическом редакторе свой шаблон этикетки.
Для меня разработка такой функциональности была непозволительной роскошью, потому что заняла бы много времени без гарантии положительного результата. Однако мне все же хотелось добавить шаблонизатор. По умолчанию в моем приложении было только два варианта печати: либо А4, либо термопринтер. На самой этикетке выводился только датаматрикс и чуть-чуть пользовательского текста.
В поисках решения я подробно изучил продукты компании iText. Их библиотека iТext PDF используется в BarCodesFX для генерации PDF. У нее есть много разных функций и при этом она полностью бесплатная при использовании в опенсорс-проектах. В коде можно полностью собрать pdf-файл с форматированием, дополнительными элементами и картинками. Через нее же происходит преобразование строки в датаматрикс.
У них же обнаружил pdfHTML — библиотеку, которая преобразует HTML-страницу в PDF. Внутри нее нашлась функциональность для заполнения HTML-шаблона. Так у пользователя появилась возможность самостоятельно сверстать практически любую этикетку, а не ограничиваться предустановленными шаблонами.
В шаблоне часть тегов нужно было заменять на пользовательские значения. Например, вместо <datamatrix/>
выводить картинку кода, а вместо <page_number/>
— номер страницы. Для этого разработчику достаточно в свойствах передать свою CustomTagWorkerFactory
, которая наследует от DefaultTagWorkerFactory
. Таким образом, все изменения гармонично встраиваются в поток обработки HTML-кода, при необходимости заменяя дефолтные обработчики тегов на собственные, с помощью имплементации интерфейса ITagWorker .
properties.setTagWorkerFactory(new CustomTagWorkerFactory());
List<IElement> elements =
HtmlConverter.convertToElements(new FileInputStream(htmlSource), properties);
for (IElement element : elements) {
document.add((IBlockElement) element);
}
Можно сказать, что в целом шаблонизатор удался и им активно пользуются. Из 194 млн распечатанных кодов 25 млн было сгенерированно с использованием шаблонизатора. В качестве источника данных для заполнения полей типа артикула, цвета и размера используется эксель-файл.
Хотя не обошлось и без нюансов при верстке. Например, если ваш кастомный тег <datamatrix/>
обернуть в <div>
, то замена не произойдет. Такая вот особенность библиотеки.
Попытки интеграций с API
За время существования проекта было две попытки интеграций с API операторов маркировки.
Первая интеграция была с СУЗ (станцией управления заказами) оператора ЦРПТ (Центра развития перспективных технологий). Она прошла успешно, все работало, но в какой-то момент оператор без предупреждения изменил поведение API. Это привело к массовым обращениям от пользователей, которые сообщали об ошибках в работе приложения.
Так как я занимаюсь проектом в свободное время, то не могу быстро реагировать на такие изменения и обеспечить требуемый уровень поддержки. Поэтому от интеграции с API пришлось отказаться. Кроме того, добавилась необходимость использовать КриптоПро для авторизации, так что эта задача задвинулась в дальний угол.
Вообще работа с криптографией — это весьма интересная задача. Но использовать отечественного криптопровайдера типа КриптоПро в десктопном Java-приложении — это задача «со звездочкой».
Вторая попытка интеграции была с API оператора Республики Беларусь. Авторизация у оператора проходила по логину и паролю и не требовала наличия крипто-провайдера. Функциональность была готова к релизу, но в последний момент пришлось отказаться.
-
Во-первых, была плохая коммуникация с поддержкой оператора РБ, нежелание разбираться и что-то решать. Их позиция: «У нас все работает, проблема на вашей стороне».
-
Во-вторых, нарушение стандарта RFC 8259 при реализации API. В чате поддержка оператора сказала, что символы GS не нужно экранировать при использовании их API. Это дважды нарушает 7-ой пункт стандарта.
Вместе два этих фактора давали гремучую смесь. Пользователи пытались бы использовать внедренную функциональность, а она не работает должным образом. Обращения шли бы ко мне, отнимая много времени на разбор ошибок. Только после подробного разбора стоило идти к оператору. При этом высока вероятность, что оператор просто «отфутболит» мой запрос, потому что я даже не являюсь резидентом. А с точки зрения пользователя — проблема в программе.
Генерация XML
Чтобы при работе на сайте не отмечать каждый код в длинном списке, Честный Знак добавил возможность загружать коды файлами. Например, вам нужно списать 2000 кодов и вы просто загружаете один файл, а не выискиваете все эти коды и не прокликиваете их по одному.
Однако файл должен быть в xml-формате с правильно заполненными тегами. Вручную его создавать еще сложнее, чем прокликивать коды по одному. И именно с созданием таких файлов и помогает программа.
Задача создания xml-файлов достаточно типовая, поэтому здесь особо нечего рассказывать, кроме трех интересных моментов:
Для генерации XML используется библиотека Jackson FasterXML. При сериализации списков пришлось добавить кастомный StdSerializer, иначе вместо этого…
<products_list>
<product>
<ki>0104600840362250215<QCkpilDMTLs</ki>
</product>
<product>
<ki>0104600840362250215*uJEIn4EH>Rd</ki>
</product>
</products_list>
… получали лишние теги product вокруг списка.
<products_list>
<product>
<product>
<ki>0104600840362250215<QCkpilDMTLs</ki>
</product>
<product>
<ki>0104600840362250215*uJEIn4EH>Rd</ki>
</product>
</product>
</products_list>
Разрулить ситуацию через аннотации не представлялось возможным, потому что классы генерируются автоматически на базе XSD-схем.
ЦРПТ ввели дополнительные правила экранирования символов в кодах маркировки в XML. По этой причине нужно было экранировать одинарные и двойные кавычки, хотя этого не требуется по стандарту (пункт 2.4).
К счастью, в библиотеке FasterXML это удалось решить добавлением кастомной EscapingWriterFactory.
public Writer createEscapingWriterFor(final Writer out, String enc) {
return new Writer(){
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
String val = "";
for (int i = off; i < len; i++) {
val += cbuf[i];
}
String escapedStr = StringEscapeUtils.escapeXml(val);
out.write(escapedStr);
}
@Override
public void flush() throws IOException {
out.flush();
}
@Override
public void close() throws IOException {
out.close();
}
};
}
ЦРПТ предоставляет некорректные xsd-схемы. Схемы разделены по документам: есть документ на ввод в оборот, вывод из оборота, списание. Для каждого документа есть свой xsd-файл и при этом есть общая для всех схема — «Определенные пользовательские типы».
Общая схема добавляется через импорт в схемы документов. Например, в схеме документа списания есть такой элемент:
<xs:element name="cis" type="cis_type">
<xs:annotation>
<xs:documentation>Код идентификации</xs:documentation>
</xs:annotation>
Однако тип cis_type не отражен в общей схеме «Определенные пользовательские типы». Такие типы приходилось допридумывать самостоятельно, потому что даже техподдержка не смогла предоставить полностью валидные схемы.
Тесты
Боль. Их просто нет. А для уважающего себя проекта они должны быть написаны — хотя бы юнит-тесты. Но на все не хватает времени.
И к сожалению, нет ни малейшего представления, как можно тестировать сам интерфейс. Вся надежда на проект TestFX, но пока у меня еще не дошли руки посмотреть его подробнее.
Что стоило бы изначально сделать иначе
Контроллер. Сейчас при запуске приложения открывается форма со множеством вкладок, которые программно управляются из одного класса-контроллера. Из-за этого класс достигает размера под 1000 строк. Можно было бы подключать каждую вкладку как отдельный FXML-файл со своим контроллером — это сделало бы программу намного удобней в разработке и поддержке.
Подключить DI (dependency injection) на более ранних этапах. Это повлияло бы в целом на архитектуру и упростило как разработку, так и дальнейшую поддержку. До сих пор в коде видны следы разработки до DI с ручным управлением жизненным циклом объекта. Изначально при написании пришлось потратить время на кодирование жизненного цикла и при дальнейшей разработке приходится помнить об этой особенности.
Немного статистики
Поделюсь статистикой скачиваний за все время существования проекта. Пик в 7000 скачиваний — это выброс из-за сбоя в SourceForge, когда вместо загрузки файла заново запускался таймер, и так до бесконечности. При этом прокручивался счётчик скачиваний. Остальные пики совпадают с этапами внедрения маркировки.
Пик скачивания из РБ (Республика Беларусь) в последние месяцы обусловлен тем, что программа была официально рекомендована оператором РБ для формирования pdf файлов с этикетками.
Согласно статистике самой программы за все время существования проекта с ее помощью распечатали приблизительно 184 000 000 этикеток и ввели в оборот около 210 000 000 единиц товара, а отгрузили почти 81 000 000 единиц товаров.
Статистика собирается обезличенно, о чем указано в описании к программе. При желании сбор статистики можно отключить. Дружественная компания предоставила серверные мощности для сбора данных.
Цифры приблизительные, потому что статистику начали собирать уже после старта обязательной маркировки обуви. Кроме того, сгенерировать PDF — не значит его распечатать. К тому же у ряда пользователей программа находится за корпоративным фаерволом, поэтому статистика просто не доходит до сервера.
Выводы
Разрабатывать десктопные приложения на JavaFx можно: технология живая и достаточно удобная за счет разделения view и controller. В графическом редакторе можно набросать FXML-форму, потом прописать ей поведение в контроллере. Есть подключаемые библиотеки с дополнительными элементами форм. А еще можно написать свои элементы при необходимости. Есть возможность задействовать сторонние фреймворки типа Spring — он работает с современными версиями Java.
Подводя итог можно сказать следующее: если вы Java-разработчик и перед вами поставлена задача сделать утилитное десктопное приложение для внутреннего использования, то JavaFx — хороший выбор. Для написания небольших прикладных программ его более, чем достаточно.
Если же вам нужно сделать коммерческое решение с красивой визуальной картинкой, использующее особенности конкретной ОС (например, сворачивание в трей или показ всплывающих уведомлений), то скорее всего вам потребуется другое решение.
Спасибо, что дочитали, буду рад ответить на вопросы в комментариях.
Ссылка на проект, ссылка на исходники
Java – это популярный язык программирования, разработанный компанией Sun Microsystems в 1995 году. Благодаря своей объектно-ориентированной архитектуре, он обеспечивает удобство и гибкость в разработке программного обеспечения.
Одним из ключевых преимуществ Java является возможность запуска программ на различных устройствах благодаря использованию виртуальной машины (Java Virtual Machine, JVM). Она позволяет компилировать код в байт-код, который затем может выполняться на любой платформе, поддерживающей JVM. Это делает Java универсальным инструментом для создания настольных, мобильных и серверных приложений.
Программирование на Java используется в корпоративных решениях, веб-разработке и мобильных приложениях. Java-разработчики востребованы во многих сферах, включая банковский сектор, игровые технологии и облачные сервисы.
Сейчас это один из ведущих языков, обеспечивающих высокую надежность, безопасность и масштабируемость приложений. Его богатая экосистема и мощные инструменты делают его незаменимым для профессиональной разработки программного обеспечения.
Что такое оконное приложение?
Оконное приложение – это программа с графическим интерфейсом, которая запускается в отдельном окне операционной системы, что позволяет пользователю взаимодействовать с ней с помощью визуальных элементов, таких как кнопки, поля ввода, меню, а такхе другие компоненты.
В отличие от консольных программ, которые работают в текстовом режиме, требуют ввода команд вручную, такие программы имеют удобный интерфейс, где пользователи могут выполнять действия, нажимая кнопки, выбирая пункты меню или вводя данные в поля.
Такие программы используются в различных сферах благодаря своей наглядности, а также удобству взаимодействия. Вот несколько причин, почему они востребованы:
- Удобство для пользователя
- Визуальные элементы позволяют легко управлять программой.
- Понятный интерфейс снижает порог входа для пользователей.
- Широкий спектр применения
- Программы используются в офисных программах, редакторах, играх, инструментах для работы с базами данных и многом другом.
- Например, Microsoft Word, Photoshop или файловые менеджеры – это оконные приложения.
- Интерактивность
- Возможность обрабатывать события (нажатия кнопок, ввод данных, перетаскивание файлов).
- Взаимодействие с пользователем в реальном времени.
- Универсальность
- Могут работать на разных операционных системах (Windows, macOS, Linux).
- Существуют кроссплатформенные библиотеки, позволяющие создавать GUI-программы, работающие одинаково на разных устройствах.
- Гибкость и масштабируемость
- Программа может быть простым (например, калькулятор) или сложным (редактор видео или бухгалтерская программа).
- Можно добавлять новые функции, а также улучшать интерфейс по мере необходимости.
Примеры
- Офисные программы (Word, Excel, PowerPoint).
- Графические редакторы (Photoshop, GIMP, Illustrator).
- Для работы с базами данных (MySQL Workbench, Access).
- Игры (2D, 3D, например, Minecraft, Sims).
- Среды разработки (IntelliJ IDEA, Eclipse, VS Code).
- Музыкальные, видеоплееры (VLC, Windows Media Player).
- Финансовые, бухгалтерские программы.
Таким образом, оконные приложения делают программное обеспечение удобным, доступным, понятным для пользователей, позволяя им эффективно работать с данными, а также выполнять повседневные задачи.
ОНЛАЙН-ПРАКТИКУМ
КАК «ХАКНУТЬ» PYTHON С ПОМОЩЬЮ CHATGPT
ЧТО БУДЕТ НА ОБУЧЕНИИ?
- Прямо в эфире решим типичные задачи программиста только с помощью ChatGPT
- Возможности Python — расскажем что можно делать и сколько на этом зарабатывать?
- Что ждет рынок программирования и почему мы решили сюда пойти
Создание первого приложения может показаться сложной задачей, особенно если вы только начинаете знакомиться с графическим интерфейсом. Однако с правильным подходом и пошаговым разбором процесса это становится вполне понятной и увлекательной задачей.
В этой инструкции мы детально рассмотрим каждый этап разработки программы с использованием библиотеки Swing. Мы создадим окно, добавим в него элементы интерфейса (текстовую метку, кнопку), а также настроим обработчик событий, чтобы кнопка выполняла определенные действия при нажатии.
Шаг 1: установка Java Development Kit (JDK)
Прежде чем мы начнем, убедитесь, что у вас установлен Java Development Kit (JDK). JDK включает в себя все необходимые инструменты для разработки приложений на Java. Вы можете скачать JDK с официального сайта Oracle. Следуйте инструкциям по установке для вашей операционной системы.
Шаг 2: установка интегрированной среды разработки (IDE)
Хотя вы можете разрабатывать Java-приложения с помощью любого текстового редактора, а также командной строки, использование интегрированной среды разработки значительно облегчит вашу работу. В этом туториале мы будем использовать Eclipse IDE, которая является популярным выбором для разработки на Java. Вы можете скачать Eclipse по адресу: https://www.eclipse.org/downloads/
Шаг 3: создание нового проекта
После успешной установки Eclipse IDE, запустите его, следуйте этим шагам:
- Выберите «File» (Файл) в верхнем меню, затем «New» (Создать).
- В выпадающем меню выберите «Java Project» (Проект Java).
- Введите имя проекта, например, «MyFirstJavaApp», и нажмите «Finish» (Завершить).
Теперь у вас есть пустой проект, мы готовы перейти к созданию оконного приложения.
Шаг 4: создание интерфейса
- Щелкните правой кнопкой мыши на папке проекта в обозревателе проектов (Package Explorer), выберите «New» (Создать) -> «Class» (Класс).
- Введите имя класса, например, «MainApp», и убедитесь, что установлен флажок «public static void main(String[] args)».
- Нажмите «Finish» (Завершить).
Откроется окно редактора кода для класса «MainApp». Теперь давайте добавим код для создания окна.
import javax.swing.JFrame;
public class MainApp {
public static void main(String[] args) {
// Создаем экземпляр JFrame (окно)
JFrame frame = new JFrame(«Мое первое оконное приложение»);
// Устанавливаем размер окна
frame.setSize(400, 300);
// Завершаем работу, когда пользователь закроет окно
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Делаем окно видимым
frame.setVisible(true);
}
}
Добавив простые операции, можно сделать, например, калькулятор.
Шаг 5: запуск
Чтобы его запустить, выполните следующие действия:
- Выберите класс «MainApp» в обозревателе проектов (Package Explorer).
- Щелкните правой кнопкой мыши и выберите «Run As» (Запустить как) -> «Java Application» (Java-приложение).
Вы должны увидеть окно с заголовком «Мое первое оконное приложение», размером 400×300 пикселей. Поздравляем, ваше первое оконное приложение на Java успешно работает.
Заключение
В этом туториале мы пошагово разобрали процесс создания простого оконного приложения на языке Java с использованием Eclipse IDE. Мы установили Development Kit (JDK), настроили новый проект в среде разработки, написали код для создания окна и успешно запустили программу.
Теперь у вас есть базовое понимание работы с Swing, одной из самых популярных библиотек для разработки графического интерфейса в Java. Мы рассмотрели, как использовать JFrame для создания главного окна, добавили JButton и JLabel, а также настроили обработчик событий, чтобы реагировать на действия пользователя. Это первый шаг на пути к созданию полноценных настольных приложений.
Что делать дальше
Чтобы закрепить полученные знания, попробуйте немного улучшить вашу программу:
- Добавьте текстовое поле (JTextField) для ввода данных.
- Создайте всплывающее окно (JOptionPane) с сообщением после нажатия кнопки.
- Измените оформление интерфейса, используя Look and Feel.
- Добавьте меню (JMenuBar) и изучите работу с ним.
Чем больше вы практикуетесь, тем лучше будете понимать возможности языка для создания функциональных графических интерфейсов.
Программирование – это не только логика и код, но и творчество. Возможности Java практически безграничны: от разработки настольных программ до создания мобильных приложений и сложных серверных систем. Чтобы расти как разработчик, попробуйте изучить:
- JavaFX – современную библиотеку для создания графических интерфейсов с расширенными возможностями.
- Работу с базами данных (JDBC, Hibernate) – для хранения и обработки информации.
- Основы многопоточного программирования – чтобы создавать более производительные интерфейсы.
- Разработку веб-приложений на Java (Spring, Java EE) – если хотите выйти за пределы настолок.
Спасибо, что прошли этот туториал! Надеюсь, вы получили удовольствие от процесса программирования и теперь чувствуете себя увереннее в работе с Java. Успехов в дальнейших проектах, пусть ваш код всегда будет чистым и эффективным.
3-дневный курс
НАУЧИСЬ СОЗДАВАТЬ TELEGRAM-БОТОВ НА PYTHON С CHATGPT
C НУЛЯ ЗА 3 ДНЯ
- Освой Python и нейросети и узнай, как гарантированно получить первые 10 заказов
- УЧАСТВОВАТЬ ЗА 0 РУБ.
- Создай и прокачай собственного чат-бота
Участвовать бесплатно
Вебинар
ФРИЛАНС И ПРОЕКТНАЯ РАБОТАДЛЯ PYTHON-РАЗРАБОТЧИКА
- Подарим подборку бесплатных инструментов для написания кода
Участвовать бесплатно
April 18, 2023
3 min read
views 5280
Arthur C. Codex
chats: 1
Engineering
Java
In this tutorial, we will explore how to create cross-platform Java desktop applications using Swing and JavaFX. Both frameworks enable you to build rich and interactive user interfaces for your applications to perform on various platforms.
Table of Contents:
- Introduction to Swing
- Introduction to JavaFX
- Setting up the Development Environment
- Creating a Simple Swing Application
- Creating a Simple JavaFX Application
- Integrating Swing and JavaFX
- Conclusion
1. Introduction to Swing
Swing is a GUI (Graphical User Interface) widget toolkit for Java that provides a set of components for building rich and interactive desktop applications. It is part of Java Foundation Classes (JFC) and an extension to the Abstract Window Toolkit (AWT). Swing components are lightweight, which means they are written entirely in Java and do not rely on native operating systems.
2. Introduction to JavaFX
JavaFX is a modern Java framework for building rich and interactive desktop applications. It provides a set of graphics and media packages that enable developers to design, create, test, debug, and deploy rich client applications. JavaFX provides a more advanced and flexible way to create user interfaces compared to Swing. It uses FXML, a declarative XML-based language, which allows for a cleaner separation between the application’s UI and the underlying Java code.
3. Setting up the Development Environment
To start developing Java desktop applications with Swing and JavaFX, you need to have the following tools installed:
- Java Development Kit (JDK)
- An Integrated Development Environment (IDE) like IntelliJ IDEA or Eclipse
- Scene Builder (for JavaFX)
Download and install the latest version of the JDK and your preferred IDE. For JavaFX, you will need to download and install JavaFX SDK and JavaFX Scene Builder.
4. Creating a Simple Swing Application
Let’s create a simple Java Swing application to understand the basics of Swing components and event handling.
Open your IDE and create a new Java project. Create a new Java class called «SwingExample» and add the following code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SwingExample {
public static void main(String[] args) {
JFrame frame = new JFrame("Swing Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 200);
JPanel panel = new JPanel(new FlowLayout());
frame.add(panel);
JLabel label = new JLabel("Enter your name:");
panel.add(label);
JTextField textField = new JTextField(20);
panel.add(textField);
JButton button = new JButton("Submit");
panel.add(button);
JTextArea textArea = new JTextArea(5, 30);
textArea.setEditable(false);
panel.add(textArea);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String name = textField.getText();
textArea.append("Hello, " + name + "\n");
}
});
frame.setVisible(true);
}
}
Run the application, and you will see a simple Swing application with a label, text field, button, and text area. Enter your name in the text field and click the «Submit» button. The application will display a greeting with your name in the text area.
5. Creating a Simple JavaFX Application
Now let’s create a simple JavaFX application to understand the basics of JavaFX components and event handling.
Create a new Java class called «JavaFXExample» and add the following code:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class JavaFXExample extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("JavaFX Example");
VBox vbox = new VBox(10);
vbox.setAlignment(Pos.CENTER);
vbox.setPadding(new Insets(20));
Label label = new Label("Enter your name:");
vbox.getChildren().add(label);
TextField textField = new TextField();
vbox.getChildren().add(textField);
Button button = new Button("Submit");
vbox.getChildren().add(button);
TextArea textArea = new TextArea();
textArea.setEditable(false);
vbox.getChildren().add(textArea);
button.setOnAction(e -> {
String name = textField.getText();
textArea.appendText("Hello, " + name + "\n");
});
primaryStage.setScene(new Scene(vbox, 400, 200));
primaryStage.show();
}
}
Run the application, and you will see a simple JavaFX application with a label, text field, button, and text area. The user interface looks similar to the Swing application we created earlier.
6. Integrating Swing and JavaFX
It is possible to integrate Swing and JavaFX in the same application. This can be useful if you want to add JavaFX components to an existing Swing application or if you want to use Swing components in a JavaFX application.
To integrate Swing and JavaFX, you can use the JFXPanel
class, which is a component that can host JavaFX content inside a Swing application. Here’s an example of how to create a Swing application with an embedded JavaFX WebView:
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javax.swing.*;
public class SwingJavaFXIntegration {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Swing and JavaFX Integration");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
JFXPanel jfxPanel = new JFXPanel();
frame.add(jfxPanel);
Platform.runLater(() -> {
WebView webView = new WebView();
webView.getEngine().load("https://www.google.com");
jfxPanel.setScene(new Scene(webView));
});
frame.setVisible(true);
});
}
}
Run the application, and you will see a Swing application with an embedded JavaFX WebView displaying the Google homepage.
7. Conclusion
In this tutorial, we learned how to create cross-platform Java desktop applications using Swing and JavaFX. Both frameworks provide a rich set of components for building interactive and responsive user interfaces. JavaFX provides a more modern approach with better support for styling and animations, while Swing is still widely used for maintaining legacy applications. You can also integrate Swing and JavaFX components in the same application to leverage the advantages of both frameworks. Hire dedicated Java developers to build powerful and efficient cross-platform desktop applications.
If you’re interested in enhancing this article or becoming a contributing author, we’d love to hear from you.
Please contact Sasha at [email protected] to discuss the opportunity further or to inquire about adding a direct link to your resource. We welcome your collaboration and contributions!
Glossary
Integrated Development Environment (IDE)
An Integrated Development Environment (IDE) is a software application that provides comprehensive facilities to computer programmers for software development. An IDE normally consists of at least a source code editor, build automation tools and a debugger. Some popular IDEs for Java include Eclipse, IntelliJ IDEA, and NetBeans.
Java Development Kit (JDK)
The Java Development Kit (JDK) is a software development environment used for developing Java applications and applets. It includes the Java Runtime Environment (JRE), an interpreter/loader (java), a compiler (javac), an archiver (jar), a documentation generator (javadoc), and other tools needed in Java development. Learn more
JavaFX
JavaFX is an open-source client application platform for building rich internet applications (RIAs) using Java. It supports a wide range of functionalities, including 2D and 3D graphics, audio and video playback, UI controls, and CSS-like styling. JavaFX applications can run on any platform that has a compatible Java Runtime Environment (JRE). More details can be found on the official OpenJFX website.
JFXPanel
JFXPanel is a component that enables integrating JavaFX content into Swing applications. It acts as a host for JavaFX content thus allowing the combination of Swing and JavaFX components within the same application.
Scene Builder
Scene Builder is a visual layout tool that lets users quickly design JavaFX application user interfaces by dragging and dropping. It allows for a rapid building of JavaFX applications and provides a live preview of the user interface document being created.
Swing
Swing is a Graphical User Interface (GUI) widget toolkit for Java. It provides a set of components for building rich and interactive desktop applications. Swing is part of the Java Foundation Classes (JFC) and is an extension to the Abstract Window Toolkit (AWT). The components in Swing are lightweight as they are written entirely in Java and do not rely on native operating systems.
В этом уроке мы рассмотрим, как создавать простые оконные приложения на Java с использованием библиотеки Swing. Мы узнаем, как добавлять различные компоненты в окно, такие как кнопки, текстовые поля и метки, а также как обрабатывать события, такие как нажатие кнопок. Создание графических интерфейсов позволяет улучшить взаимодействие пользователя с программой и сделать её более удобной и интуитивно понятной.
Создание основного окна
Для создания основного окна используется класс JFrame
. Рассмотрим пример создания окна с несколькими компонентами:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SimpleWindow {
public static void main(String[] args) {
JFrame frame = new JFrame("Простое оконное приложение");
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JLabel label = new JLabel("Введите текст:");
JTextField textField = new JTextField(20);
JButton button = new JButton("Отправить");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Введенный текст: " + textField.getText());
}
});
panel.add(label);
panel.add(textField);
panel.add(button);
frame.add(panel);
frame.setVisible(true);
}
}
Результат выполнения
Откроется окно с меткой «Введите текст:», текстовым полем и кнопкой «Отправить». При нажатии на кнопку введенный текст будет выведен в консоль.
Добавление дополнительных компонентов
Вы можете добавлять различные компоненты в ваше окно, такие как переключатели, флажки и списки. Пример добавления флажка:
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CheckboxExample {
public static void main(String[] args) {
JFrame frame = new JFrame("Пример с флажком");
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JLabel label = new JLabel("Введите текст:");
JTextField textField = new JTextField(20);
JCheckBox checkBox = new JCheckBox("Согласен с условиями");
JButton button = new JButton("Отправить");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (checkBox.isSelected()) {
System.out.println("Введенный текст: " + textField.getText());
} else {
System.out.println("Вы должны согласиться с условиями");
}
}
});
panel.add(label);
panel.add(textField);
panel.add(checkBox);
panel.add(button);
frame.add(panel);
frame.setVisible(true);
}
}
Результат выполнения
Откроется окно с меткой «Введите текст:», текстовым полем, флажком и кнопкой «Отправить». При нажатии на кнопку текст будет выведен в консоль, только если установлен флажок «Согласен с условиями».
Упражнения
Упражнение 1: Окно с двумя кнопками
Напишите программу, которая создает окно с двумя кнопками «Показать» и «Скрыть». При нажатии кнопки «Показать» в окне должна отображаться метка с текстом «Привет!», а при нажатии кнопки «Скрыть» метка должна исчезать.
Решение:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ShowHideExample {
public static void main(String[] args) {
JFrame frame = new JFrame("Окно с двумя кнопками");
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JLabel label = new JLabel("Привет!");
label.setVisible(false); // Изначально метка скрыта
JButton showButton = new JButton("Показать");
JButton hideButton = new JButton("Скрыть");
showButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
label.setVisible(true);
}
});
hideButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
label.setVisible(false);
}
});
panel.add(showButton);
panel.add(hideButton);
panel.add(label);
frame.add(panel);
frame.setVisible(true);
}
}
Объяснение: Программа создает окно с двумя кнопками «Показать» и «Скрыть». При нажатии на кнопку «Показать» метка «Привет!» становится видимой, а при нажатии на кнопку «Скрыть» — скрывается.
Упражнение 2: Окно с переключателем
Напишите программу, которая создает окно с переключателем и кнопкой «Проверить». При нажатии кнопки должна выводиться информация, установлен ли переключатель.
Решение:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class RadioButtonExample {
public static void main(String[] args) {
JFrame frame = new JFrame("Окно с переключателем");
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JLabel label = new JLabel("Выбрано: Нет");
JRadioButton radioButton = new JRadioButton("Выбрать");
JButton button = new JButton("Проверить");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (radioButton.isSelected()) {
label.setText("Выбрано: Да");
} else {
label.setText("Выбрано: Нет");
}
}
});
panel.add(radioButton);
panel.add(button);
panel.add(label);
frame.add(panel);
frame.setVisible(true);
}
}
Объяснение: Программа создает окно с переключателем и кнопкой «Проверить». При нажатии кнопки выводится информация о состоянии переключателя (выбран или нет).
Последнее обновление: 20.03.2024
Итак, после установки JDK создадим первое приложение на языке Java. Что необходимо для создания программы на Java? Прежде всего нам надо написать код программы, и для этого нужен текстовый редактор.
Можно использовать любой текстовый редактор, например, Notepad++.
И чтобы превратить код программы в исполняемое приложение необходим компилятор. Компилятор устанавливается вместе с JDK.
Итак, создадим на жестком диске какой-нибудь каталог, в котором будут располагаться файлы с исходным кодом на языке Java. Допустим, это будет каталог
C:/Java. Затем создадим в этом каталоге текстовый файл, который переименуем в Program.java.
Откроем этот файл в любом текстовом редакторе и наберем в нем следующую программу:
public class Program{ public static void main (String args[]){ System.out.println("Hello METANIT.COM!"); } }
Java является объектно-ориентированным языком, поэтому вся программа представляется в виде набора взаимодействующих классов.
В данном случае определен один класс Program.
При определении класса вначале идет модификатор доступа public, который указывает, что данный класс будет доступен
всем, то есть мы сможем его запустить из командной строки. Далее идет ключевое слово
class, а затем название класса. То есть класс называется Program. После названия в фигурных скобках расположено содержимое класса.
Класс может содержать различные переменные и методы. В данном случае у нас объявлен один метод main.
Это главный метод в любой программе на Java, он является входной точкой программы и с него начинается все управление. Он обязательно
должен присутствовать в программе.
Метод main также имеет модификатор public
. Слово static
указывает, что метод main — статический, а слово void
— что он не возвращает никакого значения. Позже
мы подробнее разберем, что все это значит.
Далее в скобках у нас идут параметры метода — String args[]
— это массив args, который хранит значения типа String
, то
есть строки. В данном случае ни нам пока не нужны, но в реальной программе это те строковые параметры, которые передаются при запуске программы из
командной строки.
После списка параметров в фигурных скобках идет тело метода — это собственно те инструкции, которые и будет выполнять метод.
В данном случае фактически определени определена только одна инструкция — вывод на консоль некоторой строки. Для вывода на консоль используется встроенный метод
System.out.println()
. В этот метод передается выводимая строка. Каждая инструкция завершается точкой с запятой.
Теперь скомпилируем написанную программу. Откроем командную строку (в Windows) или терминал в Linux/MacOS и введем там соответствующие команды. Первым делом перейдем в каталог, где лежит наш файл с программой с помощью команды cd:
cd C:\Java
В данном случае файл находится в каталоге C:\Java.
Затем cкомпилируем программу с помощью команды
javac Program.java
Компилятор языка Java представляет утилиту javac. Через пробел название нашего файла, который содержит класс программы.
После этого программа компилируется в байт-код, и в каталоге C:\Java можно будет найти новый файл Program.class.
Это и будет файл с байт-кодом программы. Теперь нам надо его запустить с помощью утилиты java:
java Program
Здесь уже расширение у файла не надо использовать.
Для ОС Windows весь процесс будет выглядеть следующим образом:
В примере выше весь процесс разбивался на два этапа:
-
Компилятор javac создает из программы на языке Java файл с расширением
*.class
, который содержит байт-код для виртуальной машины Java или JVM -
Утилита java запускает скомпилированный байт-код из файла с расширением
*.class
. То есть происходит выполнение программы
Но в последних версиях Java также стало возможно сразу выполнить код программы на языке Java:
C:\Java>java Program.java Hello METANIT.COM! C:\Java>
В этом случае утилите java передается файл с исходным кодом. При этом файла с расширением *.class
не создается.