Slint框架开发原生桌面应用,响应式UI,Rust语言实现
更新日期:
Slint是一个声明式UI框架,用于构建多个平台上的原生GUI界面的应用,支持windows/macos/linux以及嵌入式linux与mcu微控制器,支持编译为wasm,当前已经发布版本为1.4。它使用一种DSL语言.slint
来描述界面,类似于Qt中的QML,响应式,可以编译时转换为代码或者在运行时进行解析,支持Vscode插件实时预览界面显示;而业务逻辑也支持多编程语言,比如c++/javascript/rust等,这里主要探索使用rust来开发。
参考:
slint支持的平台,截图自slint github页面:
slint架构, 截图自slint github页面。左侧.slint
描述语言文件经过slint编译器编译为native原生语言代码,在slint runtime运行时的基础上运行;右侧C++/Rust/Javascript
语言实现的业务与slint runtime进行交互; slint使用GPU/软件实现的渲染器将UI代码渲染显示出来, 接收处理输入事件。
初始化slint的helloworld项目
已经安装完rust工作链,就可以直接使用cargo
命令新建项目,添加slint
信赖。也可以使用cargo generate
从模板创建项目。
1 | cargo new slint-hello |
然后编辑rust项目文件,将如下内容粘贴到src/main.rs
中来替换默认生成的代码:
1 | fn main() { |
然后使用cargo run
命令来编译运行程序,将会弹出一个小窗口, 显示绿色文字的hello world
。
前面rust代码中slint::slint!
宏后面的内容即是slint中声明界面的DSL语言,使用component
关键字声明组件MainWindow
, 使用inherits
声明继承于slint内置的Window
组件; MainWindow
内部声明了子组件Text
,text
与color
是组件Text
的属性。
然后在main()
方法中内容,先使用new()创建组件MainWindow
,接着调用run()
方法进行执行。slint::slint!
宏会将声明的界面信息转换rust代码,所以在main()中可以直接引用到MainWindow
类型。
安装VsCode插件
开发代码离不开编辑器/IDE的支持。 slint官方提供了VS Code插件,支持.slint
描述语言的语法高亮及显示实时预览。VS Code插件可以直接从左侧栏的扩展中直接安装,建议安装。
安装完插件后, slint::slint!
后的代码已经有语法高亮,并且上面多出Show Preview
的按钮,点击后弹出预览窗口。预览功能是通过命令行工具slint-viewer
实现,可以选择显示风格。
.slint语法
Slint文档上有.slint
文件格式的参考,且提供网页版工具SlintPad来编辑、预览。 Slint描述文件在rust中有三种使用方式, 1-使用宏slint::slint!
直接写在rust代码中,2-保存在文件中以.slint
结尾,3-在程序运行时从文件系统中动态加载,需要使用解释器API。
一个.slint
文件中可以声明一个或者多个组件,每个组件包含属性及子组件树,如同Javascript框架ReactJS中声明组件树。如下列出了.slint
描述文件的一些重点:
component
声明组件,inherits
继承,export
导出组件在外部可用,import
导入组件;使用:=
给子组件命名,命名需满足标识符规则,非首字母可以使用短横线-
, 生成代码时会转换为下划线_
;组件内部可以使用预定义的名字,root最外层组件, self当前元素,parent父组件元素- 组件内可以给属性赋值, 使用
:
冒号分隔; 组件内声明属性使用property
, 默认是只有内部可以访问,可以使用private
(默认),in
,out
,in-out
进行修饰; 如in-out property <bool> checked;
- 属性值中可以使用表达式进行计算,响应式方式实现, 如果依赖的值发生变化,属性值会重新计算然后刷新显示内容。
- 使用
callback
声明回调函数, 使用=>
来设置回调函数的值如clicked => {root.hello()}
;<=>
来绑定回调与元素的事件调用callback clicked <=> area.clicked
- 使用
function
声明函数,函数无负作用时可使用pure
来修饰 - Slint提供了一些内置组件,如
Window/Rectangle/HorizontalLayout/HorizontalLayout
,可以直接使用; 提供的标准控件Widgets如Button
等可以从std-widgets.slint
中引入,import { Button, VerticalBox } from "std-widgets.slint";
- Slint提供了类似于CSS中的属性,元素位置使用
x
,y
,width
,height
等, 背景色background: #3960D5;
, 图片使用组件Image
, 图片路径使用source: @image-url("icons/bus.png");
;animate
声明属性值的转换动画 - 使用c/c++风格的注释,
//
单行注释,/**/
多行注释且可以嵌套 - 支持
for-in
循环,if
判断,..?..:..
三元表达式
参考:
- Slint Reference https://slint.dev/releases/1.4.1/docs/slint/
- SlintPad https://slint.dev/editor
- Slint Rust doc https://slint.dev/releases/1.4.1/docs/rust/slint/
开发一个简单的应用
开发一个简单的应用,演示下property与callback使用,界面上先显示一行文本,然后三个按钮,分别是重置、加1、加2。加1是在.slint
中实现,而加2使用rust实现。
主组件MainWindow
中定义属性count用于计数,回调callback inc-count-2(int) -> int
用于在rust中计算新的count值,使用win.on_inc_count_2()
来设置回调方法的逻辑,注意方法名的差异,以on开始,.slint
中的短横换成了下划线。
在button的clicked回调中使用root.count
引用属性。
1 | fn main() { |
显示效果如下