托盘菜单
¥Tray Menu
本指南将指导你创建一个带有自身上下文菜单的系统托盘图标。
¥This guide will take you through the process of creating an icon with its own context menu to the system tray.
-
在 macOS 上,图标将位于屏幕右上角的 菜单栏附加功能 区域。
¥On macOS, the icon will be located on the top right corner of your screen in the menu bar extras area.
-
在 Windows 上,图标将位于任务栏末尾的 通知区域 中。
¥On Windows, the icon will be located in the notification area at the end of the taskbar.
-
在 Linux 上,托盘的位置会根据你的桌面环境而有所不同。
¥On Linux, the location of the Tray will differ based on your desktop environment.
创建托盘图标
¥Creating a Tray icon
你的 Electron 应用的托盘图标需要使用 Tray 类的实例以编程方式创建。类构造函数需要一个 NativeImage 实例或兼容图标文件的路径。
¥The tray icon for your Electron app needs to be created programmatically with an instance of the Tray class. The class constructor requires a single instance of a NativeImage or a path to a compatible icon file.
[!注意] 文件格式因操作系统而异。更多详情,请参阅 Tray API 文档的 平台注意事项 部分。
¥[!NOTE] File formats vary per operating system. For more details, see the Platform Considerations section of the Tray API documentation.
最小化到托盘
¥Minimizing to tray
为了使应用和系统托盘图标在所有窗口关闭后仍保持活动状态,你需要在 app
模块上监听 window-all-closed
事件。基础 Electron 模板通常会监听此事件,但在 Windows 和 Linux 上会退出应用,以模拟标准操作系统行为。
¥In order to keep the app and the system tray icon alive even when all windows are closed, you need to
have a listener for the window-all-closed
event on the
app
module. The base Electron templates generally listen for this event but quit the app on
Windows and Linux to emulate standard OS behavior.
app.on('window-all-closed', () => {
// having this listener active will prevent the app from quitting.
})
附加上下文菜单
¥Attaching a context menu
你可以通过将 Menu 实例传递给 tray.setContextMenu
函数,将上下文菜单附加到 Tray 对象。
¥You can attach a context menu to the Tray object by passing in a Menu instance
into the tray.setContextMenu
function.
[!注意] 与常规 上下文菜单 不同,托盘上下文菜单不需要使用
menu.popup
API 手动检测。Tray 对象会替你处理点击事件(尽管 API 中存在各种与点击相关的事件,用于高级用例)。¥[!NOTE] Unlike with regular context menus, Tray context menus don't need to be manually instrumented using the
menu.popup
API. Instead, the Tray object handles click events for you (although various click-related events exist on the API for advanced use cases).
const { nativeImage } = require('electron/common')
const { app, Tray, Menu } = require('electron/main')
// save a reference to the Tray object globally to avoid garbage collection
let tray
// 16x16 red circle data URL
const icon = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACTSURBVHgBpZKBCYAgEEV/TeAIjuIIbdQIuUGt0CS1gW1iZ2jIVaTnhw+Cvs8/OYDJA4Y8kR3ZR2/kmazxJbpUEfQ/Dm/UG7wVwHkjlQdMFfDdJMFaACebnjJGyDWgcnZu1/lrCrl6NCoEHJBrDwEr5NrT6ko/UV8xdLAC2N49mlc5CylpYh8wCwqrvbBGLoKGvz8Bfq0QPWEUo/EAAAAASUVORK5CYII=')
// The Tray can only be instantiated after the 'ready' event is fired
app.whenReady().then(() => {
tray = new Tray(icon)
const contextMenu = Menu.buildFromTemplate([
{ role: 'quit' }
])
tray.setContextMenu(contextMenu)
})
[!TIP] 要了解更多关于在 Electron 中制作菜单的信息,请参阅 菜单 指南。
¥[!TIP] To learn more about crafting menus in Electron, see the Menus guide.
[!WARNING] macOS 托盘中的顶层菜单项无法使用
enabled
和visibility
属性。¥[!WARNING] The
enabled
andvisibility
properties are not available for top-level menu items in the tray on macOS.
可运行的 Fiddle 演示
¥Runnable Fiddle demo
下面是一个可运行的示例,它将各种菜单项附加到托盘的上下文菜单,以帮助控制应用状态并与托盘 API 本身交互。
¥Below is a runnable example of attaching various menu items to the Tray's context menu that help control app state and interact with the Tray API itself.
- main.js
- index.html
const { app, BrowserWindow, Menu, Tray } = require('electron/main')
const { nativeImage } = require('electron/common')
// save a reference to the Tray object globally to avoid garbage collection
let tray = null
function createWindow () {
const mainWindow = new BrowserWindow()
mainWindow.loadFile('index.html')
}
// The Tray object can only be instantiated after the 'ready' event is fired
app.whenReady().then(() => {
createWindow()
const red = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACTSURBVHgBpZKBCYAgEEV/TeAIjuIIbdQIuUGt0CS1gW1iZ2jIVaTnhw+Cvs8/OYDJA4Y8kR3ZR2/kmazxJbpUEfQ/Dm/UG7wVwHkjlQdMFfDdJMFaACebnjJGyDWgcnZu1/lrCrl6NCoEHJBrDwEr5NrT6ko/UV8xdLAC2N49mlc5CylpYh8wCwqrvbBGLoKGvz8Bfq0QPWEUo/EAAAAASUVORK5CYII=')
const green = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACOSURBVHgBpZLRDYAgEEOrEzgCozCCGzkCbKArOIlugJvgoRAUNcLRpvGH19TkgFQWkqIohhK8UEaKwKcsOg/+WR1vX+AlA74u6q4FqgCOSzwsGHCwbKliAF89Cv89tWmOT4VaVMoVbOBrdQUz+FrD6XItzh4LzYB1HFJ9yrEkZ4l+wvcid9pTssh4UKbPd+4vED2Nd54iAAAAAElFTkSuQmCC')
tray = new Tray(red)
tray.setToolTip('Tray Icon Demo')
const contextMenu = Menu.buildFromTemplate([
{
label: 'Open App',
click: () => {
const wins = BrowserWindow.getAllWindows()
if (wins.length === 0) {
createWindow()
} else {
wins[0].focus()
}
}
},
{
label: 'Set Green Icon',
type: 'checkbox',
click: ({ checked }) => {
checked ? tray.setImage(green) : tray.setImage(red)
}
},
{
label: 'Set Title',
type: 'checkbox',
click: ({ checked }) => {
checked ? tray.setTitle('Title') : tray.setTitle('')
}
},
{ role: 'quit' }
])
tray.setContextMenu(contextMenu)
})
app.on('window-all-closed', function () {
// This will prevent the app from closing when windows close
})
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Tray Menu Demo</title>
</head>
<body>
<h1>Tray Menu Demo</h1>
<p>This app will stay running even after all windows are closed.</p>
<ul>
<li>Use the "Open App" menu item to focus the main window (or open one if it does not exist).</li>
<li>Change between red and green Tray icons with the "Set Green Icon" checkbox.</li>
<li>Give the Tray icon a title using the "Set Title" checkbox.</li>
<li>Quit the app using the "Quit" menu item.</li>
</ul>
</body>
</html>