Простое сетевое GUI приложение на Go + Fyne

На днях меня попросили сделать простенький реестр записей, но так чтобы он был в виде GUI приложения и имел клиент-серверную архитектуру. Т. е. приложение должно состоять из двух частей:

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

Недавно я как раз прочитал про новый фреймворк Fyne для создания графичесих приложений на Go и решил опробыввать его на этой задаче.

Введение в Fyne

Fyne построен полностью с использованием векторной графики, что означает, что приложения, написанные с помощью Fyne, будут прекрасно масштабироваться до любого размера.

Приложения Fyne основаны на 1 слое (canvas) на окно. Каждый канвас имеет корневой CanvasObject, который может быть отдельным виджетом или контейнером для многих подобъектов, размер и положение которых контролируются макетом.

Каждый холст имеет свое происхождение вверху слева (0, 0), каждый элемент пользовательского интерфейса может масштабироваться в зависимости от устройства вывода, поэтому API не описывает пиксели или точные измерения.

Клиентская часть

Клиентская часть имеет форму с 3-мя полями и двумя кнопками. Выглядит она следующим образом:

демо

Такую формочку можно создасть с помощью кода:

a := app.New()

w := a.NewWindow("Client")

planEvent := widget.NewEntry()
executor := widget.NewEntry()
count := widget.NewEntry()

form := widget.NewForm(
    widget.NewFormItem("План. мероприятия", planEvent),
    widget.NewFormItem("Исполнители", executor),
    widget.NewFormItem("Количество обуч.", count),
)

btnSave := widget.NewButton("OK", func() {
    dataSend := fmt.Sprintf("%s %s %s", planEvent.Text, executor.Text, count.Text)
    
    // оптправка данных на сервер
})

btnExit := widget.NewButton("Выход", func() {
    a.Quit()
})

w.SetContent(
    widget.NewVBox(
        form,
        layout.NewSpacer(), // add empty block
        widget.NewHBox(layout.NewSpacer(), btnSave, btnExit), // add button block
    ))


w.Resize(fyne.NewSize(480, 200))
a.Settings().SetTheme(theme.LightTheme())

w.ShowAndRun()

В данном коде мы создаем новое приложение (app.New), а в нем новое окно на котором будут размещаться виджеты (элементы управления).

Затем мы создаем 3 поля ввода с помощью NewEntry и помещаем их на форму, через NewFormItem.

Далее идет создание 2-х кнопок NewButton, которые будут помещены под формой. Кнопка btnSave будет отчечать за чтение и отправку данных, а btnExit - за выход из приложения.

После того как мы определились с виджетами их надо разместить в окне, для этого служит функция SetContent. В этой фунукции мы добавляем вертикальный блок для виджетов, а затем добавляем горизонтальный блок для кнопок.

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

Ну и соответственно ShowAndRun стартует само приложение.

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

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

Полный код клиента можно посмотерть в репозитории.

Серверная часть

Сначала я хотел делать отображение записей из БД в этом приложении, но к сожалению не нашел готового виджета.

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

Полный код сервера можно посмотерть в репозитории.

Заключение

На протяжении всей работы мне очень не хватало документации, поэтому приходилось постоянно лазить по исходному коду и примерам. Также набор виджетов очень беден, но, возможно, это вопрос времени, так как продукт молодой.

В целом Fyne еще довольно сырой и использовать его для чего-то серьезней чем простой формочки представляется слабо возможным.

Так же я полагаю, что быстрее до ума доведут Flutter для декстопных приложений, нежели Fyne.

 
comments powered by Disqus