Приветствую вас, коллеги!
Пару-тройку месяцев назад я начал приглядываться к Golang с целью использовать его для десктопных приложений. Язык понравился, объем и тематика написанных для него пакетов произвели впечатление, но вот с GUI дело обстоит не так радужно. Не буду сейчас подробно останавливаться на деталях, достаточно будет сказать, что после чтения нескольких обзоров и беглого просмотра существующих GUI-пакетов решил написать свой — тем более, что опыт в этом у меня есть.
Первая мысль была — пойти по уже проторенному пути: написать набор соответствующих функций на С, точнее, адаптировать уже готовый — то, что я писал когда-то для Harbour и C++, сделать привязку к нему с помощью cgo (C API для Golang) и дружелюбную обертку. Я даже начал это делать, получил первое окошко, но как представил, сколько впереди еще работы, отдельно для Windows, отдельно для Linux, работы чисто технической, поскольку я это уже проходил, энтузиазм несколько поостыл.
И тогда пришла другая идея.
У меня ведь уже есть GUI-библиотека, HwGUI для Harbour, вполне функциональная, кросс-платформенная, которую я регулярно использую для своих приложений. В ней уже реализовано все, что мне надо. Почему бы не написать на ее основе программу, работающую как своеобразный GUI-сервер. Этот сервер после запуска будет молча слушать определенный порт, и, получив соединение от моей программы на Golang, будет в ответ на ее запросы создавать окошки, виджеты, производить с ними манипуляции и осуществлять обратную связь при появлении каких-то событий от виджетов — словом, реализовывать для нее GUI. Все низкоуровневые детали реализации GUI уже есть в библиотеке, для Windows — через прямые вызовы WinAPI, для Linux/Unix и, наверное, macOs — посредством GTK. Кроме того, я не предполагаю делать сервер в полном смысле этого слова, он не будет принимать соединения от разных программ — это привнесло бы дополнительные ненужные сложности. Для каждого экземпляра Golang-программы будет запускаться свой отдельный экземпляр GUI-сервера, что еще упрощает задачу. В целом программа будет состоять, таким образом, из двух процессов, один из которых выполняет основную задачу, другой — отвечает за интерфейс.
Соответствующий пакет для Go должен включать в себя процедуру Init, которая запускает GUI-сервер и присоединяется к нему, и набор структур, методов, функций для создания окон и виджетов и манипуляций ими. Основная содержательная часть всех этих функций — отправка сообщений определенного формата (основанного на JSON) на сервер и прием сообщений от него. Связь поддерживается с помощью двух tcp/ip портов, один отвечает за отправку запросов на сервер, другой — за получение сигналов от сервера для обработки событий (нажатие кнопки, закрытие окна и пр.). Задача относительно несложная, сам пакет получается небольшой. Не нужно использовать cgo, не нужна привязка к сторонним библиотекам, весь код на чистом Go. Исполняемый файл самой программы и исполняемый файл GUI-сервера — все.
Выбор Harbour + HwGUI для реализации GUI-сервера для меня обусловлен, прежде всего, тем, что это мои «родные» инструменты, самое простое и быстрое решение. Но это хороший выбор и с других точек зрения. Вот, на мой взгляд, основные достоинства:
- кроссплатформенность «в коробке»;
- то, что называется, native look and feel, поскольку под Windows это исключительно вызовы WinAPI, под Linux/Unix — GTK; насколько «native» GTK для macOs я, правда, не знаю;
- возможность использовать Harbour как встроенный скриптовый язык, на сервер можно передавать фрагменты кода для исполнения — обработчики событий, например, что может разгрузить основную программу от некоторых деталей реализации. Кроме того, Harbour хорош для многих вещей, для работы с dbf и некоторыми базами данных, например;
- реализация печати;
- возможность использовать созданные Дизайнером (утилита HwGUI) экранные формы. Эти формы хранятся в XML формате и могут использоваться без изменений в любой ОС, в которой работает сервер;
- возможность использовать созданные тем же Дизайнером формы отчетов для печати (тоже в XML).
Короче, я начал это делать и значительная часть работы уже выполнена. Оба проекта, GuiServer и Golang GUI-фреймворк External — на Github'е, все ссылки в конце статьи. Ниже — пара скриншотов. Ничего особенного, просто тесты.
Это — простое диалоговое окно:
А это сделано на основе примера из книги Кернигана и Донована:
Сейчас основная цель проектов — добиться того, чтобы эта сладкая парочка, External и GuiServer, могли все, что может HwGUI. Ну а по ходу создания каких-то реальных приложений, использующих External, будет ясно, что нужно еще.
На этом можно было бы и закончить, описание Golang-пакета я отложил на другой раз. Но главное в этой статье только начинается. Ведь описанный способ реализации GUI-фреймворка с тем же самым GUI-сервером можно использовать и для других языков. C, Python, Java, ..., даже Perl и PHP (а почему бы и нет?) — см. заголовок статьи. Минимум затрат — и готово довольно функциональное GUI решение. Самое сложное для каждого конкретного языка — не реализация обмена с сервером, а то, чтобы это решение органично вписывалось в его парадигму, в его внутреннюю логику. Если кто хочет создать такой фреймворк для своего языка, постараюсь оказать посильную помощь в получении необходимой информации и, возможно, в добавлении каких-то фич к GUI-серверу.
Параллельно с Golang'овским пакетом я делал аналог для Harbour, в основном в целях проверки/отладки. Фреймворк для Perl вряд ли буду делать, а вот для С или С++ — вполне вероятно. И вот почему: есть ведь еще одна интересная возможность, связанная с использованием GUI-сервера, его можно запускать на другом компьютере. Основная программа работает на одном компьютере, а ее интерфейс — на другом. Сходу видятся вот такие варианты использования этого дела:
- основная программа работает на Linux/Unix сервере, на котором вообще не установлена графическая оболочка;
- основная программа работает на чужом компьютере (у условного бухгалтера в вашей компании), а вы, не мешая ему, управляете ею на своем;
- основная программа работает на смартфоне, а вы с нормального компа копаетесь в его внутренностях;
- основная программа работает на контроллере, на Ардуино каком-нибудь, Распберри или их аналогах, где и монитора нормального, может, нет. Подключаетесь со своим ноутбуком — и вперед.
Вот для этого последнего варианта пригодился бы, наверное, С-фреймворк под GUI-сервер, мне такая возможность кажется очень перспективной.
И, наконец, ссылки:
github.com/alkresin/guiserver — GuiServer на Github
github.com/alkresin/external — External( Go пакет ) на Github
www.kresin.ru/guisrv.html — страница GuiServer у меня на сайте, здесь можно скачать готовые бинарники
habr.com/post/198618 — моя статья о Harbour здесь на Хабре
ru.wikipedia.org/wiki/Harbour — Harbour в Википедии
www.kresin.ru/harbour.html — страница Harbour у меня на сайте
www.kresin.ru/hwgui.html — страница HwGUI у меня на сайте
P.S.: Понятно, что устанавливать Harbour и HwGUI, чтобы собрать GuiServer из исходников мало кто будет, поэтому собранные бинарники я регулярно выкладываю на странице GuiServer у себя на сайте — для Windows, Debian 8 32-bit, Ubuntu 18.04 64-bit. Могу для Федоры собрать, а вот под macOs — увы, у меня в шаговой доступности его нет.
Автор: alkresin