托盘图标
托盘图标显示在 macOS 菜单栏、Windows 通知区或 Linux 的 StatusNotifierItem 宿主中。把图像放进 resources/,并在应用启动回调里创建图标。它与打包的应用图标不是同一张图。
#创建托盘图标
把一张小 PNG 随应用一起打包,再从安装后的路径创建图标:
Application::new()
.on_tray_event(|event, cx| {
if event.kind == TrayEventKind::Click {
// 显示或聚焦窗口。
}
if event.kind == TrayEventKind::MenuItem && event.menu_item_id == Some(2) {
cx.exit();
}
})
.run(|cx| {
let icon = TrayIconImage::from_path(
cx.app_paths()
.unwrap()
.resource_dir()
.join("trayTemplate.png"),
)
.expect("tray icon");
cx.set_tray_icon(
TrayIconOptions::new(1, icon)
.tooltip("My App")
.menu([
TrayMenuItem::action(1, "Show window"),
TrayMenuItem::separator(),
TrayMenuItem::action(2, "Quit"),
]),
)
.expect("tray icon");
cx.open_window(WindowOptions::new("My App").size(760.0, 520.0), App);
})set_tray_icon 会替换该 id 的图标。remove_tray_icon 删除它。Image::open 和 TrayIconImage::from_path 都会遵守模板文件名约定。
22×22 的 PNG 适合作为 1× 源图。需要视网膜菜单栏图像时,再画一张 44×44 的 trayTemplate@2x.png。
#模板图像
在 macOS 上,模板图像是单色蒙版。AppKit 只使用 alpha 通道,按菜单栏的浅色、深色和高亮外观重新着色。
文件名的主干以 Template 结尾(后面可以跟 @2x 或 @3x)时,会被当作模板图像:
resources/trayTemplate.png
resources/trayTemplate@2x.pngtrayTemplate.png 和 statusTemplate@2x.png 会匹配。emailTemplateIcon.png 不会。quickgui::is_template_image_path 是同一套判断。
文件名不符合约定时,调用 .template(true) 或 .icon_is_template(true);用 .template(false) 可强制关闭。Image、MenuIcon 和 TrayIconImage 都会携带该标志。其他平台会保留并忽略它。
let icon = Image::open(path)?.template(false);
cx.set_dock_icon(icon)?;#菜单与事件
托盘菜单是原生上下文菜单。在 Application::on_tray_event 上处理 TrayEventKind::MenuItem。其他类型包括 Click、DoubleClick、Enter、Move、Leave 和 Scroll。
show_tray_menu 在 macOS 和 Windows 上于光标位置打开菜单。Linux 宿主自行呈现菜单,并拒绝该调用。
#平台说明
| 平台 | 宿主 | 模板图像 | show_tray_menu |
|---|---|---|---|
| macOS | 菜单栏额外图标 | 由 AppKit 重新着色 | 支持 |
| Windows | 通知区 | 忽略 | 支持 |
| Linux | StatusNotifierItem | 忽略 | 不支持 |
DesktopIntegrationSupport::current().tray_icons 在 macOS、Windows 和 Linux 上为 true。programmable_tray_popup 仅限 macOS 和 Windows。最多保留 32 个托盘图标。
