Dioxus v0.5 でデスクトップアプリを作る
概要
Dioxus v0.5.0 がリリースされたので簡単な電卓アプリ(デスクトップアプリ)を作ってみます。
Dioxus とは
Rust で React ライクにマルチプラットフォームのアプリを作成することができます。
アプリ開発に必要な状態管理, ルーターが備わっています。
また、Tailwind を使用することもできます。
公式情報
環境
- rustc 1.76.0 (07dca489a 2024-02-04)
- cargo 1.76.0 (c84b36747 2024-01-18)
- Dioxus v0.5.0
- dioxus-cli v0.5.0
- Visual Studio Code 1.87.2
- Dioxus VSCode Extension v0.5.0
セットアップ
Getting Started を参考に Dioxus をセットアップします。
-
Visual Studio Code に Dioxus VSCode Extension を追加します。
-
デスクトップアプリの依存関係をインストールします。
-
Dioxus CLI をインストールします。
cargo install dioxus-cli@0.5.0
プロジェクトの作成
-
プロジェクトの作成を開始します。
dx new
-
テンプレートは Desktop を選択します。
? 🤷 Which sub-template should be expanded? › Web Liveview Fullstack ❯ Desktop TUI
-
プロジェクト名は calculator にします。
🤷 Project Name: calculator
-
Tailwind は使用しないので Vanilla を選択します。
? 🤷 How do you want to create CSS? › Tailwind ❯ Vanilla
-
ルーターは使用しないので false を選択します。
? 🤷 Should the application use the Dioxus router? › ❯ false true
-
作成したプロジェクトを実行します。
cd calculator dx serve --hot-reload --platform desktop
State
実装の前に State の使い分けについて簡単に説明します。
- 1 つのコンポーネントでしか State を使わない場合は、use_signal を使用します。(Component State)
- 複数のコンポーネントで State を使う場合は、use_context_provider を使用します。(Sharing State)
画面の実装
-
App コンポーネントを修正して電卓アプリの画面を実装します。
calculator/src/main.rs#[component] fn App() -> Element { rsx! { link { rel: "stylesheet", href: "main.css" } div { id: "calculator", div { id: "result", "0" } div { button { "1" } button { "2" } button { "3" } button { "+" } } div { button { "4" } button { "5" } button { "6" } button { "-" } } div { button { "7" } button { "8" } button { "9" } button { "*" } } div { button { "0" } button { "C" } button { "=" } button { "/" } } } } }
-
電卓アプリの画面デザインを実装します。
calculator/assets/main.cssbody { font-family: Arial, sans-serif; text-align: center; } #calculator { width: 300px; margin: 50px auto; border: 1px solid #ccc; padding: 20px; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } button { width: 50px; height: 50px; font-size: 20px; margin: 5px; border: none; cursor: pointer; border-radius: 5px; background-color: #f0f0f0; } button:hover { background-color: #e0e0e0; } #result { margin-top: 20px; font-size: 24px; font-weight: bold; }
-
プロジェクトを実行すると次の画面が表示されます。
ロジックの実装
-
式を評価するために使用する evalexpr を Cargo.toml > dependencies に追加します。
calculator/Cargo.toml[dependencies] evalexpr = "11.3.0"
-
引数を State に追加する関数を実装します。
calculator/src/main.rsfn appendToResult(ch: char) { let mut result_state = consume_context::<Signal<String>>(); let result = result_state(); if result == "0" || result == "Error" { *result_state.write() = ch.to_string(); } else { result_state.write().push(ch); } }
-
State をクリアする関数を実装します。
calculator/src/main.rsfn clearResult() { let mut result_state = consume_context::<Signal<String>>(); *result_state.write() = "0".to_string(); }
-
式を評価して State に書き込む関数を実装します。
calculator/src/main.rsfn calculate() { let mut result_state = consume_context::<Signal<String>>(); let evaluated = eval(result_state().as_str()); match evaluated { Ok(v) => { log::info!("Evaluated: {:?}", v); *result_state.write() = v.to_string(); }, Err(e) => { log::error!("Error: {:?}", e); *result_state.write() = "Error".to_string(); } } }
-
ボタンを押下したら対応する関数をコールするように App コンポーネントを修正します。
calculator/src/main.rs#[component] fn App() -> Element { use_context_provider(|| Signal::new("0".to_string())); let result_state = consume_context::<Signal<String>>(); rsx! { link { rel: "stylesheet", href: "main.css" } div { id: "calculator", div { id: "result", "{result_state()}" } div { button { onclick: move |_| { appendToResult('1'); }, "1" } button { onclick: move |_| { appendToResult('2'); }, "2" } button { onclick: move |_| { appendToResult('3'); }, "3" } button { onclick: move |_| { appendToResult('+'); }, "+" } } div { button { onclick: move |_| { appendToResult('4'); }, "4" } button { onclick: move |_| { appendToResult('5'); }, "5" } button { onclick: move |_| { appendToResult('6'); }, "6" } button { onclick: move |_| { appendToResult('-'); }, "-" } } div { button { onclick: move |_| { appendToResult('7'); }, "7" } button { onclick: move |_| { appendToResult('8'); }, "8" } button { onclick: move |_| { appendToResult('9'); }, "9" } button { onclick: move |_| { appendToResult('*'); }, "X" } } div { button { onclick: move |_| { appendToResult('0'); }, "0" } button { onclick: move |_| { clearResult(); }, "C" } button { onclick: move |_| { log::info!("= Button clicked"); calculate(); }, "=" } button { onclick: move |_| { appendToResult('/'); }, "/" } } } } }
-
プロジェクトを実行すると次の画面が表示されます。ボタンを押下して計算することができます。
Discussion
大変参考になりました。
ちなみに、dioxus cli のインストールは以下で良くなったみたいです。。
cargo install dioxus-cli
dx --version
dioxus 0.5.4