跳到主要内容

应用菜单

lencx
{折腾 ⇌ 迷茫 ⇌ 思考]ing,在路上...
​关注他
13 人赞同了该文章
仓库:lencx/OhMyBox
阅读原文(首发于 GitHub)
关注《浮之静》公众号,私信作者,进 Tauri 技术交流群
此文以 macOS 为例子
Tauri 允许开发者创建自己的菜单项并向其添加特殊功能,枚举了特定于平台的菜单项集合(如 About、Hide、Quit、Copy 等,查看更多 MenuItem Variants),目前版本(v1.0)未在 Windows 上实现。菜单主要包含以下 API:

Menu - 创建一个新菜单
Submenu - 使用给定的标题和菜单项创建一个新的子菜单
MenuItem - 菜单项,绑定到预定义的操作或 Custom 发出事件
CustomMenuItem - 自定义菜单项
默认菜单
Step 1
新建 src-tauri/src/menu.rs 文件

use tauri::{utils::assets::EmbeddedAssets, Context, Menu};

pub fn init(context: &Context<EmbeddedAssets>) -> Menu {
// 获取应用名称
let name = &context.package_info().name;
tauri::Menu::os_default(name)
}
注意:不同 OS 下的默认菜单略有差别,详情请查看 Menu os_default。

Step 2
在 src-tauri/src/main.rs 中使用 menu.rs,并将菜单添加至所有窗口

#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]

mod menu;

fn main() {
let context = tauri::generate_context!();
tauri::Builder::default()
.menu(menu::init(&context)) // ✅ 将菜单添加到所有窗口
.run(context)
.expect("error while running OhMyBox application");
}

自定义菜单
Menu 使用以下方式来添加一个菜单项目:

with_items - 使用给定的菜单项集合创建一个新菜单
use tauri::{Menu, MenuItem, CustomMenuItem, Submenu};

Menu::with_items([
MenuItem::SelectAll.into(),
#[cfg(target_os = "macos")]
MenuItem::Redo.into(),
CustomMenuItem::new("toggle", "Toggle visibility").into(),
Submenu::new("View", Menu::new()).into(),
]);
add_native_item - 将原生菜单项添加到菜单
use tauri::{Menu, MenuItem};

Menu::new()
.add_native_item(MenuItem::Copy)
.add_native_item(MenuItem::Minimize)
.add_native_item(MenuItem::Zoom);
add_item - 将自定义菜单项添加到菜单
use tauri::{Menu, CustomMenuItem};

Menu::new()
.add_item(CustomMenuItem::new("quit".to_string(), "Quit"))
.add_item(CustomMenuItem::new("close".to_string(), "Close"));
add_submenu - 添加一个带有子菜单的条目
use tauri::{Menu, MenuItem, CustomMenuItem};

Menu::new()
.add_submenu(Submenu::new(
"View", // 子菜单名称
Menu::new() // 子菜单项
.add_item(CustomMenuItem::new("close".to_string(), "Close")) // 自定义菜单(关闭)
.add_native_item(MenuItem::Quit) // 原生菜单(退出)
));
菜单事件
原生菜单已绑定事件,无需再次绑定,自定义菜单则需要绑定事件
编辑 src-tauri/src/menu.rs 文件

use tauri::api::dialog::message;
use tauri::utils::assets::EmbeddedAssets;
use tauri::{AboutMetadata, Context, CustomMenuItem, Menu, MenuItem, Submenu, WindowMenuEvent};

// 应用菜单项
pub fn init(context: &Context<EmbeddedAssets>) -> Menu {
// 应用名称
let name = &context.package_info().name;
// tauri::Menu::os_default(name)
// 应用主菜单
let app_menu = Submenu::new(
"",
// MenuItem::About 为原生菜单
Menu::new().add_native_item(MenuItem::About(name.into(), AboutMetadata::new())),
);
// 文件菜单(自定义菜单)
let file_menu = Submenu::new(
"File",
Menu::new()
.add_item(CustomMenuItem::new("new_file".to_string(), "New File"))
.add_item(CustomMenuItem::new("edit_file".to_string(), "Edit File")),
);
// 编辑菜单(自定义菜单)
let edit_menu = Submenu::new(
"Edit",
Menu::new()
.add_item(CustomMenuItem::new("undo".to_string(), "Undo"))
.add_item(CustomMenuItem::new("redo".to_string(), "Redo")),
);

Menu::new()
.add_submenu(app_menu)
.add_submenu(file_menu)
.add_submenu(edit_menu)
}

// 应用菜单处理事件
pub fn handler(event: WindowMenuEvent) {
// 菜单所属的窗口
let win = Some(event.window());
// 匹配菜单 id
match event.menu_item_id() {
"new_file" => {
// debug 信息(终端输出)
dbg!("new file");
}
"edit_file" => {
// 发送信息到菜单所属窗口(弹窗形式)
message(win, "Eidt File", "TODO");
}
"undo" => {
dbg!("undo");
}
"redo" => {
dbg!("redo");
}
_ => {}
}
}
编辑 src-tauri/src/main.rs 文件

#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]

mod menu;

fn main() {
let context = tauri::generate_context!();
tauri::Builder::default()
.menu(menu::init(&context))
.on_menu_event(menu::handler)
.run(context)
.expect("error while running OhMyBox application");
}
动图封面
更新菜单项
编辑 src-tauri/src/menu.rs 文件中的 handler 方法

pub fn handler(event: WindowMenuEvent) {
let win = Some(event.window());
let menu_handle = win.unwrap().menu_handle();
match event.menu_item_id() {
"new_file" => {
// 新开一个线程用于处理更新操作,否则应用会卡死
std::thread::spawn(move || {
menu_handle
.get_item("new_file") // 获取菜单项 id
.set_title("Create File") // 设置新的菜单名
.unwrap();
});
dbg!("new file");
}
"edit_file" => {
message(win, "Eidt File", "TODO");
}
"undo" => {
dbg!("undo");
}
"redo" => {
dbg!("redo");
}
_ => {}
}
}
动图封面
注意:在tauri::Builder::default().setup()的setup中获取到 window 后也可以进行类似操作。关于菜单的更多信息,请自行查看文档 Tauri Menu