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——这是诚实的结果:已经没有上下文可供运行了。