🦀

Rust: eguiを触ってみた

2024/12/17に公開

はじめに

つい最近触る機会があったのでRustでGUIが実装できるeguiの紹介をします。

https://github.com/emilk/egui

egui (pronounced "e-gooey") is a simple, fast, and highly portable immediate mode GUI library for Rust.

egui runs on the web, natively, and in your favorite game engine.

eguiの目指すところ

egui公式のGoalsより

  • 使いやすいGUIライブラリ
  • レスポンシブ:デバッグビルドで60 Hzを目標とする
  • フレンドリー:間違いを起こしにくく、パニックを引き起こさない
  • 移植性:同じコードがウェブとネイティブアプリの両方で動作する
  • どの環境にも簡単に統合できる(Web, Windows, MacOS, Linux...)
  • カスタム描画のためのシンプルな2D グラフィックスAPI(epaint)
  • Pure immediate mode:No callbacks
  • 拡張性:eguiのためのウィジェットを簡単に作成できる
  • モジュラー:eguiの小さな部分を使用し、新しい方法で組み合わせることができる
  • 最小限の依存関係

eguiの良いところ

  • コードが非常に簡単
    • crateを入れて、数十行のupdate関数を実装すれば完成
    • Immediate Modeというパターンを採用しているのでこの簡単さが実現されている
  • ビルドもそれなりに早く、本当にどこでも動く
    • Windows, Macで全く同じコードが動作する
  • 標準のUI要素が充実
  • 拡張も簡単
    • ユーザーが作成したUIもぼちぼち公開されているので自分でUIを考える必要がない

実装例

https://github.com/tokikokoko/simple-egui

実装例 - Cargo.toml

eframeはeguiチームが提供しているeguiのためのフレームワークです。簡単なアプリであれば依存関係はeframeだけで実装できてしまいます。

eguiレポジトリのexampleもeframeを使った例が多いので、基本的にはeframeを使ったほうが楽に実装できそうです。

[package]
name = "simple-egui"
version = "0.1.0"
edition = "2021"

[dependencies]
eframe = { version = "0.29.1", default-features = true }

実装例 - main.rs

struct SimpleApp {
    counter: u64,
    input: String,
    dpi: f32,
}

impl SimpleApp {
    fn new(cc: &eframe::CreationContext<'_>) -> Self {
        Self {
            counter: 0,
            input: "".to_string(),
            dpi: 1.5,
        }
    }

    fn reset(&mut self) {
        self.counter = 0;
        self.input = "".to_string();
        self.dpi = 1.5;
    }
}

実装例 - main.rs

impl eframe::App for SimpleApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        ctx.set_pixels_per_point(self.dpi);

        egui::CentralPanel::default().show(ctx, |ui| {
            ui.heading("Simple app");

            if ui.button("Reset").clicked() {
                self.reset();
            };

            if ui.button("Increment").clicked() {
                self.counter = self.counter + 1;
            };

            ui.text_edit_multiline(&mut self.input);
            
            ui.label(format!("Counter: {}", self.counter));
            ui.label(format!("Input: {}", self.input));

            ui.heading("Setting");
            ui.add(egui::Slider::new(&mut self.dpi, 0.5..=3.0).text("dpi"));
        });
    }
}

活用例を考える

  • 標準のUIを組み合わせてGUIを組み立てるという流れなので、そこまでデザインに凝ったUIは作れないそうです
    • eguiはリッチなUIはターゲットにしていない
    • 活用例を考えるうえでこの観点は重要そう
  • デバッグ用のツールが公式のユースケースとしてあげられています
    • 業務用のちょっとしたツールとかにちょうど良さそうかなと考えています
    • Rustでツールを書いてから、わざわざVue.jsやReactをセットアップして画面つくるか...とかはやる気がちょっと無いとなかなか腰が上がらないでしょうし...

まとめ

  • RustのGUIライブラリeguiの紹介
    • 数十行のコードで簡単にどの環境でも動くGUIアプリが完成!
    • 非常にシンプルな機能、デザインなので実装も簡単ですが、用途は選びそうです
  • 簡単なツールやcliツールを開発したあと、画面が欲しいなと思ったときの選択肢の一つとして
    • セットアップの簡単さは魅力だと考えています

Discussion