🎯 Exemplos recomendados
Balanced sample collections from various categories for you to explore
Exemplos de Recursos Desktop Web Go
Exemplos de recursos específicos de desktop Web Go incluindo caixas de diálogo de arquivo, caixas de mensagem e bandeja do sistema
💻 Caixas de Mensagem go
🟢 simple
⭐⭐⭐
Exibir caixas de mensagem de informação, aviso e erro
⏱️ 20 min
🏷️ go, web, desktop features
Prerequisites:
Basic Go, GUI framework
// Web Go Message Box Examples
// Using Fyne and Walk for message dialogs
package main
import (
"fmt"
"os"
)
// 1. Using Fyne Framework
/*
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/dialog"
)
func FyneInfoDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("Message Dialog")
dialog.ShowInformation("Information", "This is an info message", myWindow)
myWindow.ShowAndRun()
}
func FyneErrorDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("Error Dialog")
dialog.ShowError(errors.New("This is an error message"), myWindow)
myWindow.ShowAndRun()
}
func FyneConfirmDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("Confirm Dialog")
dialog.ShowConfirm("Confirm", "Are you sure?", func(confirmed bool) {
if confirmed {
fmt.Println("User confirmed")
} else {
fmt.Println("User cancelled")
}
}, myWindow)
myWindow.ShowAndRun()
}
*/
// 2. Using Walk Framework (Windows)
/*
import (
"github.com/lxn/walk"
)
func WalkMessageBox() error {
// Information
walk.MsgBox(nil, "Information",
"This is an info message",
walk.MsgBoxIconInformation)
// Warning
walk.MsgBox(nil, "Warning",
"This is a warning",
walk.MsgBoxIconWarning)
// Error
walk.MsgBox(nil, "Error",
"This is an error",
walk.MsgBoxIconError)
// Question with Yes/No
ret, err := walk.MsgBox(nil, "Question",
"Do you want to continue?",
walk.MsgBoxYesNo|walk.MsgBoxIconQuestion)
if err == nil {
if ret == walk.DialogButtonYes {
fmt.Println("User clicked Yes")
} else {
fmt.Println("User clicked No")
}
}
return nil
}
*/
// 3. Cross-Platform Message Box
// MessageType defines message box type
type MessageType int
const (
InfoMsg MessageType = iota
WarningMsg
ErrorMsg
QuestionMsg
)
// MessageBoxButton defines button type
type MessageBoxButton int
const (
OKBtn MessageBoxButton = iota
OKCancelBtn
YesNoBtn
YesNoCancelBtn
RetryCancelBtn
AbortRetryIgnoreBtn
)
// MessageBoxResult holds message box result
type MessageBoxResult struct {
ButtonPressed string
Confirmed bool
Err error
}
// MessageBox shows message box
func MessageBox(title, message string, msgType MessageType, buttons MessageBoxButton) MessageBoxResult {
// Terminal-based message box
return showTerminalMessageBox(title, message, msgType, buttons)
}
func showTerminalMessageBox(title, message string, msgType MessageType, buttons MessageBoxButton) MessageBoxResult {
// Print message header
var icon string
switch msgType {
case InfoMsg:
icon = "ℹ️"
case WarningMsg:
icon = "⚠️"
case ErrorMsg:
icon = "❌"
case QuestionMsg:
icon = "❓"
}
fmt.Printf("\n%s %s\n", icon, title)
fmt.Printf("%s\n", message)
// Print buttons
var options []string
switch buttons {
case OKBtn:
options = []string{"OK"}
case OKCancelBtn:
options = []string{"OK", "Cancel"}
case YesNoBtn:
options = []string{"Yes", "No"}
case YesNoCancelBtn:
options = []string{"Yes", "No", "Cancel"}
case RetryCancelBtn:
options = []string{"Retry", "Cancel"}
case AbortRetryIgnoreBtn:
options = []string{"Abort", "Retry", "Ignore"}
}
fmt.Print("Options: ")
for i, opt := range options {
if i > 0 {
fmt.Print(", ")
}
fmt.Printf("[%d] %s", i+1, opt)
}
fmt.Println()
// Get user input
var choice int
fmt.Scanln(&choice)
if choice < 1 || choice > len(options) {
return MessageBoxResult{Err: fmt.Errorf("invalid choice")}
}
selected := options[choice-1]
return MessageBoxResult{
ButtonPressed: selected,
Confirmed: selected == "OK" || selected == "Yes" || selected == "Retry",
}
}
// 4. Convenience Functions
// ShowInfo shows information message
func ShowInfo(title, message string) MessageBoxResult {
return MessageBox(title, message, InfoMsg, OKBtn)
}
// ShowWarning shows warning message
func ShowWarning(title, message string) MessageBoxResult {
return MessageBox(title, message, WarningMsg, OKBtn)
}
// ShowError shows error message
func ShowError(title, message string) MessageBoxResult {
return MessageBox(title, message, ErrorMsg, OKBtn)
}
// ShowQuestion shows question with Yes/No
func ShowQuestion(title, message string) MessageBoxResult {
result := MessageBox(title, message, QuestionMsg, YesNoBtn)
return result
}
// ShowConfirm shows confirmation dialog
func ShowConfirm(title, message string) MessageBoxResult {
result := MessageBox(title, message, QuestionMsg, OKCancelBtn)
return result
}
// 5. Progress Dialog
// ProgressDialog shows progress for operations
type ProgressDialog struct {
title string
total int64
current int64
cancelled bool
}
// NewProgressDialog creates progress dialog
func NewProgressDialog(title string, total int64) *ProgressDialog {
return &ProgressDialog{
title: title,
total: total,
current: 0,
}
}
// Update updates progress
func (pd *ProgressDialog) Update(current int64) {
pd.current = current
// Clear line and show progress
fmt.Printf("\r%s: ", pd.title)
percentage := float64(current) / float64(pd.total) * 100
barWidth := 40
filled := int(float64(barWidth) * float64(current) / float64(pd.total))
fmt.Print("[")
for i := 0; i < barWidth; i++ {
if i < filled {
fmt.Print("=")
} else {
fmt.Print(" ")
}
}
fmt.Printf("] %.1f%%", percentage)
}
// Complete marks progress as complete
func (pd *ProgressDialog) Complete() {
pd.Update(pd.total)
fmt.Println(" - Complete!")
}
// 6. Notification
// NotificationType defines notification type
type NotificationType int
const (
NotificationInfo NotificationType = iota
NotificationWarning
NotificationError
NotificationSuccess
)
// ShowNotification shows desktop notification
func ShowNotification(title, message string, notifType NotificationType) {
// Terminal notification
var icon string
switch notifType {
case NotificationInfo:
icon = "ℹ️"
case NotificationWarning:
icon = "⚠️"
case NotificationError:
icon = "❌"
case NotificationSuccess:
icon = "✅"
}
fmt.Printf("\n%s %s: %s\n", icon, title, message)
}
// 7. Input Dialog
// InputDialogResult holds input dialog result
type InputDialogResult struct {
Value string
Err error
}
// ShowInputDialog shows input dialog
func ShowInputDialog(title, prompt, defaultValue string) InputDialogResult {
fmt.Printf("\n%s\n", title)
fmt.Printf("%s", prompt)
if defaultValue != "" {
fmt.Printf(" [%s]", defaultValue)
}
fmt.Print(": ")
var input string
fmt.Scanln(&input)
if input == "" {
input = defaultValue
}
return InputDialogResult{Value: input}
}
// ShowPasswordDialog shows password input dialog
func ShowPasswordDialog(title, prompt string) InputDialogResult {
fmt.Printf("\n%s\n", title)
fmt.Printf("%s: ", prompt)
// Note: In terminal, password won't be hidden
// For real applications, use terminal password reading
var input string
fmt.Scanln(&input)
return InputDialogResult{Value: input}
}
// 8. Select Dialog
// SelectDialogResult holds selection dialog result
type SelectDialogResult struct {
SelectedIndex int
SelectedValue string
Err error
}
// ShowSelectDialog shows selection dialog
func ShowSelectDialog(title string, options []string) SelectDialogResult {
fmt.Printf("\n%s\n", title)
for i, opt := range options {
fmt.Printf("[%d] %s\n", i+1, opt)
}
fmt.Print("Select: ")
var choice int
fmt.Scanln(&choice)
if choice < 1 || choice > len(options) {
return SelectDialogResult{Err: fmt.Errorf("invalid choice")}
}
return SelectDialogResult{
SelectedIndex: choice - 1,
SelectedValue: options[choice-1],
}
}
// 9. Dialog Builder
// DialogBuilder builds message dialogs
type DialogBuilder struct {
title string
message string
msgType MessageType
buttons MessageBoxButton
onConfirm func()
onCancel func()
defaultAction func()
}
// NewDialogBuilder creates dialog builder
func NewDialogBuilder(title, message string) *DialogBuilder {
return &DialogBuilder{
title: title,
message: message,
msgType: InfoMsg,
buttons: OKBtn,
}
}
func (db *DialogBuilder) WithType(msgType MessageType) *DialogBuilder {
db.msgType = msgType
return db
}
func (db *DialogBuilder) WithButtons(buttons MessageBoxButton) *DialogBuilder {
db.buttons = buttons
return db
}
func (db *DialogBuilder) OnConfirm(fn func()) *DialogBuilder {
db.onConfirm = fn
return db
}
func (db *DialogBuilder) OnCancel(fn func()) *DialogBuilder {
db.onCancel = fn
return db
}
func (db *DialogBuilder) Show() MessageBoxResult {
result := MessageBox(db.title, db.message, db.msgType, db.buttons)
if result.Confirmed && db.onConfirm != nil {
db.onConfirm()
} else if !result.Confirmed && db.onCancel != nil {
db.onCancel()
}
return result
}
// Usage Examples
func main() {
fmt.Println("=== Web Go Message Box Examples ===\n")
// 1. Info message
fmt.Println("--- 1. Info Message ---")
ShowInfo("Information", "This is an informational message")
// 2. Warning message
fmt.Println("\n--- 2. Warning Message ---")
ShowWarning("Warning", "This is a warning message")
// 3. Error message
fmt.Println("\n--- 3. Error Message ---")
ShowError("Error", "An error occurred!")
// 4. Question dialog
fmt.Println("\n--- 4. Question Dialog ---")
result := ShowQuestion("Question", "Do you want to continue?")
if result.Confirmed {
fmt.Println("User chose Yes")
} else {
fmt.Println("User chose No")
}
// 5. Input dialog
fmt.Println("\n--- 5. Input Dialog ---")
input := ShowInputDialog("Name", "Enter your name", "")
if input.Err == nil {
fmt.Printf("Hello, %s!\n", input.Value)
}
// 6. Select dialog
fmt.Println("\n--- 6. Select Dialog ---")
selectResult := ShowSelectDialog("Choose Option", []string{"Option A", "Option B", "Option C"})
if selectResult.Err == nil {
fmt.Printf("Selected: %s\n", selectResult.SelectedValue)
}
// 7. Progress dialog
fmt.Println("\n--- 7. Progress Dialog ---")
progress := NewProgressDialog("Processing", 100)
for i := 0; i <= 100; i += 10 {
progress.Update(int64(i))
time.Sleep(100 * time.Millisecond)
}
progress.Complete()
// 8. Notification
fmt.Println("
--- 8. Notification ---")
ShowNotification("Success", "Operation completed successfully!", NotificationSuccess)
// 9. Dialog builder
fmt.Println("
--- 9. Dialog Builder ---")
builderResult := NewDialogBuilder("Confirm Action", "Are you sure?").
WithType(QuestionMsg).
WithButtons(YesNoBtn).
OnConfirm(func() {
fmt.Println("Action confirmed!")
}).
Show()
fmt.Printf("
Builder result: %v\n", builderResult.ButtonPressed)
fmt.Println("
=== All Message Box Examples Completed ===")
fmt.Println("Note: For full GUI functionality, install Fyne or Walk framework")
}
💻 Caixas de Diálogo de Arquivo go
🟡 intermediate
⭐⭐⭐
Abrir e salvar caixas de diálogo de arquivo usando frameworks GUI Fyne ou Walk
⏱️ 30 min
🏷️ go, web, desktop features
Prerequisites:
Intermediate Go, GUI framework
// Web Go File Dialog Examples
// Using Fyne and Walk frameworks for file dialogs
package main
import (
"fmt"
"os"
"path/filepath"
)
// 1. Using Fyne Framework (Cross-platform)
// FyneFileDialogExample demonstrates file dialogs with Fyne
// Install: go get fyne.io/fyne/v2
/*
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/widget"
)
func FyneOpenFileDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("File Dialog")
// Create open file dialog
fd := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) {
if err == nil && reader != nil {
defer reader.Close()
fmt.Printf("Opened file: %v\n", reader.URI())
}
}, myWindow)
fd.SetFilter(storage.NewExtensionFileFilter([]string{".txt", ".go"}))
fd.Show()
// Keep window running
myWindow.ShowAndRun()
}
func FyneSaveFileDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("Save Dialog")
// Create save file dialog
sd := dialog.NewFileSave(func(writer fyne.URIWriteCloser, err error) {
if err == nil && writer != nil {
defer writer.Close()
writer.Write([]byte("Hello, World!"))
fmt.Printf("Saved file: %v\n", writer.URI())
}
}, myWindow)
sd.SetFileName("untitled.txt")
sd.Show()
myWindow.ShowAndRun()
}
func FyneSelectFolderDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("Folder Dialog")
// Create folder select dialog
fd := dialog.NewFolderOpen(func(uri fyne.ListableURI, err error) {
if err == nil && uri != nil {
fmt.Printf("Selected folder: %v\n", uri)
}
}, myWindow)
fd.Show()
myWindow.ShowAndRun()
}
*/
// 2. Using Walk Framework (Windows)
// WalkFileDialogExample demonstrates file dialogs with Walk
// Install: go get github.com/lxn/walk
/*
import (
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
)
func WalkOpenFileDialog() {
var dlg *walk.Dialog
var text *walk.TextEdit
MainWindow{
Title: "File Dialog",
MinSize: Size{400, 300},
Layout: VBox{},
Children: []Widget{
PushButton{
Text: "Open File",
OnClicked: func() {
filePath, err := walk.FileDialog{
Filter: "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
Title: "Open File",
}.ShowOpen(nil)
if err == nil && filePath != "" {
text.SetText(filePath)
fmt.Printf("Opened: %s\n", filePath)
}
},
},
TextEdit{AssignTo: &text},
},
}.Create()
}
func WalkSaveFileDialog() {
var fileName *walk.LineEdit
MainWindow{
Title: "Save Dialog",
Layout: VBox{},
Children: []Widget{
PushButton{
Text: "Save File",
OnClicked: func() {
filePath, err := walk.FileDialog{
Filter: "Text Files (*.txt)|*.txt",
Title: "Save File",
}.ShowSave(nil)
if err == nil && filePath != "" {
fmt.Printf("Save to: %s\n", filePath)
}
},
},
LineEdit{AssignTo: &fileName},
},
}.Create()
}
*/
// 3. Cross-Platform File Dialog Wrapper
// FileDialogOptions holds options for file dialogs
type FileDialogOptions struct {
Title string
Filter string
InitialDir string
DefaultName string
}
// FileDialogResult holds file dialog result
type FileDialogResult struct {
FilePath string
FileName string
Dir string
Err error
}
// OpenFileDialog opens file selection dialog
func OpenFileDialog(options FileDialogOptions) FileDialogResult {
result := FileDialogResult{}
// Check if running in terminal environment
if os.Getenv("TERM") != "" || os.Getenv("TERM_PROGRAM") != "" {
// Terminal-based file selection
return openTerminalFileDialog(options)
}
// Try GUI frameworks
// Note: In a real application, you'd use Fyne or Walk here
result.Err = fmt.Errorf("no GUI framework available")
return result
}
// SaveFileDialog opens save file dialog
func SaveFileDialog(options FileDialogOptions) FileDialogResult {
result := FileDialogResult{}
// Check environment
if os.Getenv("TERM") != "" {
return saveTerminalFileDialog(options)
}
result.Err = fmt.Errorf("no GUI framework available")
return result
}
// 4. Terminal-Based File Dialog (Fallback)
func openTerminalFileDialog(options FileDialogOptions) FileDialogResult {
fmt.Printf("%s\n", options.Title)
fmt.Println("Enter file path (or 'cancel'): ")
var input string
fmt.Scanln(&input)
if input == "cancel" {
return FileDialogResult{Err: fmt.Errorf("cancelled")}
}
if _, err := os.Stat(input); err != nil {
return FileDialogResult{Err: err}
}
return FileDialogResult{
FilePath: input,
FileName: filepath.Base(input),
Dir: filepath.Dir(input),
}
}
func saveTerminalFileDialog(options FileDialogOptions) FileDialogResult {
fmt.Printf("%s\n", options.Title)
defaultName := options.DefaultName
if defaultName == "" {
defaultName = "untitled.txt"
}
fmt.Printf("Enter save path [%s]: ", defaultName)
var input string
fmt.Scanln(&input)
if input == "" {
input = defaultName
}
return FileDialogResult{
FilePath: input,
FileName: filepath.Base(input),
Dir: filepath.Dir(input),
}
}
// 5. File Dialog with Validation
// OpenFileDialogWithValidation opens dialog and validates file
func OpenFileDialogWithValidation(options FileDialogOptions, validateFunc func(string) error) FileDialogResult {
result := OpenFileDialog(options)
if result.Err != nil {
return result
}
if validateFunc != nil {
if err := validateFunc(result.FilePath); err != nil {
return FileDialogResult{Err: err}
}
}
return result
}
// ValidateFileExtension validates file extension
func ValidateFileExtension(extensions []string) func(string) error {
return func(filePath string) error {
ext := filepath.Ext(filePath)
for _, validExt := range extensions {
if ext == validExt {
return nil
}
}
return fmt.Errorf("invalid extension: %s", ext)
}
}
// ValidateFileSize validates file size
func ValidateFileSize(maxSizeMB int64) func(string) error {
return func(filePath string) error {
info, err := os.Stat(filePath)
if err != nil {
return err
}
sizeMB := info.Size() / (1024 * 1024)
if sizeMB > maxSizeMB {
return fmt.Errorf("file too large: %dMB (max %dMB)", sizeMB, maxSizeMB)
}
return nil
}
}
// 6. Batch File Selection
// BatchFileDialogResult holds multiple file selection results
type BatchFileDialogResult struct {
FilePaths []string
Err error
}
// OpenMultipleFilesDialog opens dialog for multiple file selection
func OpenMultipleFilesDialog(options FileDialogOptions) BatchFileDialogResult {
result := BatchFileDialogResult{}
fmt.Printf("%s (Multiple files)\n", options.Title)
fmt.Println("Enter file paths (one per line, empty line to finish):")
var filePaths []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
path := scanner.Text()
if path == "" {
break
}
filePaths = append(filePaths, path)
}
if len(filePaths) == 0 {
result.Err = fmt.Errorf("no files selected")
return result
}
// Validate all files
for _, path := range filePaths {
if _, err := os.Stat(path); err != nil {
result.Err = fmt.Errorf("invalid file: %s - %v", path, err)
return result
}
}
result.FilePaths = filePaths
return result
}
// 7. Recent Files Management
// RecentFiles manages recent file list
type RecentFiles struct {
files []string
max int
}
// NewRecentFiles creates recent files manager
func NewRecentFiles(maxFiles int) *RecentFiles {
return &RecentFiles{
files: []string{},
max: maxFiles,
}
}
// Add adds file to recent list
func (rf *RecentFiles) Add(filePath string) {
// Remove if already exists
for i, f := range rf.files {
if f == filePath {
rf.files = append(rf.files[:i], rf.files[i+1:]...)
break
}
}
// Add to front
rf.files = append([]string{filePath}, rf.files...)
// Limit size
if len(rf.files) > rf.max {
rf.files = rf.files[:rf.max]
}
}
// GetFiles returns recent files list
func (rf *RecentFiles) GetFiles() []string {
return rf.files
}
// SaveToFile saves recent files to file
func (rf *RecentFiles) SaveToFile(filePath string) error {
file, err := os.Create(filePath)
if err != nil {
return err
}
defer file.Close()
for _, f := range rf.files {
file.WriteString(f + "\n")
}
return nil
}
// LoadFromFile loads recent files from file
func (rf *RecentFiles) LoadFromFile(filePath string) error {
file, err := os.Open(filePath)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
rf.Add(scanner.Text())
}
return scanner.Err()
}
// 8. File Dialog Presets
// OpenImageDialog opens image file dialog
func OpenImageDialog() FileDialogResult {
return OpenFileDialog(FileDialogOptions{
Title: "Open Image",
Filter: "*.png;*.jpg;*.jpeg;*.gif;*.bmp",
})
}
// SaveTextFileDialog opens text file save dialog
func SaveTextFileDialog() FileDialogResult {
return SaveFileDialog(FileDialogOptions{
Title: "Save Text File",
Filter: "*.txt",
DefaultName: "untitled.txt",
})
}
// OpenCodeFileDialog opens code file dialog
func OpenCodeFileDialog() FileDialogResult {
return OpenFileDialog(FileDialogOptions{
Title: "Open Code File",
Filter: "*.go;*.js;*.py;*.java;*.cpp",
})
}
// Usage Examples
func main() {
fmt.Println("=== Web Go File Dialog Examples ===\n")
// 1. Open file dialog
fmt.Println("--- 1. Open File Dialog ---")
result := OpenFileDialog(FileDialogOptions{
Title: "Select a File",
Filter: "*.txt",
})
if result.Err == nil {
fmt.Printf("Selected: %s\n", result.FilePath)
}
// 2. Save file dialog
fmt.Println("\n--- 2. Save File Dialog ---")
saveResult := SaveFileDialog(FileDialogOptions{
Title: "Save File",
DefaultName: "output.txt",
})
if saveResult.Err == nil {
fmt.Printf("Save to: %s\n", saveResult.FilePath)
}
// 3. File dialog with validation
fmt.Println("\n--- 3. File Dialog with Validation ---")
validated := OpenFileDialogWithValidation(
FileDialogOptions{Title: "Select Text File"},
ValidateFileExtension([]string{".txt"}),
)
if validated.Err != nil {
fmt.Printf("Validation error: %v\n", validated.Err)
}
// 4. Multiple files
fmt.Println("\n--- 4. Multiple Files ---")
multi := OpenMultipleFilesDialog(FileDialogOptions{
Title: "Select Files",
})
if multi.Err == nil {
fmt.Printf("Selected %d files\n", len(multi.FilePaths))
}
// 5. Recent files
fmt.Println("\n--- 5. Recent Files ---")
recent := NewRecentFiles(5)
recent.Add("file1.txt")
recent.Add("file2.txt")
recent.Add("file3.txt")
fmt.Printf("Recent files: %v\n", recent.GetFiles())
// 6. Presets
fmt.Println("\n--- 6. Preset Dialogs ---")
imageResult := OpenImageDialog()
if imageResult.Err == nil {
fmt.Printf("Image: %s\n", imageResult.FileName)
}
fmt.Println("\n=== All File Dialog Examples Completed ===")
fmt.Println("Note: For full GUI functionality, install Fyne or Walk framework")
}
💻 Bandeja do Sistema go
🔴 complex
⭐⭐⭐⭐
Exibir ícone da bandeja do sistema com menu e notificações
⏱️ 30 min
🏷️ go, web, desktop features
Prerequisites:
Intermediate Go, GUI framework, goroutines
// Web Go System Tray Examples
// System tray icon with menu using Fyne or other frameworks
package main
import (
"fmt"
"os"
"time"
)
// 1. Using Fyne Framework
/*
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/driver/desktop"
"fyne.io/fyne/v2/menu"
"fyne.io/fyne/v2/storage"
)
func FyneSystemTray() {
myApp := app.New()
myWindow := myApp.NewWindow("System Tray")
// Create system tray
if desk, ok := myApp.(desktop.App); ok {
// Set system tray icon
icon := storage.NewFileURI("icon.png")
desk.SetSystemTrayIcon(icon)
desk.SetSystemTrayMenu(menu.New(
menu.NewItem("Show", func() { myWindow.Show() }),
menu.NewItem("Hide", func() { myWindow.Hide() }),
menu.NewSeparator(),
menu.NewItem("Quit", func() { myApp.Quit() }),
))
}
myWindow.ShowAndRun()
}
*/
// 2. Using Systray Framework (Cross-platform)
/*
import (
"github.com/getlantern/systray"
)
func SystrayExample() {
systray.Run(onReady, onExit)
}
func onReady() {
// Set icon
// iconBytes, _ := ioutil.ReadFile("icon.ico")
// systray.SetIcon(iconBytes)
systray.SetTitle("My App")
systray.SetTooltip("My Application")
// Add menu items
mQuit := systray.AddMenuItem("Quit", "Quit the whole app")
mShow := systray.AddMenuItem("Show", "Show window")
mHide := systray.AddMenuItem("Hide", "Hide window")
// Handle menu clicks
go func() {
for {
select {
case <-mShow.ClickedCh:
fmt.Println("Show clicked")
case <-mHide.ClickedCh:
fmt.Println("Hide clicked")
case <-mQuit.ClickedCh:
fmt.Println("Quitting...")
systray.Quit()
return
}
}
}()
}
func onExit() {
fmt.Println("Exiting systray")
}
*/
// 3. Simulated System Tray (Terminal)
// TrayIcon represents a system tray icon
type TrayIcon struct {
title string
tooltip string
menuItems []TrayMenuItem
visible bool
running bool
onQuit func()
notification string
}
// TrayMenuItem represents a menu item
type TrayMenuItem struct {
Title string
Tooltip string
Disabled bool
OnClick func()
}
// NewTrayIcon creates new tray icon
func NewTrayIcon(title, tooltip string) *TrayIcon {
return &TrayIcon{
title: title,
tooltip: tooltip,
menuItems: []TrayMenuItem{},
visible: false,
running: false,
}
}
// SetTitle sets tray icon title
func (ti *TrayIcon) SetTitle(title string) {
ti.title = title
fmt.Printf("[Tray] Title set to: %s\n", title)
}
// SetTooltip sets tooltip
func (ti *TrayIcon) SetTooltip(tooltip string) {
ti.tooltip = tooltip
fmt.Printf("[Tray] Tooltip set to: %s\n", tooltip)
}
// AddMenuItem adds menu item
func (ti *TrayIcon) AddMenuItem(title, tooltip string, onClick func()) {
item := TrayMenuItem{
Title: title,
Tooltip: tooltip,
OnClick: onClick,
}
ti.menuItems = append(ti.menuItems, item)
fmt.Printf("[Tray] Menu item added: %s\n", title)
}
// AddSeparator adds separator
func (ti *TrayIcon) AddSeparator() {
fmt.Println("[Tray] Separator added")
}
// Show shows tray icon
func (ti *TrayIcon) Show() {
ti.visible = true
ti.running = true
fmt.Printf("[Tray] Icon shown: %s\n", ti.title)
ti.run()
}
// Hide hides tray icon
func (ti *TrayIcon) Hide() {
ti.visible = false
fmt.Println("[Tray] Icon hidden")
}
// Quit quits tray icon
func (ti *TrayIcon) Quit() {
ti.running = false
if ti.onQuit != nil {
ti.onQuit()
}
fmt.Println("[Tray] Quit")
}
// OnQuit sets quit handler
func (ti *TrayIcon) OnQuit(fn func()) {
ti.onQuit = fn
}
// ShowNotification shows notification
func (ti *TrayIcon) ShowNotification(title, message string) {
ti.notification = fmt.Sprintf("%s: %s", title, message)
fmt.Printf("[Tray] Notification: %s\n", ti.notification)
}
// run runs tray icon loop
func (ti *TrayIcon) run() {
fmt.Println("[Tray] Running... (Press Ctrl+C to quit)")
fmt.Println("Menu items:")
for i, item := range ti.menuItems {
fmt.Printf(" [%d] %s\n", i+1, item.Title)
}
// Simple menu loop
for ti.running {
time.Sleep(100 * time.Millisecond)
}
}
// 4. Tray Menu Manager
// TrayMenu manages tray menu
type TrayMenu struct {
items []TrayMenuItem
}
// NewTrayMenu creates tray menu
func NewTrayMenu() *TrayMenu {
return &TrayMenu{
items: []TrayMenuItem{},
}
}
// AddItem adds menu item
func (tm *TrayMenu) AddItem(title, tooltip string, onClick func()) {
tm.items = append(tm.items, TrayMenuItem{
Title: title,
Tooltip: tooltip,
OnClick: onClick,
})
}
// AddSubmenu adds submenu
func (tm *TrayMenu) AddSubmenu(title string) *TrayMenu {
submenu := &TrayMenu{}
fmt.Printf("[Tray] Submenu added: %s\n", title)
return submenu
}
// AddSeparator adds separator
func (tm *TrayMenu) AddSeparator() {
fmt.Println("[Tray] Separator added")
}
// 5. Tray Application
// TrayApp represents a complete tray application
type TrayApp struct {
tray *TrayIcon
menu *TrayMenu
running bool
}
// NewTrayApp creates new tray application
func NewTrayApp(title, tooltip string) *TrayApp {
tray := NewTrayIcon(title, tooltip)
return &TrayApp{
tray: tray,
menu: NewTrayMenu(),
running: false,
}
}
// AddMenuItem adds menu item
func (ta *TrayApp) AddMenuItem(title, tooltip string, onClick func()) {
ta.tray.AddMenuItem(title, tooltip, onClick)
}
// AddSeparator adds separator
func (ta *TrayApp) AddSeparator() {
ta.tray.AddSeparator()
}
// SetOnQuit sets quit handler
func (ta *TrayApp) SetOnQuit(fn func()) {
ta.tray.OnQuit(fn)
}
// Run runs tray application
func (ta *TrayApp) Run() {
ta.running = true
ta.tray.Show()
}
// ShowNotification shows notification
func (ta *TrayApp) ShowNotification(title, message string) {
ta.tray.ShowNotification(title, message)
}
// Quit quits application
func (ta *TrayApp) Quit() {
ta.running = false
ta.tray.Quit()
}
// 6. Tray Builder
// TrayBuilder builds tray applications
type TrayBuilder struct {
app *TrayApp
}
// NewTrayBuilder creates tray builder
func NewTrayBuilder(title, tooltip string) *TrayBuilder {
return &TrayBuilder{
app: NewTrayApp(title, tooltip),
}
}
func (tb *TrayBuilder) WithItem(title, tooltip string, onClick func()) *TrayBuilder {
tb.app.AddMenuItem(title, tooltip, onClick)
return tb
}
func (tb *TrayBuilder) WithSeparator() *TrayBuilder {
tb.app.AddSeparator()
return tb
}
func (tb *TrayBuilder) OnQuit(fn func()) *TrayBuilder {
tb.app.SetOnQuit(fn)
return tb
}
func (tb *TrayBuilder) Build() *TrayApp {
return tb.app
}
// 7. Advanced Tray Features
// TrayStatus holds tray status
type TrayStatus struct {
Enabled bool
Tooltip string
IconIndex int
}
// UpdateStatus updates tray status
func (ta *TrayApp) UpdateStatus(status TrayStatus) {
if status.Tooltip != "" {
ta.tray.SetTooltip(status.Tooltip)
}
fmt.Printf("[Tray] Status updated\n")
}
// SetIcon sets tray icon
func (ta *TrayApp) SetIcon(iconPath string) {
fmt.Printf("[Tray] Icon set to: %s\n", iconPath)
}
// ToggleVisibility toggles tray visibility
func (ta *TrayApp) ToggleVisibility() {
fmt.Println("[Tray] Visibility toggled")
}
// Usage Examples
func main() {
fmt.Println("=== Web Go System Tray Examples ===\n")
// 1. Basic tray icon
fmt.Println("--- 1. Basic Tray Icon ---")
tray := NewTrayIcon("My App", "My Application")
tray.AddMenuItem("Show", "Show window", func() {
fmt.Println("Show clicked")
})
tray.AddMenuItem("Hide", "Hide window", func() {
fmt.Println("Hide clicked")
})
tray.AddSeparator()
tray.AddMenuItem("Quit", "Quit application", func() {
fmt.Println("Quit clicked")
tray.Quit()
})
tray.OnQuit(func() {
fmt.Println("Cleanup on quit")
})
// Simulate running (in real app, this would be goroutine)
fmt.Println("Tray icon created (simulated)")
tray.running = true
time.Sleep(1 * time.Second)
tray.Quit()
// 2. Tray application
fmt.Println("
--- 2. Tray Application ---")
app := NewTrayApp("Tray App", "System Tray Application")
app.AddMenuItem("Open", "Open application", func() {
fmt.Println("Open clicked")
})
app.AddMenuItem("Settings", "Open settings", func() {
fmt.Println("Settings clicked")
})
app.AddSeparator()
app.SetOnQuit(func() {
fmt.Println("Application quitting")
})
fmt.Println("Tray application created (simulated)")
// 3. Tray builder
fmt.Println("
--- 3. Tray Builder ---")
builtApp := NewTrayBuilder("Builder App", "Built with Builder").
WithItem("Start", "Start service", func() {
fmt.Println("Service started")
}).
WithItem("Stop", "Stop service", func() {
fmt.Println("Service stopped")
}).
WithSeparator().
WithItem("Exit", "Exit application", func() {
fmt.Println("Exiting")
}).
OnQuit(func() {
fmt.Println("Builder cleanup")
}).
Build()
fmt.Println("Built app created (simulated)")
// 4. Status update
fmt.Println("
--- 4. Status Update ---")
builtApp.UpdateStatus(TrayStatus{
Enabled: true,
Tooltip: "Running",
})
// 5. Notification
fmt.Println("
--- 5. Notification ---")
builtApp.ShowNotification("Update Available", "Version 2.0 is ready")
// 6. Menu manager
fmt.Println("
--- 6. Menu Manager ---")
menu := NewTrayMenu()
menu.AddItem("File", "File operations", func() {
fmt.Println("File menu")
})
menu.AddItem("Edit", "Edit operations", func() {
fmt.Println("Edit menu")
})
menu.AddSeparator()
menu.AddItem("View", "View options", func() {
fmt.Println("View menu")
})
fmt.Printf("Menu created with %d items\n", len(menu.items))
fmt.Println("
=== All System Tray Examples Completed ===")
fmt.Println("Note: For full system tray functionality, install Systray or Fyne framework")
}