i18n(ja) Japanese Texts for "Learn" section (part 1 of 2) (#3399)

Co-authored-by: Ayres Vitor <gitkey@virtuaires.com.br>
This commit is contained in:
Junichi TAKAI (たかい じゅんいち)
2025-12-07 12:30:09 +09:00
committed by GitHub
parent 33de7b4e71
commit 25d43acc7f
6 changed files with 1750 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
---
title: 学習要領
sidebar:
order: 0
label: 概要
i18nReady: true
---
import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components';
import AwesomeTauri from '@components/AwesomeTauri.astro';
import BookItem from '@components/BookItem.astro';
import RoseRustBook from '@assets/learn/community/HTML_CSS_JavaScript_and_Rust_for_Beginners_A_Guide_to_Application_Development_with_Tauri.png';
import TranslationNote from '@components/i18n/TranslationNote.astro';
この「学習」編では、Tauri 関連のトピックに関する学習体験を端から端まで提供することを目的としています。
各チュートリアルは、特定のトピックについて説明し、ガイドや参考文書(リファレンス)から得た知識を応用できるようになるでしょう。
セキュリティ関連のトピックでは、アクセス権システムについて学ぶことができます。そこではシステムの使い方、拡張のし方、そしてあなた自身のアクセス権を記述するやり方について、実践的な知識が得られます。
<CardGrid>
<LinkCard
title="Plugin アクセス権の使用法"
href="/ja/learn/security/using-plugin-permissions/"
/>
<LinkCard
title="異なるウィンドウ/プラットフォームのためのセキュリティ機能"
href="/ja/learn/security/capabilities-for-windows-and-platforms/"
/>
<LinkCard
title="Plugin アクセス権の作成"
href="/ja/learn/security/writing-plugin-permissions/"
/>
</CardGrid>
独自の「スプラッシュスクリーン」起動時表示画面を作成する方法や、「Node.js サイドカー」を使用する方法については、以下を参照してください:
<CardGrid>
<LinkCard title="スプラッシュスクリーン" href="/ja/learn/splashscreen/" />
<LinkCard title="Node.js サイドカー" href="/ja/learn/sidecar-nodejs/" />
</CardGrid>
## その他の資料
この項には、この Web サイトに掲載されていない、コミュニティによって作成された学習資料を掲載しています。
<LinkCard
title="共有可能な資料はありますか?"
description="プル・リクエストでその素晴らしい資料を公開してみませんか"
href="https://github.com/tauri-apps/awesome-tauri/pulls"
/>
### 書籍
<BookItem
image={RoseRustBook}
title="HTML, CSS, JavaScript, and Rust for Beginners: A Guide to Application Development with Tauri"
alt="HTML, CSS, JavaScript, and Rust for Beginners Book Cover"
author="James Alexander Rose"
links={[
{
preText: 'ペーパーバック英語版Amazon:',
text: '購入はこちらから',
url: 'https://www.amazon.com/dp/B0DR6KZVVW',
},
{
preText: '無償 PDF 版:',
text: 'ダウンロード (PDF 4MB)',
url: '/assets/learn/community/HTML_CSS_JavaScript_and_Rust_for_Beginners_A_Guide_to_Application_Development_with_Tauri.pdf',
},
]}
/>
### ガイドとチュートリアル
<AwesomeTauri section="guides-no-official-no-video" />
#### ビデオ・ガイド
<AwesomeTauri section="guides-no-official-only-video" />
<div style="text-align: right">
【※ この日本語版は、「Feb 22, 2025 英語版」に基づいています】
</div>

View File

@@ -0,0 +1,202 @@
---
title: Node.js サイドカー
sidebar:
order: 1
i18nReady: true
---
import CommandTabs from '@components/CommandTabs.astro';
import { Tabs, TabItem, Steps } from '@astrojs/starlight/components';
import CTA from '@fragments/cta.mdx';
import TranslationNote from '@components/i18n/TranslationNote.astro';
この章では、Node.js アプリケーションを自己完結型バイナリにパッケージ化して、エンドユーザーが Node.js をインストールすることなく Tauri アプリケーションの「サイドカー」として利用できるようにします。
このチュートリアル例は、デスクトップ・オペレーティング・システムにのみ適用可能です。
「Tauri サイドカー」の仕組みをより深く理解するために、まずは一般的な [サイドカー・ガイド] を読むことをお勧めします。
以下の事例では、コマンドライン [process.argv] から入力を読み取り、[console.log] を使用して出力を stdout標準出力に書き込む Node.js アプリケーションを作成します。<br/>
「ローカルホスト・サーバー」、「stdin/stdout」標準入出力、「ローカル・ソケット」などといった代替のプロセス間通信システムを活用できます。
これらはそれぞれに利点、欠点、セキュリティ上の懸念があることに注意してください。
## 事前準備(必要なもの)
シェル・プラグインを使用してセットアップされた「既存の Tauri アプリケーション」。このシェル・プラグインは、ローカルでコンパイルおよび実行を行ないます。
:::tip[試作アプリの作成]
あなたが上級ユーザーでない場合は、ここで提供されているオプションとフレームワークをそのまま使用することを**強く推奨**します。これはあくまで「試作(ラボ)」なので、作業終了後にはプロジェクトを削除できます。
<CTA />
- プロジェクト名: `node-sidecar-lab`
- フロントエンド用言語の選択: `Typescript / Javascript`
- パッケージ・マネージャーの選択: `pnpm`
- UI テンプレートの選択: `Vanilla`
- UI フレーバーの選択: `Typescript`
- モバイル用プロジェクトも設定しますか?: `yes`
:::
:::note
プラグインを正しく設定して初期化するには、まず[シェル・プラグイン・ガイド](/ja/plugin/shell/)に従ってください。
プラグインの初期化と設定が行なわれていないと、以下の事例は機能しません。
:::
## ガイド
<Steps>
1. ##### サイドカー・プロジェクトの初期化
サイドカー実装を格納する新しい Node.js プロジェクトを作成しましょう。
**Tauri アプリケーションのルート・フォルダー** に新しいディレクトリを作成し(この事例では `sidecar-app` と呼びます)、そのディレクトリ内で、好みの Node.js パッケージ・マネージャーの `init` コマンドを実行します。
<CommandTabs npm="npm init" yarn="yarn init" pnpm="pnpm init" />
[pkg] コマンドを使用して、Node.js アプリケーションを自己完結型バイナリにコンパイルします。
<TranslationNote lang="ja">
**自己完結型バイナリ** 原文 a self contained binary この語は本稿一行目にも記載あり。ただし、この「ガイド」項目内では a self contain**er** binary と記載されており、表記のゆらぎか誤記かは不明。翻訳では self contained の意味として表記を統一してあります。
</TranslationNote>
それを開発依存関係としてインストールしましょう:
<CommandTabs
npm="npm add @yao-pkg/pkg --save-dev"
yarn="yarn add @yao-pkg/pkg --dev"
pnpm="pnpm add @yao-pkg/pkg --save-dev"
/>
1. ##### サイドカー・ロジックの記述
では、Tauri アプリケーションによって実行される JavaScript コードの作成を始めましょう。
この事例では、コマンドライン引数からコマンドを処理し、出力を stdout標準出力に書き出します。
つまり、このプロセスは短命で、一度に一つのコマンドのみを処理します。
もしあなたのアプリケーションが「長い存続時間」(長命のプロセス)を必要としている場合には、別の「プロセス間通信システム」の使用を検討してください。
`sidecar-app` ディレクトリに `index.js` ファイルを作成し、基本的な Node.js アプリを記述しましょう:
```js title=sidecar-app/index.js
const command = process.argv[2];
switch (command) {
case 'ping':
const message = process.argv[3];
console.log(`pong, ${message}`);
break;
default:
console.error(`unknown command ${command}`);
process.exit(1);
}
```
1. ##### サイドカーのパッケージ化
Node.js アプリケーションを自己完結型バイナリにパッケージ化するには、以下の `pkg` コマンドを実行します:
<CommandTabs
npm="npm run pkg -- --output app"
yarn="yarn pkg --output app"
pnpm="pnpm pkg --output app"
/>
これにより、Linux および macOS では `sidecar-app/app` バイナリが作成され、Windows では `sidecar-app/app.exe` 実行可能ファイルが作成されます。
このファイル名を Tauri サイドカー・ファイル名で要求される形式に変更するには、次の Node.js スクリプトを使用します:
```js
import { execSync } from 'child_process';
import fs from 'fs';
const ext = process.platform === 'win32' ? '.exe' : '';
const rustInfo = execSync('rustc -vV');
const targetTriple = /host: (\S+)/g.exec(rustInfo)[1];
if (!targetTriple) {
console.error('Failed to determine platform target triple');
}
fs.renameSync(
`app${ext}`,
`../src-tauri/binaries/app-${targetTriple}${ext}`
);
```
1. ##### Tauriアプリケーションでのサイドカー設定
Node.js アプリケーションの準備ができたので、[`bundle > externalBin`] 配列を設定して、これを Tauri アプリケーションに接続します:
```json title="src-tauri/tauri.conf.json"
{
"bundle": {
"externalBin": ["binaries/app"]
}
}
```
Tauri CLI は、サイドカー・バイナリが `src-tauri/binaries/app-<target-triple>` として存在する限り、サイドカー・バイナリのバンドルを処理します。
<TranslationNote lang="ja">
**target-triple** 「target」はアプリが対象とするプラットフォーム、「triple」は target の内容を示す三要素 \<machine>-\<vendor>-\<os>: 例 aarch64-apple-darwinARM64-apple-macOS[参考](https://doc.rust-lang.org/nightly/rustc/platform-support.html)
</TranslationNote>
1. ##### サイドカーの実行
サイドカー・バイナリは、Rust コードからでも、直接 JavaScript からでも実行できます。
<Tabs syncKey="lang">
<TabItem label="JavaScript">
Node.js サイドカーで `ping` コマンドを直接実行してみましょう:
```javascript
import { Command } from '@tauri-apps/plugin-shell';
const message = 'Tauri';
const command = Command.sidecar('binaries/app', ['ping', message]);
const output = await command.execute();
const response = output.stdout;
```
</TabItem>
<TabItem label="Rust">
Tauri コマンド `pipe` を Node.js サイドカーにパイプ処理をしてみましょう:
```rust
#[tauri::command]
async fn ping(app: tauri::AppHandle, message: String) -> String {
let sidecar_command = app
.shell()
.sidecar("app")
.unwrap()
.arg("ping")
.arg(message);
let output = sidecar_command.output().unwrap();
let response = String::from_utf8(output.stdout).unwrap();
response
}
```
</TabItem>
</Tabs>
</Steps>
[サイドカー・ガイド]: /ja/develop/sidecar/
[process.argv]: https://nodejs.org/docs/latest/api/process.html#processargv
[console.log]: https://nodejs.org/api/console.html#consolelogdata-args
[pkg]: https://github.com/vercel/pkg
[`bundle > externalBin`]: /reference/config/#externalbin
<div style="text-align: right">
【※ この日本語版は、「Feb 22, 2025 英語版」に基づいています】
</div>

View File

@@ -0,0 +1,274 @@
---
title: スプラッシュスクリーン(起動時表示画面)
sidebar:
order: 1
tableOfContents:
minHeadingLevel: 2
maxHeadingLevel: 5
i18nReady: true
---
import { Image } from 'astro:assets';
import step_1 from '@assets/learn/splashscreen/step_1.png';
import step_3 from '@assets/learn/splashscreen/step_3.png';
import { Steps, Tabs, TabItem } from '@astrojs/starlight/components';
import ShowSolution from '@components/ShowSolution.astro';
import CTA from '@fragments/cta.mdx';
import TranslationNote from '@components/i18n/TranslationNote.astro';
この「試作ラボ」では、Tauri アプリに基本的なスプラッシュスクリーン機能を実装します。
やりかたは至って単純明快です。スプラッシュスクリーンは、実質的には、アプリがセットアップ関連の負荷の高いタスクを実行している間中、相応のコンテンツを表示する新しいウィンドウを描画し、セットアップが完了したらそのウィンドウを閉じるだけです。
## 事前準備
:::tip[試作アプリの作成]
あなたが上級ユーザーでない場合は、ここで提供されているオプションとフレームワークを使用することを**強く推奨**します。これはあくまで「試作(ラボ)」なので、完了したらプロジェクトを削除できます。
<CTA />
- プロジェクト名: `splashscreen-lab`
- フロントエンド用言語の選択: `Typescript / Javascript`
- パッケージ・マネージャーの選択: `pnpm`
- UI テンプレートの選択: `Vanilla`
- UI フレーバーの選択: `Typescript`
- モバイル用プロジェクトも設定しますか?: `yes`
:::
## 作業手順
<Steps>
1. ##### 依存関係のインストールとプロジェクトの実行
プロジェクトの開発を始める前に、セットアップが意図したとおりに動作していることを確認するために、初期テンプレートをビルドして実行することが重要です。
<ShowSolution>
```sh frame=none
# 正しいディレクトリにいることを確認してください
cd splashscreen-lab
# 依存関係をインストール
pnpm install
# アプリのビルドと実行
pnpm tauri dev
```
<Image src={step_1} alt="Successful run of the created template app." />
</ShowSolution>
1. ##### `tauri.conf.json` に新しいウィンドウを登録
新しいウィンドウを追加する最も簡単な方法は、`tauri.conf.json` に直接追加することです。
起動時に動的にウィンドウを作成することもできますが、簡素化のために、そうはせずに直接登録することにします。
`main` というラベルのウィンドウが「非表示」ウィンドウとして、`splashscreen` というラベルのウィンドウが「直接表示」されるウィンドウとして作成されていることを確認してください。その他のオプション項目はどれも、デフォルト設定のままでも、好みに応じて調整しても構いません。
<ShowSolution>
```json
// src-tauri/tauri.conf.json
{
"windows": [
{
"label": "main",
"visible": false
},
{
"label": "splashscreen",
"url": "/splashscreen"
}
]
}
```
</ShowSolution>
1. ##### スプラッシュスクリーンをホストする新しいページの作成
ページの作成を始める前に、表示するコンテンツをいくつか準備する必要があります。
新しいページをどのように展開するのかは、選択したフレームワークによって異なりますが、ほとんどのフレームワークにはページ・ナビゲーションを処理する「ルーター」という考え方があり、Tauri で普通に機能するはずです。そうであれば、あとは新しいスプラッシュスクリーン・ページを生成するだけです。
あるいは、以下で行なうように、コンテンツをホストするための新しい `splashscreen.html` ファイルを作成します。
ここで重要なのは、「URL `/splashscreen`」にアクセスでき、スプラッシュスクリーンに表示したいコンテンツが表示されることです。この手順を完了したら、アプリをもう一度実行して確かめてみてください。
<ShowSolution>
```html
// /splashscreen.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="/src/styles.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri App</title>
</head>
<body>
<div class="container">
<h1>Tauri used Splash!</h1>
<div class="row">
<h5>It was super effective!</h5>
</div>
</div>
</body>
</html>
```
<Image src={step_3} alt="The splashscreen we just created."/>
</ShowSolution>
1. ##### 起動タスクの開始
一般的に、スプラッシュスクリーンは起動時の重いタスクを隠すことを意図しているため、アプリのフロントエンドとバックエンドでいくつかの重い処理を擬似実行させて見ましょう。
フロントエンドで重い起動処理を擬似実行するには、単純な `setTimeout` 関数を使用します。
一方、バックエンドで重い操作を擬似実行する最も簡単な方法は、Tokio クレートを使用することです。これは、バックエンドで非同期ランタイムを提供するために Tauri が使用する Rust クレートです。Tauri がランタイムを提供する一方で、クレートから再エクスポートしない様々なユーティリティがあるため、そのようなユーティリティにアクセスするために、Tokio クレートをプロジェクトに追加する必要があります。これは Rust エコシステムではごく一般的なやりかたです。
非同期関数では `std::thread::sleep` を使用しないでください。非同期関数は、並列ではなく同時実行環境で協調的に実行されます。つまり、Tokio タスクの代わりにこの `std::thread::sleep` 関数でスレッドをスリープ状態にすると、そのスレッドで実行するようにスケジュールされているすべてのタスクの実行がロックされ、アプリがフリーズします。
<ShowSolution>
```sh frame=none
# `Cargo.toml`ファイルがある場所でこのコマンドを実行
cd src-tauri
# Tokio crate の追加
cargo add tokio
# 必要に応じてトップ・フォルダに戻り開発作業を継続
# `tauri dev` がどこで実行するかを自動判断
cd ..
```
```javascript
// src/main.ts
// 以下の内容は既存のコードの下にコピーして貼り付けることができますが、ファイル全体を置き換えないでください。
// TypeScript でスリープ機能を実装するためのユーティリティ関数
function sleep(seconds: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, seconds * 1000));
}
// Setup 関数
async function setup() {
// 非常に重い起動処理タスクを擬似実行
console.log('Performing really heavy frontend setup task...')
await sleep(3);
console.log('Frontend setup task complete!')
// フロントエンド・タスクを完了済みとして設定
invoke('set_complete', {task: 'frontend'})
}
// 実質的に JavaScript のメイン関数
window.addEventListener("DOMContentLoaded", () => {
setup()
});
```
```rust
// /src-tauri/src/lib.rs
// 利用する機能をインポート
use std::sync::Mutex;
use tauri::async_runtime::spawn;
use tauri::{AppHandle, Manager, State};
use tokio::time::{sleep, Duration};
// 起動関連タスクの完了を追跡するために使用する構造体を作成
struct SetupState {
frontend_task: bool,
backend_task: bool,
}
// バージョン 2 モバイル対応アプリでのメイン・エントリーポイント
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
// Tauri の起動前ではなく、起動フック部分にコードを記載してください!
tauri::Builder::default()
// Tauri で管理される `State` を登録する
// これには書き込みアクセスが必要なので、`Mutex`でラップします。
.manage(Mutex::new(SetupState {
frontend_task: false,
backend_task: false,
}))
// 確認に使用するコマンドの追加
.invoke_handler(tauri::generate_handler![greet, set_complete])
// 起動関連タスクの実行に起動フックを使用
// メインループの前に実行されるため、ウィンドウはまだ作成されません
.setup(|app| {
// 起動を非ブロッキング処理として生成し、実行中にウィンドウを生成・実行可能にします。
spawn(setup(app.handle().clone()));
// フックは「Ok」という結果を要求します
Ok(())
})
// アプリを実行
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
#[tauri::command]
fn greet(name: String) -> String {
format!("Hello {name} from Rust!")
}
// 起動タスクの状態を設定するためのカスタム・タスク
#[tauri::command]
async fn set_complete(
app: AppHandle,
state: State<'_, Mutex<SetupState>>,
task: String,
) -> Result<(), ()> {
// 書き込みアクセスなしで状態をロック
let mut state_lock = state.lock().unwrap();
match task.as_str() {
"frontend" => state_lock.frontend_task = true,
"backend" => state_lock.backend_task = true,
_ => panic!("invalid task completed!"),
}
// フロントエンド・バックエンド両方のタスクが完了したかどうかを確認
if state_lock.backend_task && state_lock.frontend_task {
// 起動が完了したら、スプラッシュスクリーンを閉じてメインウィンドウを提示
let splash_window = app.get_webview_window("splashscreen").unwrap();
let main_window = app.get_webview_window("main").unwrap();
splash_window.close().unwrap();
main_window.show().unwrap();
}
Ok(())
}
// 重い起動タスクを実行する非同期関数
async fn setup(app: AppHandle) -> Result<(), ()> {
// 重い処理を 3 秒間擬似実行
println!("Performing really heavy backend setup task...");
sleep(Duration::from_secs(3)).await;
println!("Backend setup task completed!");
// バックエンドタスクを完了済みとして設定
// 入力引数を自分で処理する限り、コマンドは通常の関数として実行できます。
set_complete(
app.clone(),
app.state::<Mutex<SetupState>>(),
"backend".to_string(),
)
.await?;
Ok(())
}
```
</ShowSolution>
1. ##### アプリケーションの実行
これでスプラッシュスクリーン・ウィンドウがポップアップ表示され、フロントエンドとバックエンドの両方でそれぞれ 3 秒間の重い起動タスクが実行され、その後スプラッシュスクリーンが消えてメイン・ウィンドウに切り替わります。
</Steps>
## 争点
##### スプラッシュスクリーンは必要ですか?
一般的に、スプラッシュスクリーンを表示するということは、スプラッシュスクリーンを必要としないほどアプリの読み込み速度を上げることができなかったという敗北を認めることになります。
実際、メイン・ウィンドウを直接表示して、メイン・ウィンドウの隅のどこかに小さなスピナー(進捗表示計)を表示し、バックグラウンドで起動タスクがまだ実行中であることをユーザーに通知する方がどちらかといえばよいでしょう。
ただし、そうは言っても、スプラッシュスクリーンを表示したいというスタイル上の選択があったり、特定のタスクが実行されるまでアプリを起動できなくしたいという特殊な事情がある場合もあります。
スプラッシュスクリーンがあることは決して*間違って*いるというわけではありませんが、必ずしも必要とされない傾向にあり、ユーザーにアプリがあまり最適化されていないと感じさせる可能性があります。
<div style="text-align: right">
【※ この日本語版は、「Feb 22, 2025 英語版」に基づいています】
</div>

View File

@@ -0,0 +1,328 @@
---
title: システム・トレイ
sidebar:
order: 1
tableOfContents:
maxHeadingLevel: 4
i18nReady: true
---
import { Icon } from '@astrojs/starlight/components';
import { Tabs, TabItem } from '@astrojs/starlight/components';
import TranslationNote from '@components/i18n/TranslationNote.astro';
Tauri では、あなたのアプリケーション用に「システム・トレイ」を作成およびカスタマイズできます。
これにより、一般的なアクションにすばやくアクセスできるようになり、ユーザー・エクスペリエンスが向上します。
## 設定
まず初めに、`Cargo.toml` をアップデートし、「システム・トレイ」に必要な機能が含まれるようにします。
```toml title="src-tauri/Cargo.toml"
tauri = { version = "2.0.0", features = [ "tray-icon" ] }
```
## 使用方法
「トレイ API」は JavaScript と Rust の両方で利用できます。
<TranslationNote lang="ja">
**トレイ API** tray API 以下、本稿での各関数へのリンクは、「英語版」のみです。
</TranslationNote>
### トレイ・アイコンの生成
<Tabs synckey="language">
<TabItem label="JavaScript">
新しい「トレイ・アイコン」を作成するには、静的関数 [`TrayIcon.new`] を使用します。
```javascript
import { TrayIcon } from '@tauri-apps/api/tray';
const options = {
// この部分には、トレイ・メニューtray menu、タイトルtitle、ツールチップtooltip、イベント・ハンドラーevent handlerなどを追加できます。
};
const tray = await TrayIcon.new(options);
```
カスタマイズ・オプションの詳細については、リンク先 [`TrayIconOptions`] を参照してください。
</TabItem>
<TabItem label="Rust">
```rust
use tauri::tray::TrayIconBuilder;
tauri::Builder::default()
.setup(|app| {
let tray = TrayIconBuilder::new().build(app)?;
Ok(())
})
```
カスタマイズ・オプションの詳細については、リンク先 [`TrayIconBuilder`] を参照してください。
</TabItem>
</Tabs>
### トレイ・アイコンの変更
トレイの生成時には、アプリケーション・アイコンをトレイ・アイコンとして利用できます。
<Tabs syncKey="lang">
<TabItem label="JavaScript">
```javascript
import { TrayIcon } from '@tauri-apps/api/tray';
import { defaultWindowIcon } from '@tauri-apps/api/app';
const options = {
icon: await defaultWindowIcon(),
};
const tray = await TrayIcon.new(options);
```
</TabItem>
<TabItem label="Rust">
```rust
let tray = TrayIconBuilder::new()
.icon(app.default_window_icon().unwrap().clone())
.build(app)?;
```
</TabItem>
</Tabs>
### メニューの追加
トレイをクリックしたときに表示される「メニュー」を追加するには、`menu` オプションを使用します。
:::note
デフォルトでは、このメニューは左クリックでも右クリックでも表示されます。
左クリックでメニューが表示されないようにするには、Rust 関数の [`menu_on_left_click(false)`][TrayIconBuilder::menu_on_left_click] を呼び出すか、
JavaScript オプションの [`menuOnLeftClick`] を `false` に設定してください。
:::
{/* TODO: link to the menu plugin documentation page */}
<Tabs syncKey="lang">
<TabItem label="JavaScript">
```javascript
import { TrayIcon } from '@tauri-apps/api/tray';
import { Menu } from '@tauri-apps/api/menu';
const menu = await Menu.new({
items: [
{
id: 'quit',
text: 'Quit',
},
],
});
const options = {
menu,
menuOnLeftClick: true,
};
const tray = await TrayIcon.new(options);
```
</TabItem>
<TabItem label="Rust">
```rust
use tauri::{
menu::{Menu, MenuItem},
tray::TrayIconBuilder,
};
let quit_i = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?;
let menu = Menu::with_items(app, &[&quit_i])?;
let tray = TrayIconBuilder::new()
.menu(&menu)
.menu_on_left_click(true)
.build(app)?;
```
</TabItem>
</Tabs>
#### メニュー・イベントへの応答
<Tabs syncKey="lang">
<TabItem label="JavaScript">
JavaScript では、「メニュー・クリック・イベント・リスナー」をメニュー項目に直接記述できます:
- メニュー・クリック・ハンドラーを共有利用する場合
```javascript
import { Menu } from '@tauri-apps/api/menu';
function onTrayMenuClick(itemId) {
// itemId === 'quit'
}
const menu = await Menu.new({
items: [
{
id: 'quit',
text: 'Quit',
action: onTrayMenuClick,
},
],
});
```
- 専用のメニュー・クリック・ハンドラーを使用する場合
```javascript
import { Menu } from '@tauri-apps/api/menu';
const menu = await Menu.new({
items: [
{
id: 'quit',
text: 'Quit',
action: () => {
console.log('quit pressed');
},
},
],
});
```
</TabItem>
<TabItem label="Rust">
[`TrayIconBuilder::on_menu_event`] メソッドを使用して、トレイ・メニュー・クリック・イベント・リスナーを記述します。
```rust
use tauri::tray::TrayIconBuilder;
TrayIconBuilder::new()
.on_menu_event(|app, event| match event.id.as_ref() {
"quit" => {
println!("quit menu item was clicked");
app.exit(0);
}
_ => {
println!("menu item {:?} not handled", event.id);
}
})
```
</TabItem>
</Tabs>
### トレイ・イベントへの応答
「トレイ・アイコン」は、次のような「マウス・イベント」に対してイベントを発行します。
- クリックClick カーソルが左、右、または中央のシングル・クリックを受け取ったときに、マウスのクリックが解除されたかどうかの情報も含めて、トリガーされます。
- ダブルクリックDoubleClick カーソルが左、右、または中央のダブルクリックを受け取ったときにトリガーされます。
- 進入Enter カーソルがトレイ・アイコン領域に入ったときにトリガーされます
- 移動Move カーソルがトレイ・アイコン領域内を移動したときにトリガーされます
- 離脱Leave カーソルがトレイ・アイコン領域から離れた時にトリガーされます
<Tabs>
<TabItem label="JavaScript">
```javascript
import { TrayIcon } from '@tauri-apps/api/tray';
const options = {
action: (event) => {
switch (event.type) {
case 'Click':
console.log(
`mouse ${event.button} button pressed, state: ${event.buttonState}`
);
break;
case 'DoubleClick':
console.log(`mouse ${event.button} button pressed`);
break;
case 'Enter':
console.log(
`mouse hovered tray at ${event.rect.position.x}, ${event.rect.position.y}`
);
break;
case 'Move':
console.log(
`mouse moved on tray at ${event.rect.position.x}, ${event.rect.position.y}`
);
break;
case 'Leave':
console.log(
`mouse left tray at ${event.rect.position.x}, ${event.rect.position.y}`
);
break;
}
},
};
const tray = await TrayIcon.new(options);
```
「イベント・ペイロード」の詳細については、[`TrayIconEvent`][js TrayIconEvent] を参照してください。
</TabItem>
<TabItem label="Rust">
```rust
use tauri::{
Manager,
tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}
};
TrayIconBuilder::new()
.on_tray_icon_event(|tray, event| match event {
TrayIconEvent::Click {
button: MouseButton::Left,
button_state: MouseButtonState::Up,
..
} => {
println!("left click pressed and released");
// この例では、トレイがクリックされたときに「let」文がメインウィンドウを表示しアクティブ化します。
let app = tray.app_handle();
if let Some(window) = app.get_webview_window("main") {
let _ = window.show();
let _ = window.set_focus();
}
}
_ => {
println!("unhandled event {event:?}");
}
})
```
「イベント型」の詳細については、[`TrayIconEvent`][rust TrayIconEvent] を参照してください。
</TabItem>
</Tabs>
[`TrayIcon.new`]: /reference/javascript/api/namespacetray/#new
[`TrayIconOptions`]: /reference/javascript/api/namespacetray/#trayiconoptions
[`TrayIconBuilder`]: https://docs.rs/tauri/2.0.0/tauri/tray/struct.TrayIconBuilder.html
[TrayIconBuilder::menu_on_left_click]: https://docs.rs/tauri/2.0.0/tauri/tray/struct.TrayIconBuilder.html#method.menu_on_left_click
[`menuOnLeftClick`]: /reference/javascript/api/namespacetray/#properties-1
[`TrayIconBuilder::on_menu_event`]: https://docs.rs/tauri/2.0.0/tauri/tray/struct.TrayIconBuilder.html#method.on_menu_event
[js TrayIconEvent]: /reference/javascript/api/namespacetray/#trayiconevent
[rust TrayIconEvent]: https://docs.rs/tauri/2.0.0/tauri/tray/enum.TrayIconEvent.html
<div style="text-align: right">
【※ この日本語版は、「Jul 08, 2025 英語版」に基づいています】
</div>

View File

@@ -0,0 +1,300 @@
---
title: ウィンドウのカスタマイズ
sidebar:
order: 1
tableOfContents:
maxHeadingLevel: 4
i18nReady: true
---
import { Icon } from '@astrojs/starlight/components';
import TranslationNote from '@components/i18n/TranslationNote.astro';
Tauri は、あなたのアプリのウィンドウ外観や操作性をカスタマイズするための豊富なオプションを提供しています。カスタム・タイトルバーの作成や、透明なウィンドウ、サイズ制限の適用などが可能になります。
## 設定
ウィンドウ設定を変更するには、次の三通りの方法があります:
- <Icon name="external" class="inline-icon" /> [tauri.conf.json
を用いて](/reference/config/#windowconfig)
- <Icon name="external" class="inline-icon" /> [JavaScript API
を用いて](/reference/javascript/api/namespacewindow/#window)
- <Icon name="external" class="inline-icon" /> [Rust の Window
構造体を用いて](https://docs.rs/tauri/2.0.0/tauri/window/struct.Window.html)
## 使用法
- [カスタム・タイトルバーの作成](#カスタムタイトルバーの作成)
- [(macOS) カスタム・ウィンドウ背景色付きの透明なタイトルバー](#macos-カスタムウィンドウ背景色付きの透明なタイトルバー)
### カスタム・タイトルバーの作成
このようなウィンドウ機能の一般的な用途は、カスタム・タイトルバーの作成です。この短いチュートリアルでは、その工程を順を追って説明します。
:::note
macOS では、カスタム・タイトルバーを使用すると、[ウィンドウの移動や配置](https://support.apple.com/ja-jp/guide/mac-help/mchlp2469/mac) といった、システム自身によって提供されているいくつかの機能が失われます。
そのようなネイティブ機能を維持しながらタイトルバーをカスタマイズする別の方法として、タイトルバーを透明にしてウィンドウの背景色を設定する方法があります。そのやりかたについては、こちらの[(macOS) カスタムウィンドウ背景色を使用した透明なタイトルバー](#macos-カスタムウィンドウ背景色付きの透明なタイトルバー)をご覧ください。
:::
#### tauri.conf.json
`tauri.conf.json` で `decorations` 項目を「`false`」に設定します。
```json title="tauri.conf.json" {4}
"tauri": {
"windows": [
{
"decorations": false
}
]
}
```
#### アクセス権
「セキュリティ機能 capability ファイル」でウィンドウに「アクセス権」を追加します。
デフォルトでは、すべてのプラグイン・コマンドのアクセス権はブロックされており、アクセスできません。「セキュリティ機能`capabilities`」設定でアクセス権リストを定義する必要があります。
詳細については「[セキュリティ・レベルの概要](/ja/security/capabilities/)」の章を参照してください。また、プラグイン権限を使用するには「[プラグイン・アクセス権の使用](/ja/learn/security/using-plugin-permissions/)」の章を参照してください。
```json title="src-tauri/capabilities/default.json" ins={6}
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "main-capability",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": ["core:window:default", "core:window:allow-start-dragging"]
}
```
| Permission | Description |
| -------------------------------------------- | -------------------------------------------------------------------------------- |
| `core:window:default` | plugin 用デフォルト・アクセス権。ただし、 `window:allow-start-dragging` を除く。 |
| `core:window:allow-close` | スコープ(適用範囲)の事前設定なしで close コマンドを有効にします。 |
| `core:window:allow-minimize` | スコープの事前設定なしで minimize コマンドを有効にします。 |
| `core:window:allow-start-dragging` | スコープの事前設定なしで start_dragging コマンドを有効にします。 |
| `core:window:allow-toggle-maximize` | スコープの事前設定なしで toggle_maximize コマンドを有効にします。 |
| `core:window:allow-internal-toggle-maximize` | スコープの事前設定なしで internal_toggle_maximize コマンドを有効にします。 |
#### CSS
この CSS サンプルを追加して、タイトルバーを画面の上部に表示し、ボタンのスタイルを設定します:
```css
.titlebar {
height: 30px;
background: #329ea3;
user-select: none;
display: grid;
grid-template-columns: auto max-content;
position: fixed;
top: 0;
left: 0;
right: 0;
}
.titlebar > .controls {
display: flex;
}
.titlebar button {
appearance: none;
padding: 0;
margin: 0;
border: none;
display: inline-flex;
justify-content: center;
align-items: center;
width: 30px;
background-color: transparent;
}
.titlebar button:hover {
background: #5bbec3;
}
```
#### HTML
以下を `<body>` タグの最初に置いてください:
```html
<div class="titlebar">
<div data-tauri-drag-region></div>
<div class="controls">
<button id="titlebar-minimize" title="minimize">
<!-- https://api.iconify.design/mdi:window-minimize.svg -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="currentColor" d="M19 13H5v-2h14z" /><path>
</svg>
</button>
<button id="titlebar-maximize" title="maximize">
<!-- https://api.iconify.design/mdi:window-maximize.svg -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="currentColor" d="M4 4h16v16H4zm2 4v10h12V8z" />
</svg>
</button>
<button id="titlebar-close" title="close">
<!-- https://api.iconify.design/mdi:close.svg -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path
fill="currentColor"
d="M13.46 12L19 17.54V19h-1.46L12 13.46L6.46 19H5v-1.46L10.54 12L5 6.46V5h1.46L12 10.54L17.54 5H19v1.46z"
/>
</svg>
</button>
</div>
</div>
```
タイトルバーに隠れないように、残りのコンテンツを下に移動する必要があるかもしれないことに注意してください。
:::tip
Windows で、カスタム仕様のインタラクション(応答操作)を必要としないタイトル・バーだけで十分な場合には、以下を使用すると
```css
*[data-tauri-drag-region] {
app-region: drag;
}
```
タイトル・バーをタッチやペン入力で操作できるようになります。
:::
#### JavaScript
ボタンを機能させるには、以下のコード・スニペットを使用します:
```javascript
import { getCurrentWindow } from '@tauri-apps/api/window';
// `"withGlobalTauri": true` を使用する場合は、
// const { getCurrentWindow } = window.__TAURI__.window; を使用できます。
const appWindow = getCurrentWindow();
document
.getElementById('titlebar-minimize')
?.addEventListener('click', () => appWindow.minimize());
document
.getElementById('titlebar-maximize')
?.addEventListener('click', () => appWindow.toggleMaximize());
document
.getElementById('titlebar-close')
?.addEventListener('click', () => appWindow.close());
```
なお、Rust ベースのフロントエンドを使用しているのであれば、上記 HTML 項のコードを `index.html` ファイルの `<script>` 要素にコピーしてください。
:::note
`data-tauri-drag-region` 属性は、それが直接適用された「要素」に対してのみ機能します。同じドラッグ動作を子要素にも適用したい場合は、各子要素にも個別に追加する必要があります。
この動作は保持されますので、ボタンや入力などのインタラクティブな要素は適切に機能します。
:::
### `data-tauri-drag-region` の手作業による実装
ドラッグ動作をカスタマイズするようなユース・ケース(使用事例)では、`data-tauri-drag-region` を使用する代わりに、`window.startDragging` を使用してイベント・リスナーを手作業で追加できます。
#### HTML
前項のコードから、`data-tauri-drag-region` を削除し、`id` を追加します:
```html del={1} ins={2}
<div data-tauri-drag-region class="titlebar">
<div id="titlebar" class="titlebar">
<!-- ... -->
</div>
</div>
```
#### Javascript
タイトルバー要素にイベント・リスナーを追加します:
```js {2-9}
// ...
document.getElementById('titlebar')?.addEventListener('mousedown', (e) => {
if (e.buttons === 1) {
// 主ボタン(左)
e.detail === 2
? appWindow.toggleMaximize() // ダブルクリックで最大化
: appWindow.startDragging(); // それ以外ではドラッグ開始
}
});
```
### (macOS) カスタム・ウィンドウ背景色付きの透明なタイトルバー
メイン・ウィンドウを作成し、その背景色を Rust 側から変更します。
`tauri.conf.json` ファイルからメイン・ウィンドウを削除します:
```json title="tauri.conf.json" del={3-7}
"tauri": {
"windows": [
{
"title": "Transparent Titlebar Window",
"width": 800,
"height": 600
}
],
}
```
依存関係に `cocoa` クレートを追加し、macOS のネイティブ API を呼び出しに使用できるようにします:
```toml title="src-tauri/Cargo.toml"
[target."cfg(target_os = \"macos\")".dependencies]
cocoa = "0.26"
```
メイン・ウィンドウを作成し、その背景色を変更します:
```rust title="src-tauri/src/lib.rs"
use tauri::{TitleBarStyle, WebviewUrl, WebviewWindowBuilder};
pub fn run() {
tauri::Builder::default()
.setup(|app| {
let win_builder =
WebviewWindowBuilder::new(app, "main", WebviewUrl::default())
.title("Transparent Titlebar Window")
.inner_size(800.0, 600.0);
// macOS 用にビルドする場合にのみ適用される、透明なタイトル・バーを設定します
#[cfg(target_os = "macos")]
let win_builder = win_builder.title_bar_style(TitleBarStyle::Transparent);
let window = win_builder.build().unwrap();
// macOS 用にビルドする場合にのみ適用される、背景色を設定します
#[cfg(target_os = "macos")]
{
use cocoa::appkit::{NSColor, NSWindow};
use cocoa::base::{id, nil};
let ns_window = window.ns_window().unwrap() as id;
unsafe {
let bg_color = NSColor::colorWithRed_green_blue_alpha_(
nil,
50.0 / 255.0,
158.0 / 255.0,
163.5 / 255.0,
1.0,
);
ns_window.setBackgroundColor_(bg_color);
}
}
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
```
<div style="text-align: right">
【※ この日本語版は、「Jul 04, 2025 英語版」に基づいています】
</div>

View File

@@ -0,0 +1,562 @@
---
title: ウィンドウ・メニュー
tableOfContents:
maxHeadingLevel: 4
i18nReady: true
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import TranslationNote from '@components/i18n/TranslationNote.astro';
ネイティブのアプリケーション・メニューは、ウィンドウとシステム・トレイの両方に配置できます。デスクトップで利用が可能です。
## 基本メニューの作成
基本のネイティブ・ウィンドウ・メニューを作成し、ウィンドウに組み込むには、次の手順を実行します:
<Tabs>
<TabItem label="JavaScript">
ウィンドウ・メニューを作成するには、静的関数 [`Menu.new`] を使用します:
```javascript
import { Menu } from '@tauri-apps/api/menu';
const menu = await Menu.new({
items: [
{
id: 'quit',
text: 'Quit',
action: () => {
console.log('quit pressed');
},
},
],
});
// ウィンドウが明示的なメニューを使用して作成されていない場合、あるいは明示的にメニューが設定されていない場合は、次のメニューがそのウィンドウに割り当てられます。
menu.setAsAppMenu().then((res) => {
console.log('menu set success', res);
});
```
</TabItem>
<TabItem label="Rust">
```rust
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use tauri::menu::{MenuBuilder};
fn main() {
tauri::Builder::default()
.setup(|app| {
let menu = MenuBuilder::new(app)
.text("open", "Open")
.text("close", "Close")
.build()?;
app.set_menu(menu)?;
Ok(())
})
}
```
</TabItem>
</Tabs>
## カスタム・メニュー項目のイベントを検知
カスタム・メニューの各項目はクリック時にイベントをトリガーします。イベントを処理するには、`on_menu_event` API を使用してください。
<Tabs>
<TabItem label="JavaScript">
```javascript
import { Menu } from '@tauri-apps/api/menu';
const menu = await Menu.new({
items: [
{
id: 'Open',
text: 'open',
action: () => {
console.log('open pressed');
},
},
{
id: 'Close',
text: 'close',
action: () => {
console.log('close pressed');
},
},
],
});
await menu.setAsAppMenu();
```
</TabItem>
<TabItem label="Rust">
```rust
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use tauri::menu::{MenuBuilder};
fn main() {
tauri::Builder::default()
.setup(|app| {
let menu = MenuBuilder::new(app)
.text("open", "Open")
.text("close", "Close")
.build()?;
app.set_menu(menu)?;
app.on_menu_event(move |app_handle: &tauri::AppHandle, event| {
println!("menu event: {:?}", event.id());
match event.id().0.as_str() {
"open" => {
println!("open event");
}
"close" => {
println!("close event");
}
_ => {
println!("unexpected menu event");
}
}
});
Ok(())
})
}
```
</TabItem>
</Tabs>
## 階層化されたメニューの作成
階層化されたメニューを作成するには、メニュー項目にいくつかのサブメニューを追加します:
<Tabs>
<TabItem label="JavaScript">
```javascript
import { Menu, MenuItem, Submenu } from '@tauri-apps/api/menu';
const fileSubmenu = await Submenu.new({
text: 'File',
items: [
await MenuItem.new({
id: 'new',
text: 'New',
action: () => {
console.log('New clicked');
},
}),
await MenuItem.new({
id: 'open',
text: 'Open',
action: () => {
console.log('Open clicked');
},
}),
await MenuItem.new({
id: 'save_as',
text: 'Save As...',
action: () => {
console.log('Save As clicked');
},
}),
],
});
const editSubmenu = await Submenu.new({
text: 'Edit',
items: [
await MenuItem.new({
id: 'undo',
text: 'Undo',
action: () => {
console.log('Undo clicked');
},
}),
await MenuItem.new({
id: 'redo',
text: 'Redo',
action: () => {
console.log('Redo clicked');
},
}),
],
});
const menu = await Menu.new({
items: [
fileSubmenu,
editSubmenu,
await MenuItem.new({
id: 'quit',
text: 'Quit',
action: () => {
console.log('Quit pressed');
},
}),
],
});
menu.setAsAppMenu();
```
</TabItem>
<TabItem label="Rust">
```rust
use tauri::menu::{CheckMenuItemBuilder, MenuBuilder, SubmenuBuilder};
fn main() {
tauri::Builder::default()
.setup(|app| {
let file_menu = SubmenuBuilder::new(app, "File")
.text("open", "Open")
.text("quit", "Quit")
.build()?;
let lang_str = "en";
let check_sub_item_1 = CheckMenuItemBuilder::new("English")
.id("en")
.checked(lang_str == "en")
.build(app)?;
let check_sub_item_2 = CheckMenuItemBuilder::new("Chinese")
.id("en")
.checked(lang_str == "en")
.enabled(false)
.build(app)?;
// パスからアイコンを読み込みます
let icon_image = Image::from_bytes(include_bytes!("../icons/icon.png")).unwrap();
let icon_item = IconMenuItemBuilder::new("icon")
.icon(icon_image)
.build(app)?;
let other_item = SubmenuBuilder::new(app, "language")
.item(&check_sub_item_1)
.item(&check_sub_item_2)
.build()?;
let menu = MenuBuilder::new(app)
.items(&[&file_menu, &other_item,&icon_item])
.build()?;
app.set_menu(menu)?;
Ok(())
})
}
```
<TranslationNote lang="ja">
**Rust での SubMenu 言語指定** 上記 Rust でのサブメニュー言語指定部分 `let lang_str = "en"` には、item_1「英語」とitem_2 「中国語」のみが指定されていますが、「日本語」用の設定方法不詳のため追記しておりません。必要に応じて修正・追加をお願いいたします。
</TranslationNote>
この API を使用するには、`image-ico` または `image-png` 機能を有効にする必要があることに注意してください。
```toml title="src-tauri/Cargo.toml"
[dependencies]
tauri = { version = "...", features = ["...", "image-png"] }
```
</TabItem>
</Tabs>
## 定義済みメニューの作成
オペレーティング・システムまたは Tauri によってあらかじめ定義された動作をする「組み込み(ネイティブ)のメニュー項目」を使用するには:
<Tabs>
<TabItem label="JavaScript">
```javascript
import { Menu, PredefinedMenuItem } from '@tauri-apps/api/menu';
const copy = await PredefinedMenuItem.new({
text: 'copy-text',
item: 'Copy',
});
const separator = await PredefinedMenuItem.new({
text: 'separator-text',
item: 'Separator',
});
const undo = await PredefinedMenuItem.new({
text: 'undo-text',
item: 'Undo',
});
const redo = await PredefinedMenuItem.new({
text: 'redo-text',
item: 'Redo',
});
const cut = await PredefinedMenuItem.new({
text: 'cut-text',
item: 'Cut',
});
const paste = await PredefinedMenuItem.new({
text: 'paste-text',
item: 'Paste',
});
const select_all = await PredefinedMenuItem.new({
text: 'select_all-text',
item: 'SelectAll',
});
const menu = await Menu.new({
items: [copy, separator, undo, redo, cut, paste, select_all],
});
await menu.setAsAppMenu();
```
</TabItem>
<TabItem label="Rust">
```rust
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use tauri::menu::{MenuBuilder, PredefinedMenuItem};
fn main() {
tauri::Builder::default()
.setup(|app| {
let menu = MenuBuilder::new(app)
.copy()
.separator()
.undo()
.redo()
.cut()
.paste()
.select_all()
.item(&PredefinedMenuItem::copy(app, Some("custom text"))?)
.build()?;
app.set_menu(menu)?;
Ok(())
})
}
```
プリセット機能の詳細については、[`PredefinedMenuItem`] のドキュメントを参照してください。
:::tip
メニュー・ビルダーには、定義済みの各メニュー項目を追加するための専用メソッドが用意されているため、`.item(&PredefinedMenuItem::copy(app, None)?)` の代わりに `.copy()` を呼び出すことができます。
:::
</TabItem>
</Tabs>
## メニュー状態の変更
テキスト、アイコン、チェック状況など、メニューの状態を変更する場合は、再度 `set_menu` を実行します:
<TranslationNote lang="ja">
**メニュー状態の変更** 以下の JavaScript / Rust の記載例には。こちらも「英語 en」表示用と「中国語 zh」表示用のみが記述されています。「日本語 ja」表示を行なうためには、記述の追加が必要かもしれません。必要に応じて修正・追加をお願いいたします。
</TranslationNote>
<Tabs>
<TabItem label="JavaScript">
```javascript
import {
Menu,
CheckMenuItem,
IconMenuItem,
MenuItem,
} from '@tauri-apps/api/menu';
import { Image } from '@tauri-apps/api/image';
let currentLanguage = 'en';
const check_sub_item_en = await CheckMenuItem.new({
id: 'en',
text: 'English',
checked: currentLanguage === 'en',
action: () => {
currentLanguage = 'en';
check_sub_item_en.setChecked(currentLanguage === 'en');
check_sub_item_zh.setChecked(currentLanguage === 'cn');
console.log('English pressed');
},
});
const check_sub_item_zh = await CheckMenuItem.new({
id: 'zh',
text: 'Chinese',
checked: currentLanguage === 'zh',
action: () => {
currentLanguage = 'zh';
check_sub_item_en.setChecked(currentLanguage === 'en');
check_sub_item_zh.setChecked(currentLanguage === 'zh');
check_sub_item_zh.setAccelerator('Ctrl+L');
console.log('Chinese pressed');
},
});
// パスからアイコンを読み込みます
const icon = await Image.fromPath('../src/icon.png');
const icon2 = await Image.fromPath('../src/icon-2.png');
const icon_item = await IconMenuItem.new({
id: 'icon_item',
text: 'Icon Item',
icon: icon,
action: () => {
icon_item.setIcon(icon2);
console.log('icon pressed');
},
});
const text_item = await MenuItem.new({
id: 'text_item',
text: 'Text Item',
action: () => {
text_item.setText('Text Item Changed');
console.log('text pressed');
},
});
const menu = await Menu.new({
items: [
{
id: 'change menu',
text: 'change_menu',
items: [text_item, check_sub_item_en, check_sub_item_zh, icon_item],
},
],
});
await menu.setAsAppMenu();
```
</TabItem>
<TabItem label="Rust">
```rust
// メニュー状態の変更
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use tauri::{
image::Image,
menu::{CheckMenuItemBuilder, IconMenuItem, MenuBuilder, MenuItem, SubmenuBuilder},
};
fn main() {
tauri::Builder::default()
.setup(|app| {
let check_sub_item_en = CheckMenuItemBuilder::with_id("en", "EN")
.checked(true)
.build(app)?;
let check_sub_item_zh = CheckMenuItemBuilder::with_id("zh", "ZH")
.checked(false)
.build(app)?;
let text_menu = MenuItem::with_id(
app,
"change_text",
&"Change menu".to_string(),
true,
Some("Ctrl+Z"),
)
.unwrap();
let icon_menu = IconMenuItem::with_id(
app,
"change_icon",
&"Change icon menu",
true,
Some(Image::from_bytes(include_bytes!("../icons/icon.png")).unwrap()),
Some("Ctrl+F"),
)
.unwrap();
let menu_item = SubmenuBuilder::new(app, "Change menu")
.item(&text_menu)
.item(&icon_menu)
.items(&[&check_sub_item_en, &check_sub_item_zh])
.build()?;
let menu = MenuBuilder::new(app).items(&[&menu_item]).build()?;
app.set_menu(menu)?;
app.on_menu_event(move |_app_handle: &tauri::AppHandle, event| {
match event.id().0.as_str() {
"change_text" => {
text_menu
.set_text("changed menu text")
.expect("Change text error");
text_menu
.set_text("changed menu text")
.expect("Change text error");
}
"change_icon" => {
icon_menu
.set_text("changed menu-icon text")
.expect("Change text error");
icon_menu
.set_icon(Some(
Image::from_bytes(include_bytes!("../icons/icon-2.png")).unwrap(),
))
.expect("Change icon error");
}
"en" | "zh" => {
check_sub_item_en
.set_checked(event.id().0.as_str() == "en")
.expect("Change check error");
check_sub_item_zh
.set_checked(event.id().0.as_str() == "zh")
.expect("Change check error");
check_sub_item_zh.set_accelerator(Some("Ctrl+L"))
.expect("Change accelerator error");
}
_ => {
println!("unexpected menu event");
}
}
});
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
```
</TabItem>
</Tabs>
[`PredefinedMenuItem`]: https://docs.rs/tauri/latest/tauri/menu/struct.PredefinedMenuItem.html
[`Menu.new`]: https://v2.tauri.app/reference/javascript/api/namespacemenu/#new-2
<div style="text-align: right">
【※ この日本語版は、「Apr 18, 2025 英語版」に基づいています】
</div>