Skip to content

其他 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();
框架投遞方式
gpuichannel + 一個呼叫 cx.updatecx.spawn 排空迴圈——已封裝為 purview-gpui
Slintslint::invoke_from_event_loop;在閉包內透過 weak handle 觸達元件
GTKglib::idle_add
egui入佇列,於重繪時排空

Send 的巧妙之處

Cx 只被承載在投遞閉包的裝箱型別內部,因此即使 Cx 本身不是 SendGuiBridge<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——這是誠實的結果:已經沒有上下文可供執行了。