使用 Rust 代码运行时刷新 Slint UI 内的组件属性
过程
首先, 我们通过全局单例 global singleton 定义一些用于列表刷新的属性:
export global TestShared { callback update-list-items([ListItem]); in-out property <[ListItem]> test-list-items: [ { text: "AboutSlint", label: "aboutslint"}, { text: "Button", label: "button"}, { text: "CheckBox", label: "checkbox"}, { text: "ComboBox", label: "combobox"}, { text: "GridBox", label: "gridbox"}, { text: "GroupBox", label: "groupbox"}, { text: "HorizontalBox", label: "horizontalbox"}, { text: "LineEdit", label: "lineedit"}, { text: "ListView", label: "listview"}, { text: "ProgressIndicator", label: "progressindicator"}, { text: "ScrollView", label: "scrollview"}, { text: "Slider", label: "slider"}, { text: "SpinBox", label: "spinbox"}, { text: "Spinner", label: "spinner"}, { text: "StandardButton", label: "standardbutton"}, { text: "StandardListView", label: "standardlistview"}, { text: "StandardTableView", label: "standardtableview"}, { text: "Switch", label: "switch"}, { text: "TabWidget", label: "tabwidget"}, { text: "TextEdit", label: "textedit"}, { text: "VerticalBox", label: "verticalbox"}, ]; update-list-items(items) => { test-list-items = items; } }
说明
update-list-items
是一个全局回调, 我们在后面通过给它提供默认实现, 表明这是一个可以在外部调用的回调. 其目的是允许我们在 Rust 的 native code 中调用invoke_update_list_items
这个自动生成的回调来传入新的items
, 并间接更新全局单例TestShared
的test-list-items
属性.
此时, 我们运行程序会看到这样的样式 (具体布局实现不是本文重点, 略去不表):
此时回到 Rust native code 部分, 稍作更改:
let items: Rc<VecModel<ListItem>> = Rc::new(VecModel::from(vec![ListItem { text: "HHH".into(), label: "hhh".into(), }])); app.global::<TestShared>() .invoke_update_list_items(ModelRc::from(items.clone()));
说明
这里使用了std::rc::Rc
, 是因为目的就是在主线程中直接更新. 如果要跨线程则需要用允许在多线程中 move 的相应 wrapper 容器. 另外, Slint 中不能直接传递字符串和数组, 所以我们要将字符串 (String
或字符串切片&str
) 转变为SharedString
类型, 并使用VecModel
作为数组的封装构成一个对属性值数组的引用. 最后再通过ModelRc
封装成 Slint 能够识别的结构体数组ModelRc<ListItem>
.此外, 在 Rust 中需要使用
app.global::<TestShared>().invoke_update_list_items
的方式来触发回调函数. 其中的TestShared
就是早前定义的全局单例,invoke_xxx
是 Slint 生成 Rust 代码时映射的结构体方法, 所有的-
都被替换成了_
.
这个时候再次运行, 可以发现程序中的列表已经被替换了:
启发
这个简单的例子只是在进行属性的更新, 但是往远处想, 我们可以通过这种机制实现将 Slint UI 中难以实现的复杂逻辑 (比如状态切换, 导航, 路由) 等统统抽象成全局实例的接口. 一方面 Slint UI 中只需要进行回调函数的映射和绑定, 另一方面 Rust 可以异步进行运算和处理. 这样一来, 很多场景的代码都可以得到优化解决了. 笔者目前进行了路由的改进尝试, 效果还不错, 或许哪天有空了可以摘要记录一下.
References
- Slint Rust documentation slint::ModelRc
- Slint UI documentation Callbacks
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!