參與貢獻

編輯此文件

翻譯文件,或在您的電腦上開啟完整專案。

在您選擇提交成果之前,不會發布任何內容。

選單參考

選單項目類型、屬性與方法的完整參考

選單參考

選單項目類型、屬性與動態行為的完整參考。使用核取方塊、選項群組、分隔線與動態更新,建立專業且反應靈敏的選單。

選單項目類型

一般選單項目

最常見的類型——顯示文字並觸發動作:

go
menuItem := menu.Add("Click Me")
menuItem.OnClick(func(ctx *application.Context) {
    fmt.Println("Menu item clicked!")
})

適用於:命令、動作、開啟視窗

核取方塊

可切換勾選/未勾選狀態的選單項目:

go
checkbox := menu.AddCheckbox("Enable Feature", true)  // true = initially checked
checkbox.OnClick(func(ctx *application.Context) {
    isChecked := ctx.ClickedMenuItem().Checked()
    fmt.Printf("Feature is now: %v\n", isChecked)
})

適用於:布林設定、功能開關、檢視選項

重要:按一下後,勾選狀態會自動切換。

選項群組

互斥選項——一次只能選取一個:

go
menu.AddRadio("Small", true)   // true = initially selected
menu.AddRadio("Medium", false)
menu.AddRadio("Large", false)

適用於:互斥選擇(大小、佈景主題、模式)

群組運作方式:

  • 相鄰的選項項目會自動形成群組
  • 選取其中一個項目時,會取消選取群組中的其他項目
  • 使用分隔線或一般項目分隔不同群組

多個群組的範例:

go
// Group 1: Size
menu.AddRadio("Small", true)
menu.AddRadio("Medium", false)
menu.AddRadio("Large", false)

menu.AddSeparator()

// Group 2: Theme
menu.AddRadio("Light", true)
menu.AddRadio("Dark", false)

子選單

用於組織內容的巢狀選單結構:

go
submenu := menu.AddSubmenu("More Options")
submenu.Add("Submenu Item 1").OnClick(func(ctx *application.Context) {
    // Handle click
})
submenu.Add("Submenu Item 2")

適用於:將相關項目分組、減少雜亂

巢狀層級限制:大多數平台支援2-3層。請避免更深的巢狀結構。

分隔線

選單項目之間的視覺分隔元素:

go
menu.Add("Item 1")
menu.AddSeparator()
menu.Add("Item 2")

適用於:在視覺上將相關項目分組

最佳做法:不要在選單開頭或結尾放置分隔線。

區段標題

在 macOS 14+ 上為一組選單項目提供原生、不可互動的標籤:

go
menu.AddSectionHeader("Build server")
menu.Add("Start build").OnClick(startBuild)
menu.Add("View logs").OnClick(viewLogs)

AddSectionHeader 使用 AppKit 標準的區段標題外觀。它不會傳回選單項目,也不會關聯動作。在較舊版本的 macOS、Windows、Linux、行動平台和伺服器建置中,呼叫不會執行任何操作,也不會插入任何列。

可在系統匣選單、快顯選單或應用程式選單中使用它,為相關命令加上標籤。若要在所有平台上分隔單選群組,請使用 AddSeparator(),因為省略的標題不會分隔單選群組。方法簽章請參閱 Menu API,使用主機名稱作為標題的範例請參閱 systray-menu。

選單項目屬性

標籤

選單項目顯示的文字:

go
menuItem := menu.Add("Initial Label")
menuItem.SetLabel("New Label")

// Get current label
label := menuItem.Label()

動態標籤:

go
updateMenuItem := menu.Add("Check for Updates")
updateMenuItem.OnClick(func(ctx *application.Context) {
    updateMenuItem.SetLabel("Checking...")
    menu.Update()  // Important on Windows!
    
    // Perform update check
    checkForUpdates()
    
    updateMenuItem.SetLabel("Check for Updates")
    menu.Update()
})

啟用狀態

控制選單項目是否可供互動:

go
menuItem := menu.Add("Save")
menuItem.SetEnabled(false)  // Greyed out, can't click

// Enable it later
menuItem.SetEnabled(true)
menu.Update()  // Important: Call this after changing enabled state!

// Check current state
isEnabled := menuItem.Enabled()

範例:動態啟用/停用

go
var hasSelection bool

cutMenuItem := menu.Add("Cut")
cutMenuItem.SetEnabled(false)  // Initially disabled

copyMenuItem := menu.Add("Copy")
copyMenuItem.SetEnabled(false)

// When selection changes
func onSelectionChanged(selected bool) {
    hasSelection = selected
    cutMenuItem.SetEnabled(hasSelection)
    copyMenuItem.SetEnabled(hasSelection)
    menu.Update()  // Critical on Windows!
}

常見模式:符合條件時啟用

