LoginSignup
22
12

More than 3 years have passed since last update.

RustでGUI 〜iced編〜

Posted at

プログラム全体はgithubのogata-k/GUI_cmp/example_icedをご覧ください。

iced

今回使用するバージョンは0.1.0-betaです。

どんなクレートか

icedはバージョンにbetaとあるようにまだまだ開発中のGUIライブラリです。READMEによるとElmにインスパイアされて作られたクロスプラットフォーム向けのライブラリです。Elmを参考にしているだけあってコードの見た目もElmに見えます。
珍しいことにWebアプリもサポートしてるとのことです。さらに各種基本的なレンダーライブラリの対応や非同期も対応しています。

コード

main.rs
use iced::{Sandbox, Element, Button, Column, Text, Settings, Container, Length, Align, HorizontalAlignment, Color, Background, button};
use iced::settings::Window;

pub fn main() {
    Counter::run(Settings {
        window: Window {
            size: (300, 300), // (x, y)
            resizable: false,
        }
    })
}

// state
struct Counter {
    // counter value
    value: i32,

    // state of the two buttons
    increment_button: button::State,
    reset_button: button::State,
}

// message
#[derive(Debug, Clone, Copy)]
pub enum Message {
    Increment,
    Reset,
}

impl Sandbox for Counter {
    type Message = Message;

    fn new() -> Self {
        Counter {
            value: 0,
            increment_button: button::State::default(),
            reset_button: button::State::default(),
        }
    }

    fn title(&self) -> String {
        String::from("count up")
    }

    // update
    fn update(&mut self, message: Message) {
        match message {
            Message::Increment => {
                self.value += 1;
            }
            Message::Reset => {
                self.value = 0;
            }
        }
    }

    // view logic
    fn view(&mut self) -> Element<Message> {
        Container::new(
            Column::new()
                .push(
                    Button::new(&mut self.increment_button, Text::new("+1"))
                        .on_press(Message::Increment)
                        .border_radius(5)
                        .background(Background::Color(Color{r: 0.8, g: 0.8, b: 0.8, a: 1.})),
                )
                .push(
                    Text::new(self.value.to_string()).size(50).horizontal_alignment(HorizontalAlignment::Center),
                )
                .push(
                    Button::new(&mut self.reset_button, Text::new("reset"))
                        .on_press(Message::Reset),
                )
                .align_items(Align::Center)
        )
            .width(Length::Fill)
            .center_x()
            .height(Length::Fill)
            .center_y()
            .into()
    }
}

iced.png

コードの説明

main関数ではGUIのおおもととなるWindowの設定を元にアプリを起動するところだけを請け負います。
次に状態のモデルとなるCounterモデルです。今回はカウント値、カウントアップボタン、リセットボタンの状態を表現しています。
次に状態の変更を通知するときに通知するイベントメッセージのMessage列挙体です。今回は増加とリセットを表現しています。
そしてSandboxトレイトを実装することで描画と更新処理を実装します。Applicationというトレイトもあるのですが、こちらは非同期を扱うときのトレイトとなります。描画はview関数で定義します。少しレイアウトの定義関数に癖がある気がしますが、よくある記述で書くことができます。
更新処理のupdate関数は状態モデルを更新する処理だけを行います。

所感

まだまだ実用には向かず未成熟な感じが強いですが、触ってみた限り完全にElmですね。モデルやメッセージが肥大化しそうな予感はありますが、慣れるとElmアーキテクチャの方がGUIは表記しやすいかもしれませんね。

まとめ

まだまだ未成熟なライブラリですが、実用的になればRustでGUIと言ったらこれ!といえるGUIライブラリの一つになりそうな予感がします。

22
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
12