アプリケーション実行中に、状況に応じてメニューのラベル(テキスト)を動的に変更する方法を解説します。
例えば、「保存」を「上書き保存」に変えたり、ログイン状態によって「ログイン」を「ログアウト」に変えるといったUIの更新に使用できます。
前提条件
Permissions (権限) の設定
src-tauri/capabilities/default.json に core:menu:default を追加します。
{
"permissions": [
...,
"core:menu:default"
]
}
1. フロントエンドから変更する (TypeScript)
MenuItem インスタンスを取得し、setText() などのメソッドを使用します。
サンプルコード
import { Menu, Submenu, MenuItem } from '@tauri-apps/api/menu';
// 1. 変更したい MenuItem を個別に作成 (参照を保持するため)
const authItem = await MenuItem.new({
id: 'auth', // id は必須ではありませんが、識別用に推奨
text: 'ログイン',
action: async () => {
await toggleAuth();
}
});
// 2. メニュー構造を構築
const accountMenu = await Submenu.new({
text: 'アカウント',
items: [authItem]
});
const menu = await Menu.new({
items: [accountMenu]
});
await menu.setAsAppMenu();
// 状態管理と連動させる例
let isLoggedIn = false;
async function toggleAuth() {
isLoggedIn = !isLoggedIn;
// 保持していたインスタンスに対してメソッドを呼び出す
if (isLoggedIn) {
await authItem.setText('ログアウト');
console.log('ログインしました');
} else {
await authItem.setText('ログイン');
console.log('ログアウトしました');
}
}
その他の更新可能なプロパティ
setText 以外にも、以下のようなプロパティを動的に変更可能です。
* setEnabled(boolean): 有効/無効の切り替え
* setChecked(boolean): CheckMenuItem のチェック状態の切り替え
* setIcon(Image): IconMenuItem のアイコン変更
* setAccelerator(string): ショートカットキーの変更
2. バックエンドから変更する (Rust)
Rust 側でも MenuItem などのメソッドを使用して動的に変更できます。
サンプルコード
use tauri::menu::{Menu, MenuItem, Submenu};
use tauri::Manager;
use std::sync::Mutex;
// メニュー項目の参照と状態を管理する構造体
struct MenuState {
auth_item: MenuItem<tauri::Wry>,
is_logged_in: Mutex<bool>,
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.setup(|app| {
// 1. 動的に変更したいメニュー項目を作成
// ID "auth" を指定、初期テキストは "ログイン"
let auth_item = MenuItem::with_id(app, "auth", "ログイン", true, None::<&str>)?;
// 2. サブメニューを作成し、項目を追加
let account_menu = Submenu::with_items(app, "アカウント", true, &[&auth_item])?;
// 3. アプリケーション全体のメニューを作成
let menu = Menu::with_items(app, &[&account_menu])?;
// 4. メニューをセット
app.set_menu(menu)?;
// 5. 作成した MenuItem のインスタンスと初期状態を State に保存
// MenuItem 自体はスレッドセーフなハンドルのため Mutex は不要 (bool のみラップする)
app.manage(MenuState {
auth_item,
is_logged_in: Mutex::new(false),
});
Ok(())
})
.on_menu_event(|app, event| {
// メニューイベントのハンドリング
// .0 で ID 文字列にアクセス (Tauri v2)
if event.id().0 == "auth" {
// State を取得 (Mutex でラップしていないので直接フィールドにアクセス可)
let menu_state = app.state::<MenuState>();
// フラグの更新 (ここだけロックする)
let is_logged_in = {
let mut guard = menu_state.is_logged_in.lock().unwrap();
*guard = !*guard;
*guard
};
let new_text = if is_logged_in { "ログアウト" } else { "ログイン" };
// MenuItem のテキストを更新 (set_text は &self で呼べる)
if let Err(e) = menu_state.auth_item.set_text(new_text) {
eprintln!("Failed to update menu text: {}", e);
}
println!("Menu Item Clicked: State changed to {}", if is_logged_in { "Logged In" } else { "Logged Out" });
}
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}