go
saveMenuItem := menu.Add("Save")

func updateSaveMenuItem() {
    canSave := hasUnsavedChanges() && !isSaving()
    saveMenuItem.SetEnabled(canSave)
    menu.Update()
}

// Call whenever state changes
onDocumentChanged(func() {
    updateSaveMenuItem()
})

勾選狀態

對於核取方塊和選項項目,可控制或查詢其勾選狀態:

go
checkbox := menu.AddCheckbox("Feature", false)
checkbox.SetChecked(true)
menu.Update()

// Query state
isChecked := checkbox.Checked()

自動切換:按一下核取方塊後,其狀態會自動切換。您不需要在點擊處理常式中呼叫SetChecked()。

手動控制:

go
checkbox := menu.AddCheckbox("Auto-save", false)

// Sync with external state
func syncAutoSave(enabled bool) {
    checkbox.SetChecked(enabled)
    menu.Update()
}

快速鍵(鍵盤快捷鍵)

為選單項目新增鍵盤快捷鍵:

go
saveMenuItem := menu.Add("Save")
saveMenuItem.SetAccelerator("CmdOrCtrl+S")

quitMenuItem := menu.Add("Quit")
quitMenuItem.SetAccelerator("CmdOrCtrl+Q")

快速鍵格式:

  • CmdOrCtrl——在 macOS 上為 Cmd,在 Windows/Linux 上為 Ctrl
  • Shift、Alt、Option——輔助按鍵
  • A-Z、0-9——字母/數字鍵
  • F1-F12——功能鍵
  • Enter、Space、Backspace等——特殊按鍵

範例:

go
"CmdOrCtrl+S"           // Save
"CmdOrCtrl+Shift+S"     // Save As
"CmdOrCtrl+W"           // Close Window
"CmdOrCtrl+Q"           // Quit
"F5"                    // Refresh
"CmdOrCtrl+,"           // Preferences (macOS convention)
"Alt+F4"                // Close (Windows convention)

平台特定的快速鍵:

go
if runtime.GOOS == "darwin" {
    prefsMenuItem.SetAccelerator("Cmd+,")
} else {
    prefsMenuItem.SetAccelerator("Ctrl+P")
}

工具提示

為選單項目新增滑鼠懸停文字(各平台的支援情況不一):

go
menuItem := menu.Add("Advanced Options")
menuItem.SetTooltip("Configure advanced settings")

平台支援情況:

  • Windows:✅ 支援
  • macOS:❌ 不支援(工具提示並非選單的標準功能)
  • Linux:⚠️ 視桌面環境而異

隱藏狀態

隱藏選單項目而不移除:

go
debugMenuItem := menu.Add("Debug Mode")
debugMenuItem.SetHidden(true)  // Hidden

// Show in debug builds
if isDebugBuild {
    debugMenuItem.SetHidden(false)
    menu.Update()
}

適用於:偵錯選項、功能旗標、條件式功能

事件處理

OnClick 處理常式

按一下選單項目時執行程式碼:

go
menuItem := menu.Add("Click Me")
menuItem.OnClick(func(ctx *application.Context) {
    // Handle click
    fmt.Println("Clicked!")
})

Context 提供:

  • ctx.ClickedMenuItem()-被按下的選單項目
  • 視窗上下文(若來自視窗選單)
  • 應用程式上下文

範例:在處理常式中存取選單項目

go
checkbox := menu.AddCheckbox("Feature", false)
checkbox.OnClick(func(ctx *application.Context) {
    item := ctx.ClickedMenuItem()
    isChecked := item.Checked()
    fmt.Printf("Feature is now: %v\n", isChecked)
})

多個處理常式

您可以設定多個處理常式(以最後一個為準):

go
menuItem := menu.Add("Action")
menuItem.OnClick(func(ctx *application.Context) {
    fmt.Println("First handler")
})

// This replaces the first handler
menuItem.OnClick(func(ctx *application.Context) {
    fmt.Println("Second handler - this one runs")
})

最佳實務:只設定一次處理常式,並視需要在其中使用條件邏輯。

動態選單

更新選單項目

黃金準則:變更選單狀態後,一律呼叫menu.Update()。

go
// ✅ Correct
menuItem.SetEnabled(true)
menu.Update()

// ❌ Wrong (especially on Windows)
menuItem.SetEnabled(true)
// Forgot to call Update() - click handlers may not work!

這一點很重要的原因:

  • Windows:選單會在更新時重新建構
  • macOS/Linux:重要性較低,但仍建議這麼做
  • 按一下處理常式:若未呼叫 Update(),便無法正常觸發

重建選單

若有重大變更,請重建整個選單:

