Какой макет выбрать для десктопного приложения на Go с Fyne
Руководство по выбору оптимального макета для создания десктопного приложения на Go с использованием библиотеки Fyne. Реализация сайдбара и многострочного поля ввода.
Какой макет (Layout) выбрать для создания desktop приложения на Go с использованием библиотеки Fyne?
Как реализовать сайдбар с кнопками и контентную область с многострочным полем ввода?
Я начинающий разработчик на Go, который создал парсер контента для консольного приложения. Теперь пытаюсь создать десктопное приложение с использованием GUI библиотеки Fyne, но запутался в документации и не могу подобрать оптимальный вариант макета.
Требуется создать окно размером примерно 600x800 пикселей с:
- Правым сайдбаром с кнопками фиксированной ширины около 150 px
- Контентной областью с виджетом для ввода многострочного текста, который занимает всё оставшееся пространство
Подскажите, какой макет лучше всего подходит для такой компоновки и как оптимально расположить виджеты в окне?
Для создания десктопного приложения на Go с библиотекой Fyne с правым сайдбаром и контентной областью лучше всего подходят Border контейнер или Split контейнер. Оптимальным решением будет комбинация этих контейнеров для достижения желаемой компоновки.
Содержание
- Основные типы макетов в Fyne
- Рекомендуемый подход для вашей задачи
- Пример реализации с Border контейнером
- Пример реализации с Split контейнером
- Оптимизация многострочного поля ввода
- Полный пример приложения
- Советы по адаптации под разные экраны
Основные типы макетов в Fyne
Fyne предоставляет несколько типов контейнеров для организации интерфейса:
container.NewBorder– создает контейнер с боковыми панелями, верхним и нижним колонтитуламиcontainer.NewSplit– делит область на две части вертикально (VSplit) или горизонтально (HSplit)container.NewVBox– вертикальный контейнер для размещения виджетов друг под другомcontainer.NewHBox– горизонтальный контейнер для размещения виджетов рядом
Для вашей задачи с правым сайдбаром идеальным выбором будет container.NewBorder или container.NewSplit.
Рекомендуемый подход для вашей задачи
Для создания окна 600x800 px с правым сайдбаром шириной 150 px и контентной областью многострочного ввода:
// Основной контейнер с правой боковой панелью
sidebar := container.NewBorder(
nil, // верхний колонтитул (nil = пусто)
nil, // нижний колонтитул (nil = пусто)
nil, // левая панель (nil = пусто)
container.NewVBox( // правая боковая панель с кнопками
widget.NewButton("Кнопка 1", func() { /* действие */ }),
widget.NewButton("Кнопка 2", func() { /* действие */ }),
),
)
// Основной контейнер
content := container.NewBorder(
nil,
nil,
nil,
sidebar,
)
// Многострочное поле ввода
textArea := widget.NewMultiLineEntry()
textArea.SetPlaceHolder("Введите текст здесь…")
// Добавляем поле ввода в основную область
mainContent := container.NewScroll(textArea)
content.Objects()[1].(*widget.Container).Add(mainContent)
Пример реализации с Border контейнером
package main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func main() {
myApp := app.New()
window := myApp.NewWindow("Мое приложение")
window.Resize(fyne.NewSize(600, 800))
// Создаем кнопки для сайдбара
button1 := widget.NewButton("Обновить", func() {
println("Обновление контента")
})
button2 := widget.NewButton("Сохранить", func() {
println("Сохранение контента")
})
button3 := widget.NewButton("Выход", func() {
window.Close()
})
// Правый сайдбар с фиксированной шириной
sidebar := container.NewBorder(
nil, // верхний колонтитул
nil, // нижний колонтитул
nil, // левая панель
container.NewVBox( // правая боковая панель
button1,
button2,
button3,
),
)
// Многострочное поле ввода
textArea := widget.NewMultiLineEntry()
textArea.SetPlaceHolder("Введите или вставьте ваш текст здесь…")
// Основная контентная область
contentContainer := container.NewScroll(textArea)
// Собираем все вместе
finalLayout := container.NewBorder(
nil, // верхний колонтитул
nil, // нижний колонтитул
nil, // левая панель
sidebar,
)
// Добавляем контентную область в основную часть
if len(finalLayout.Objects()) > 1 {
finalLayout.Objects()[1].(*widget.Container).Add(contentContainer)
}
window.SetContent(finalLayout)
window.ShowAndRun()
}
Пример реализации с Split контейнером
package main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func main() {
myApp := app.New()
window := myApp.NewWindow("Мое приложение")
window.Resize(fyne.NewSize(600, 800))
// Создаем кнопки для сайдбара
buttons := []*widget.Button{
widget.NewButton("Файл", func() { println("Действие файла") }),
widget.NewButton("Редактировать", func() { println("Действие редактирования") }),
widget.NewButton("Вид", func() { println("Действие вида") }),
widget.NewButton("Справка", func() { println("Действие справки") }),
}
// Контейнер для кнопок
sidebarContainer := container.NewVBox()
for _, btn := range buttons {
sidebarContainer.Add(btn)
}
// Многострочное поле ввода
textArea := widget.NewMultiLineEntry()
textArea.SetPlaceHolder("Введите текст…")
// Основная контентная область с прокруткой
contentContainer := container.NewScroll(textArea)
// Создаем разделитель между сайдбаром и контентом
split := container.NewHSplit(
contentContainer,
sidebarContainer,
)
// Устанавливаем начальное положение разделителя (около 450 px для контента)
split.SetOffset(0.75) // 75 % ширины для контента, 25 % для сайдбара
window.SetContent(split)
window.ShowAndRun()
}
Оптимизация многострочного поля ввода
Для многострочного поля ввода (widget.NewMultiLineEntry) полезные методы:
textArea := widget.NewMultiLineEntry()
// Настройка плейсхолдера
textArea.SetPlaceHolder("Введите текст здесь…")
// Установка текста
textArea.SetText("Пример текста\nс переносом строк")
// Получение текста
text := textArea.Text
// Включение/выключение редактирования
textArea.Disable() // или textArea.Enable()
// Настройка размера шрифта
textArea.TextStyle = fyne.TextStyle{Bold: true}
Полный пример приложения
Вот полный пример, объединяющий все элементы:
package main
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func main() {
// Создание приложения и окна
a := app.New()
w := a.NewWindow("Контент‑парсер")
w.Resize(fyne.NewSize(600, 800))
w.SetCloseIntercept(func() {
println("Приложение закрыто")
})
// Создание кнопок для сайдбара
buttons := []*widget.Button{
widget.NewButton("Парсить", func() {
println("Начало парсинга…")
}),
widget.NewButton("Очистить", func() {
textArea.SetText("")
}),
widget.NewButton("Сохранить", func() {
println("Сохранение: " + textArea.Text)
}),
widget.NewButton("Загрузить", func() {
println("Загрузка файла…")
}),
widget.NewButton("Настройки", func() {
println("Открытие настроек…")
}),
}
// Контейнер для кнопок с отступами
sidebar := container.NewVBox(
widget.NewLabel("Панель управления"),
widget.NewSeparator(),
)
for _, btn := range buttons {
sidebar.Add(btn)
sidebar.Add(widget.NewSeparator())
}
// Многострочное поле ввода
textArea := widget.NewMultiLineEntry()
textArea.SetPlaceHolder("Введите URL или текст для парсинга…\nПоддерживается несколько строк")
textArea.SetText("https://example.com\nhttps://test.com")
// Область контента с прокруткой
content := container.NewScroll(textArea)
// Создание главного контейнера с разделением
mainLayout := container.NewHSplit(content, sidebar)
mainLayout.SetOffset(0.75) // 75 % для контента, 25 % для сайдбара
// Добавляем заголовок
header := container.NewHBox(
widget.NewLabel("Контент‑парсер"),
widget.NewLabel("v1.0"),
)
// Финальная компоновка
finalLayout := container.NewBorder(
header, // верхний колонтитул
nil, // нижний колонтитул
nil, // левая панель
nil, // правая панель
mainLayout,
)
w.SetContent(finalLayout)
w.ShowAndRun()
}
Советы по адаптации под разные экраны
-
Адаптивный размер сайдбара:
go// Для автоматической адаптации ширины сайдбара sidebar := container.NewVBox(buttons...) sidebar.Resize(fyne.NewSize(150, sidebar.MinSize().Height)) -
Минимальные и максимальные размеры:
gotextArea.Resize(fyne.NewSize(400, 600)) textArea.SetMinSize(fyne.NewSize(300, 400)) -
Обработка изменения размера окна:
gow.ResizeCallback = func(size fyne.Size) { // Логика адаптации интерфейса } -
Использование Grid контейнера для сложных компоновок:
gogrid := container.NewGridWithRows(2, header, container.NewHSplit(content, sidebar), )
С Border контейнером вы получаете более строгий контроль над компоновкой, а Split контейнер обеспечивает гибкость и возможность изменения размера пользователем. Для начинающего разработчика Border контейнер будет проще в понимании и использовании.