其他 GUI 框架
核心 crate 裡並沒有 gpui。要接上任何框架,都只需回答一個問題:我該怎麼把一個閉包投遞到主執行緒? 把這件事註冊一次,本指南其餘內容便原封不動地適用。
rust
// Cx is whatever your toolkit hands out on the main thread; it need not be Send.
let (bridge, app) = GuiBridge::builder(move |task: Box<dyn FnOnce(&mut MyCx) + Send>| {
my_toolkit::post_to_main_thread(move || {
let cx = /* obtain &mut MyCx here */;
task(cx);
});
})
.build();| 框架 | 投遞方式 |
|---|---|
| gpui | channel + 一個呼叫 cx.update 的 cx.spawn 排空迴圈——已封裝為 purview-gpui |
| Slint | slint::invoke_from_event_loop;在閉包內透過 weak handle 觸達元件 |
| GTK | glib::idle_add |
| egui | 入佇列,於重繪時排空 |
Send 的巧妙之處
Cx 只被承載在投遞閉包的裝箱型別內部,因此即使 Cx 本身不是 Send,GuiBridge<Cx> 以及所有控制代碼依然是 Send + Sync。正是這一點讓伺服器能跑在背景執行緒上,而你的上下文從不離開主執行緒。
自己回到主執行緒
在 on_ui 處理器之外——例如在 async 處理器裡,或任何背景任務中——明確地跳回主執行緒:
rust
let ui = app.ui(); // Ui<Cx>, cheap to clone, Send + Sync
let value = ui.run(|cx| read_widget(cx)).await;Ui::run 會投遞你的閉包並等待它的回傳值。如果主迴圈已經結束,它會 panic——這是誠實的結果:已經沒有上下文可供執行了。