Rustはたまに触る程度で継続的にプログラミングを行っていないので時間が立つと忘れてしまいます。継続的に触れる機会としてなにかアプリケーションを作ろうと思います。ということでまずは見た目から。Rustで気になるGUI crateを試してみます。
どうやらデファクトスタンダードなGUI crateは現時点では存在せず、安定度もまちまちなようです。
そこで気になるcrateを使ってビルドができるのか?軽くサンプルプログラムを動作させて問題がなさそうか?、調べて見たいと思います。
2024/04-5月頃の情報になります。
ターゲット環境
開発環境
- Ubuntu 23.04 Desktop
- とりあえずOSBoxesよりダウンロードしたもので試用
- こちらでクロスコンパイルしてWindows向けにする
- 開発中はMobaXtermで画面をリモートに表示させたい
- rustc 1.77.2 (25ef9e3d8 2024-04-09)
実行環境
- Windows環境
dioxus
dioxusはデスクトップ、モバイル、Web、TUI(テキストベースのUI)などをカバーするフレームワークです。React系の設計思想です。クロスプラットフォーム対応です。
フルスタックを謳うフレームワークで機能が充実している分、必要なcrateが多いです。JavaScriptフレームワークのような専用コマンドが用意されています。
導入
sudo apt install -y gcc
sudo apt install -y make
cargo install [email protected]
dx new
✔ 🤷 Which sub-template should be expanded? · Desktop
🤷 Project Name: test01
✔ 🤷 How do you want to create CSS? · Vanilla
✔ 🤷 Should the application use the Dioxus router? · true
cd test01
sudo apt install -y pkg-config
sudo apt install -y librust-gio-sys-dev
sudo apt install -y libgtk-3-dev
sudo apt install -y libsoup-3.0-dev
sudo apt install -y libjavascriptcoregtk-4.1-dev
sudo apt install -y libwebkit2gtk-4.1-dev
sudo apt install -y libxdo-dev
dx serve --platform desktop
下記が場合によって必要かもしれません
sudo apt install -y libglib2.0-dev
クロスコンパイル
フレームワーク提供のコマンドで実行環境向けインストーラーが作成されるらしい。詳しくはこちらを参照。
main.rsに下記を追加(オプショナル。実行時にDOS窓が表示されなくなる。他のcrateにも有効)
#![windows_subsystem = "windows"]
Dioxus.tomlに下記を追加
[bundle]
resources = ["**/main.css", "**/header.svg" ]
dx bundle --release --platform desktop
Failed to bundle project: BundlerError(
Error {
context: "Failed to build data folders and files",
source: BundlerError(
Error {
context: "Failed to copy resource files",
source: IoError(
Os {
code: 36,
kind: InvalidFilename,
message: "File name too long",
},
),
},
),
},
)
結果
成果物はネイティブアプリケーションではありませんでした。Electronのような実行環境の中でロジックが動くイメージでした。そのため、リモートに画面を表示することができません。
クロスコンパイルはBundlerErrorが出て先に進みませんでした。distフォルダーにassetsフォルダーの内容がコピーされているので動いてそうですが原因がよくわかりませんでした。
Assetsのドキュメントを見るとmanganisという別の仕組みが必要なようですがまだ不安定な印象です。
floem
floemはLapceというRustで書かれたエディターで使われているUIフレームワークです。クロスプラットフォーム対応でXilemや Leptos等に影響を受けたリアクティブ系のフレームワークのようです。
State管理はSolidJSと同様のアプローチのようです。
エディターというアプリケーションの実需で使用されているので安定度は高そうです。
導入
# Cargo.toml
[dependencies]
floem = "0.1.1"
sudo apt install -y gcc
cargo b
画面を最大化した場合、落ちる
cargo r
failed to present the surface buffer: PlatformError(Some("Failed to draw image to window"), Some(X11(ConnectionError(MaximumRequestLengthExceeded))))
サンプルプログラム
READMEにあるものを流用。
#![windows_subsystem = "windows"]
use floem::reactive::create_signal;
use floem::view::View;
use floem::views::{h_stack, label, v_stack, Decorators};
use floem::widgets::button;
fn app_view() -> impl View {
// Create a reactive signal with a counter value, defaulting to 0
let (counter, set_counter) = create_signal(0);
// Create a vertical layout
v_stack((
// The counter value updates automatically, thanks to reactivity
label(move || format!("Value: {}", counter.get())),
// Create a horizontal layout
h_stack((
button(|| "Increment").on_click_stop(move |_| {
set_counter.update(|value| *value += 1);
}),
button(|| "Decrement").on_click_stop(move |_| {
set_counter.update(|value| *value -= 1);
}),
)),
))
}
fn main() {
floem::launch(app_view);
}
クロスコンパイル
sudo apt install -y mingw-w64
cargo build --target x86_64-pc-windows-gnu
結果
コードがシンプルで良さそうですが、X Window上で画面を最大化するだけで落ちてしまうのは不便だし安定度が疑わしくなってしまいます。クロスコンパイルしてWindows環境で実行した際には最大化しても問題ありませんでした。
まだ知名度は低いので日本語の情報は少ないです。
iced
icedはElmの設計思想に影響を受けた型安全なクロスプラットフォームのUIフレームワークです。Webまでカバーしているようですが、詳細は不明です。
導入
# Cargo.toml
[dependencies]
iced = "0.12.1"
sudo apt install -y gcc
cargo b
サンプルプログラム
Exampleより流用。
#![windows_subsystem = "windows"]
use iced::widget::{button, column, text};
use iced::{Alignment, Element, Sandbox, Settings};
pub fn main() -> iced::Result {
Counter::run(Settings::default())
}
struct Counter {
value: i32,
}
#[derive(Debug, Clone, Copy)]
enum Message {
IncrementPressed,
DecrementPressed,
}
impl Sandbox for Counter {
type Message = Message;
fn new() -> Self {
Self { value: 0 }
}
fn title(&self) -> String {
String::from("Counter - Iced")
}
fn update(&mut self, message: Message) {
match message {
Message::IncrementPressed => {
self.value += 1;
}
Message::DecrementPressed => {
self.value -= 1;
}
}
}
fn view(&self) -> Element<Message> {
column![
button("Increment").on_press(Message::IncrementPressed),
text(self.value).size(50),
button("Decrement").on_press(Message::DecrementPressed)
]
.padding(20)
.align_items(Alignment::Center)
.into()
}
}
クロスコンパイル
sudo apt install -y mingw-w64
cargo build --target x86_64-pc-windows-gnu
結果
コードがシンプルで良さそうです。クロスコンパイルも動作も問題ないようです。
ボタンの見た目がボタンらしくないのですが、サンプルを見るとちゃんとしているのでそのあたりの研究が必要かもしれません。レイアウト系がシンプルな仕組みのみで弱いかもしれません。
日本語の情報を多めです。ただし初心者向けのものが多いようです。
Vizia
Viziaは宣言的でリアクティブなクロスプラットフォーム対応のUIフレームワークです。アニメーションやGPUアクセラレーター対応のようです。
導入
# Cargo.toml
[dependencies]
#vizia = "0.1.0"
vizia = {git = "https://github.com/vizia/vizia"}
sudo apt install -y gcc
cargo b
サンプルプログラム
Bookより流用。
#![windows_subsystem = "windows"]
use vizia::prelude::*;
#[derive(Lens)]
pub struct AppData {
count: i32,
}
pub enum AppEvent {
Increment,
Decrement,
}
impl Model for AppData {
fn event(&mut self, _cx: &mut EventContext, event: &mut Event) {
event.map(|app_event, _meta| match app_event {
AppEvent::Decrement => self.count -= 1,
AppEvent::Increment => self.count += 1,
});
}
}
fn main() {
let _ = Application::new(|cx| {
AppData { count: 0 }.build(cx);
HStack::new(cx, |cx| {
Button::new(cx, |cx| Label::new(cx, "Decrement"))
.on_press(|ex| ex.emit(AppEvent::Decrement))
.class("dec");
Button::new(cx, |cx| Label::new(cx, "Increment"))
.on_press(|ex| ex.emit(AppEvent::Increment))
.class("inc");
Label::new(cx, AppData::count);
})
.child_space(Stretch(1.0))
.col_between(Pixels(20.0));
})
.title("Counter")
.inner_size((400, 100))
.run();
}
クロスコンパイル
sudo apt install -y mingw-w64
cargo build --target x86_64-pc-windows-gnu
結果
0.1.0ではコンパイルできませんでした。それ以外の部分では問題がありませんでした。
バージョンがまだ若いので今後大きな変化が起きる恐れがあります。
まとめ
各crateはほぼ何らかのJavaScriptフレームワークの影響を受けたものになっているので過去に使用したことがある場合は学習コストを抑えて使っていける可能性があります。
dioxusはエコシステムが充実しているので今後の期待度が高いですが、覚えることも多そうです。また、リモートに画面を表示することができなかったのが惜しいところです。
floemはシンプルに書けそうですが、最大化するだけで落ちるといった品質面に不安が残る結果となりました。またカッコが多くなりそうです。
icedはシンプルに書けそうですが、今回試した中でボタンの見た目が一番ネイティブ表示から遠いのでカスタマイズの可能性をもう少し調べる必要がありそうです。
Viziaは動作しますが、まだ公式バージョンが安定しておらず、バージョンも若いため今後大きな変化が起こる可能性があり、現時点で使用していくには勇気が必要です。
ただ、この記事を書いている最中もアップデートが進んでおり、上記紹介したサンプルも次のリビジョンで書き方が異なっているものもあります。これらのcrateを採用するにしても、まだプロトタイプレベルの使用に抑えておいたほうがいいかもしれません。