如何在Go Fyne系统托盘菜单中点击后切换按钮文本与动作
解决Fyne系统托盘菜单动态更新问题
在macOS Big Sur 11.5.1(20G80)环境下使用Fyne v2.3.3开发Go程序时,实现系统托盘菜单后,点击"start"选项想将其文本改为"stop"并切换对应动作逻辑,但直接修改MenuItem的Label和Action属性后,系统托盘菜单无法自动刷新。这是因为Fyne的系统托盘菜单不会监听MenuItem的属性变化,必须重新调用SetSystemTrayMenu才能更新菜单显示。
解决方案
核心思路:
- 维护状态变量记录当前运行状态
- 在菜单动作中根据状态切换执行逻辑与菜单文本
- 重新调用
SetSystemTrayMenu刷新系统托盘菜单
修改后的代码
package main import ( "fmt" "sync/atomic" "fyne.io/fyne/v2" "fyne.io/fyne/v2/app" "fyne.io/fyne/v2/driver/desktop" "fyne.io/fyne/v2/widget" ) var ( menu1 *fyne.MenuItem isRunning atomic.Bool // 原子变量保证并发安全 ) func main() { a := app.New() w := a.NewWindow("SysTray") if desk, ok := a.(desktop.App); ok { // 统一动作逻辑,根据状态切换行为 toggleAction := func() { if isRunning.Load() { fmt.Println("stopped") isRunning.Store(false) menu1.Label = "start" } else { fmt.Println("started") isRunning.Store(true) menu1.Label = "stop" } // 重新设置菜单以刷新系统托盘显示 m := fyne.NewMenu("MyApp", menu1, menu2, menu3) desk.SetSystemTrayMenu(m) } menu1 = fyne.NewMenuItem("start", toggleAction) menu2 := fyne.NewMenuItem("menu1", nil) menu2.ChildMenu = fyne.NewMenu("", fyne.NewMenuItem("submenu1", func() { fmt.Println("submenu1") }), fyne.NewMenuItem("submenu2", func() { fmt.Println("submenu2") }), ) menu3 := fyne.NewMenuItem("show2", func() { fmt.Println("menu2") }) m := fyne.NewMenu("MyApp", menu1, menu2, menu3) desk.SetSystemTrayMenu(m) } w.SetContent(widget.NewLabel("Fyne System Tray")) w.SetCloseIntercept(func() { w.Hide() }) w.ShowAndRun() }
关键说明
- 使用
atomic.Bool作为状态变量,避免并发场景下的竞态问题 - 将菜单动作统一为
toggleAction,内部根据isRunning状态切换执行逻辑与菜单文本 - 修改菜单文本后必须重新创建菜单并调用
SetSystemTrayMenu,触发Fyne更新系统托盘的菜单显示
你的go.mod文件(无需修改)
module go-GUI go 1.19 require fyne.io/fyne/v2 v2.3.3 require ( fyne.io/systray v1.10.1-0.20230312215936-7f71b037e260 // indirect github.com/benoitkugler/textlayout v0.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fredbi/uri v0.1.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe // indirect github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 // indirect github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 // indirect github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 // indirect github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b // indirect github.com/go-text/typesetting v0.0.0-20221212183139-1eb938670a1f // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/goki/freetype v0.0.0-20220119013949-7a161fd3728c // indirect github.com/gopherjs/gopherjs v1.17.2 // indirect github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/srwiley/oksvg v0.0.0-20220731023508-a61f04f16b76 // indirect github.com/srwiley/rasterx v0.0.0-20210519020934-456a8d69b780 // indirect github.com/stretchr/testify v1.8.0 // indirect github.com/tevino/abool v1.2.0 // indirect github.com/yuin/goldmark v1.4.13 // indirect golang.org/x/image v0.0.0-20220601225756-64ec528b34cd // indirect golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee // indirect golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/text v0.6.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect )
内容的提问来源于stack exchange,提问作者Willis
相关产品推荐
相关产品推荐