go
func rebuildFileMenu() {
    menu := app.Menu.New()
    
    menu.Add("New").OnClick(handleNew)
    menu.Add("Open").OnClick(handleOpen)
    
    if hasRecentFiles() {
        recentMenu := menu.AddSubmenu("Open Recent")
        for _, file := range getRecentFiles() {
            recentMenu.Add(file).OnClick(func(ctx *application.Context) {
                openFile(file)
            })
        }
    }
    
    menu.AddSeparator()
    menu.Add("Quit").OnClick(handleQuit)
    
    // Set the new menu
    window.SetMenu(menu)
}

何時應重建:

  • 最近使用的檔案清單變更
  • 外掛程式選單變更
  • 重大狀態轉換

何時應更新:

  • 啟用或停用項目
  • 變更標籤
  • 切換核取方塊

內容相關選單

根據應用程式狀態調整選單:

go
func updateEditMenu() {
    cutMenuItem.SetEnabled(hasSelection())
    copyMenuItem.SetEnabled(hasSelection())
    pasteMenuItem.SetEnabled(hasClipboardContent())
    undoMenuItem.SetEnabled(canUndo())
    redoMenuItem.SetEnabled(canRedo())
    menu.Update()
}

// Call whenever state changes
onSelectionChanged(updateEditMenu)
onClipboardChanged(updateEditMenu)
onUndoStackChanged(updateEditMenu)

平台差異

選單列位置

平台 位置 備註
macOS 螢幕頂端 全域選單列
Windows 視窗頂端 各視窗各自具備選單
Linux 視窗頂端 通常各視窗各自具備選單

標準選單

macOS:

  • 具備「應用程式」選單(顯示應用程式名稱)
  • 「偏好設定」位於「應用程式」選單中
  • 「結束」位於「應用程式」選單中

Windows/Linux:

  • 沒有「應用程式」選單
  • 「偏好設定」位於「編輯」或「工具」選單中
  • 「結束」位於「檔案」選單中

範例:符合平台慣例的結構

go
menu := app.Menu.New()

// macOS gets Application menu
if runtime.GOOS == "darwin" {
    menu.AddRole(application.AppMenu)
}

// File menu
fileMenu := menu.AddSubmenu("File")
fileMenu.Add("New")
fileMenu.Add("Open")

// Preferences location varies
if runtime.GOOS == "darwin" {
    // On macOS, preferences are in Application menu (added by AppMenu role)
} else {
    // On Windows/Linux, add to Edit or Tools menu
    editMenu := menu.AddSubmenu("Edit")
    editMenu.Add("Preferences")
}

快速鍵慣例

macOS:

  • 大多數快速鍵使用Cmd+
  • 「偏好設定」使用Cmd+,
  • 「結束」使用Cmd+Q

Windows:

  • 大多數快速鍵使用Ctrl+
  • 「偏好設定」使用Ctrl+P或Ctrl+,
  • 「結束」使用Alt+F4(或Ctrl+Q)

Linux:

  • 通常遵循 Windows 慣例
  • 桌面環境可能會覆寫這些設定

最佳實務

✅ 建議做法

  • 變更選單狀態後,呼叫 menu.Update()(尤其是在 Windows 上)
  • 對互斥選項使用選項群組
  • 對可切換的功能使用核取方塊
  • 為常用動作新增快速鍵
  • 使用分隔線將相關項目分組
  • 在所有平台上測試——行為因平台而異

❌ 請勿

  • 別忘了呼叫 menu.Update()——否則點擊處理函式將無法正常運作
  • 請勿巢狀排列過深——最多 2-3 層
  • 請勿以分隔線開頭或結尾——這樣看起來不專業
  • 請勿在 macOS 上使用工具提示——macOS 不支援此功能
  • 請勿寫死特定平台的快速鍵——請使用 CmdOrCtrl

疑難排解

選單項目沒有回應

症狀:點擊處理函式未觸發

原因:啟用項目後忘了呼叫 menu.Update()

解決方法:

go
menuItem.SetEnabled(true)
menu.Update()  // Add this!

選單項目呈灰色

症狀:無法點擊選單項目

原因:項目已停用

解決方法:

go
menuItem.SetEnabled(true)
menu.Update()

快速鍵無法使用

症狀:鍵盤快速鍵未觸發選單項目

原因:

  1. 快速鍵格式不正確
  2. 與系統快速鍵衝突
  3. 視窗未取得焦點

解決方法:

go
// Check format
menuItem.SetAccelerator("CmdOrCtrl+S")  // ✅ Correct
menuItem.SetAccelerator("Ctrl+S")       // ❌ Wrong (macOS uses Cmd)

// Avoid conflicts
// ❌ Cmd+H (Hide Window on macOS - system shortcut)
// ✅ Cmd+Shift+H (Custom shortcut)

後續步驟


有問題嗎?請在 Discord 中提問,或查看選單範例。

編輯頁面

上次更新: