Setory vol3 Rust Iced でGUIアプリを作った

578 Views

December 06, 25

スライド概要

profile-image

主に参加したLTの資料を上げます。

Docswellを使いましょう

(ダウンロード不可)

関連スライド

各ページのテキスト
1.

Rust Iced でGUIアプリを作った 岡山大学電子計算機研究会 : 瀕死 @hinshiba 2025-12-06

2.

自己紹介 2 ◼ ID: hinshiba ◼ Name: 柴田 晴 ◼ 岡山大学 電子計算機研究会 副部長 ◼ B2 旧Twitter & GitHub @hinshiba https://hinshiba.net/

3.

活動 3

4.

活動 4

5.

活動 5

6.

活動 6

7.

活動 7 TUI 画像整理 ハッカソン Unityでレースゲーム numpyだけの 左手デバイス ニューラルネットワーク 電子ペーパー + サーボモーターの制御 NO IMG Discord bot セキュリティ・キャンプ コネクト2025 NO Cの標準ライブラリのみで独自言語 IMG 笠岡市との共同プロジェクト? 冬コミ C107での出店予定

8.

GUI書いたことないじゃん 8 GUI書いたことないじゃん numpyだけの 左手デバイス TUI 画像整理 ハッカソン Unityでレースゲーム ニューラルネットワーク 電子ペーパー + サーボモーターの制御 NO IMG Discord bot セキュリティ・キャンプ コネクト2025 NO Cの標準ライブラリのみで独自言語 IMG 笠岡市との共同プロジェクト? 冬コミ C107での出店予定

9.

Outline ◼ 制作物 ◼ Rustでライブラリ ◼ IcedによるGUI ◼ おわり 9

10.

Outline ◼ 制作物 ◼ Rustでライブラリ ◼ IcedによるGUI ◼ おわり 10

11.

製作物 11 ◼画像のタグ付け ◼バッチ処理 ◼操作記録機能

12.

製作物 12 画像表示部

13.

製作物 13 タグ表示部

14.

製作物 14 画像操作 タグ操作

15.

Outline ◼ 制作物 ◼ Rustでライブラリ ◼ IcedによるGUI ◼ おわり 15

16.

設計 16 GUI CLI lib CLIをまず作ると考える

17.

設計 17 GUI CLI lib CLIをまず作ると考える 共通部分をライブラリに

18.

ワークスペースの利用 18 root ├─ tagup_lib │ └ src ├─ tagproc_cli │ └ src └─ tagedit_gui └ src 複数パッケージに分割

19.

ライブラリの全体像 19

20.

Tag型 20 Tag 型 単一のタグを示す #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct Tag(String); newtypeパターン

21.

Tags型 21 Tags 型 タグの列を示す #[derive(…略)] pub struct Tags(Vec<Tag>); ここでも新しい型

22.

トレイトの活用 新しい型 ◼コンストラクタが必要 ◼メソッドの不足 22

23.

トレイトの活用 新しい型 ◼コンストラクタが必要 From系トレイト ◼メソッドの不足 Derefトレイト AsRefトレイト 23

24.
[beta]
From系トレイト
型変換を行う
impl From<Vec<Tag>> for Tags { // 略 }

Tags::from(vec![tag])

みたいなことが
できるようになる

24
種類
◼From<T>
◼FromStr
◼&strから変換
◼str::parse()
◼TryFrom<T>
◼失敗する可能性
◼Self::try_from()
◼Result<Self, Err>

25.
[beta]
Derefトレイト

25

自動で型変換
impl Deref for Tags {
type Target = Vec<Tag>;
// 略 }

let v: &Vec<Tag> = &*&tags;

& 演算子が &Tags

に

tags.iter()

* 演算子が Vec<Tag> に
みたいなことが
できるようになる

& 演算子が &Vec<Tag> に

26.

AsRefトレイト 参照を作成する impl AsRef<str> for Tag { // 略 } tag.as_ref().trim() みたいなことが できるようになる 26 種類 ◼AsRef<T> ◼&Tを返す ◼AsMut<T> ◼&mut Tを返す

27.

型変換マップ 型の恩恵 可読性向上 型検査 27

28.
[beta]
イテレータチェーン
let changes: TagsChanges = tags
.into_iter()
.map(TagChanges::new)
.replace(&replace_dict)
.delete(&delete_set)
.prepend(prepend_tags.into())
.append(append_tags.into())
.unique()
.absorb()
.collect();

28

◼イテレータを繋げる
◼型が違うので大変
map() -> Map<Self, F>
chain() -> Chain<Self, U::IntoIter>
etc

◼カッコイイ

29.

テスト 29

30.

テスト 30

31.

Outline ◼ 制作物 ◼ Rustでライブラリ ◼ IcedによるGUI ◼ おわり 31

32.

Icedの思想 32 ◼Elmアーキテクチャに着想 ◼関数型プログラミング言語 ◼JavaScriptにトランスパイル ◼Simple (easyでない) https://book.iced.rs/architecture.html

33.

Elmアーキテクチャの利用 分割を強制 https://book.iced.rs/architecture.html ◼State ◼表示する状態 ◼Update ◼状態をどう変化させるか ◼View (dictates) ◼状態をどう表示するか 33

34.
[beta]
Stateの作成
struct TagEdit {
image_paths: Vec<PathBuf>,
current_image: image::Handle,
current_image_idx: usize,

// ......
}

◼表示すべき画像一覧
◼今の画像のハンドラ
◼今の画像の番号

34

35.
[beta]
Viewの作成
impl TagEdit {
pub fn view(&self) -> Element<'_, Message> {
widget::column![
image(self.current_image.clone()),
button("next")
]
.into()
}

◼StateからWidgetsを作成
◼image
◼button

35

36.
[beta]
エントリポイント
fn main() -> anyhow::Result<()> {
iced::application(“tagedit gui”,
TagEdit::update,
TagEdit::view
).run_with(TagEdit::init)?;
Ok(())
}

◼iced::application()に渡すだけ
◼.run_with()で初期状態を渡す
◼update()は空でもよい

36

37.

実行例 37

38.

Messageの作成 #[derive(Debug, Clone)] pub enum ImageUpdateMessage { Next, Prev, } ◼ただのenum型 38 button("next").on_press(ImageUpdateMessage::Next) ◼button()に追加

39.
[beta]
Updateの作成
impl TagEdit {
fn update_image(&mut self, msg: ImageUpdateMessage) {
match msg {
ImageUpdateMessage::Next => self.current_image_idx += 1,
};
self.current_image =
image::Handle::from_path(self.image_paths[self.current_image_idx].clone());
}
}

◼current_image_idxをインクリメント
◼画像を再読み込み

39

40.

実践 40

41.

Outline ◼ 制作物 ◼ Rustでライブラリ ◼ IcedによるGUI ◼ おわり 41

42.

Rust Iced でGUIアプリを作った 岡山大学電子計算機研究会 : 瀕死 @hinshiba 2025-12-06 ご清聴ありがとうございました