slint是一个类似qml的标记语言(xml/css之类方便界面设计的语言),经过编译器slint compile(类似QT的moc/uic/rcc工具)可完整的转换成Cpp或者Rust。
其开发方式类似qml+cpp,这得益于slint ui的两位初始创建人来自QT团队。
与qt的qml相比,slint有几个优点:
slint 优点
GPLv3 + 商业
1.1版本以后:
许可证变更:新增更宽松的免版税许可证
除了 GPLv3 和专有商业许可,此版本添加了新的免版税许可作为第三个选项,该许可证可免费用于构建桌面或 Web 应用程序,并消除了 Copyleft 许可证的限制。
所有示例、教程中的示例代码等现在都可以在宽松的 MIT 许可证下使用。这可以在应用程序中自由复制、修改和使用代码,而不受任何 Copyleft 条款的限制。
简化了 CLA 协议,所有贡献现在均在 MIT 无署名许可证下实现,没有版权限制。
https://github.com/slint-ui/slint/blob/release/1.3/LICENSES/LicenseRef-Slint-Royalty-free-1.1.md
思路很好,做UI感受很不错(IDE+预览)。
有种LVGL Pro的感觉,对于简单UI的程序,完全够用。对于复杂UI缺失内容太多。
支持多种前端和后端,支持很广泛,点赞。
支持嵌入式设备,点赞!(收费问题很坑)
值得入手学习一下,作为小工具语言。(替代flutter)
如果做商业,用在嵌入式领域rust+slint还可以。(如果不用rust,可以完全使用LVGL替代)
所以,以语言为导向,rust系,推荐。c++系,不推荐。
// Explicit positioning
export component Example inherits Window {
width: 200px;
height: 200px;
Rectangle {
x: 100px;
y: 70px;
width: parent.width - self.x; // 动态计算
height: parent.height - self.y;
background: blue;
Rectangle {
x: 10px;
y: 5px;
width: 50px;
height: 30px;
background: green;
}
}
// alignment 和 horizontal-stretch
HorizontalLayout {
alignment: start;
Rectangle { background: blue; min-width: 20px; }
Rectangle { background: yellow; min-width: 30px; }
Rectangle { background: navy; horizontal-stretch: 2;}
}
// border
Rectangle {
border-color: orange; border-width: 2px;
HorizontalLayout {
Rectangle { border-color: black; border-width: 2px; }
Rectangle { border-color: pink; border-width: 2px; }
}
}
// 支持for循环
HorizontalLayout {
spacing: 5px;
Rectangle { background: green; }
for t in [ "Hello", "World", "!" ] : Text {
text: t;
}
Rectangle { background: blue; }
}
// grid
GridLayout {
spacing: 0px;
Rectangle { background: red; }
Rectangle { background: blue; }
Rectangle { background: yellow; row: 1; }
Rectangle { background: green; }
Rectangle { background: black; col: 2; row: 0; }
}
}
常规属性:
component BoxWithLabel inherits GridLayout {
Row {
Text { text: "label text here"; }
}
Row {
@children
}
}
export component MyApp inherits Window {
preferred-height: 100px;
// 使用容器
BoxWithLabel {
Rectangle { background: blue; }
Rectangle { background: yellow; }
}
}
import { Button } from "std-widgets.slint";
import "./NotoSans-Regular.ttf"; // 引用字体
component LabeledInput inherits GridLayout {
forward-focus: input;
Row {
Text {
text: @tr("Input Label:"); // @tr() 用来做多国语言
font-family: "xxx";
font-size: 20px;
font-weight: bold;
}
input := TextInput {}
}
}
export component App inherits Window {
default-font-family: "Noto Sans"; // 默认字体
GridLayout {
Button {
text: "press me";
clicked => { label.focus(); } // 组件的事件
}
// 为组件起名
label := LabeledInput {
}
}
}
1. comments
// 或者 /* .. */
2. 命名
a-zA-Z 0-9 _ -
注意: _会被统一改为-,所以 foo_bar 等价于 foo-bar
3. 数据类型
参考 https://slint.dev/releases/1.3.0/docs/slint/src/language/syntax/types
angle:0deg/1.2rad/0.25turn
bool: true/false
brush: Colors.red... // 通常是color或者渐变色linear-gradient/radial-gradient
color: #RRGGBBAA / #RGB / transparent
duration: 1ms/2s // the duration of animations
easing: linear/ease/... // animation allow specifying an easing curve
float: 0.21/42%
image: @image-url("...") // image reference
int: 10/222/..
length: 1px / 1pt / 1in / 1mm / 1cm // used for x, y, width and height coordinates
percent: 0% // 32-bit floating point number that is interpreted as percentage
physical-length: 1phx // an amount of physical pixels
relative-font-size: 0rem // font size factor that is multiplied with the Window
string: "abc" // UTF-8 encoded, 支持 \n \u{x} \\ \{ex} 转义符
4. 数据结构
// 结构体
export struct Player {
name: string,
score: int,
}
anonymous structures using
{ identifier1: type2, identifier1: type2 }
// 枚举
export enum CardSuit { clubs, diamonds, hearts, spade }
// 数组
[int] l1 : [1,12,35];
l1.length
l1[index]
5. 类型转换
int,float可以直接转string
physical-length,length 可以直接转
struct直接如果有相同属性名可以直接转
array不能直接互相转
string转float: "3.14".to-float()/is-float()
6. Properties
每个element都有built-in的属性,比如width、color等。
属性的值可以是值,也可以是表达式`{42px}`,支持各种运算符.
//自定义属性
export component Example {
// declare a property of type int with the name `my-property`
property my-property;
// declare a property with a default value
property my-second-property: 42;
// This is meant to be set by the user of the component.
in property text;
// This property is meant to be read by the user of the component.
out property pressed;
// This property is meant to both be changed by the user and the component itself.
in-out property checked;
// This property is internal to this component.
private property has-mouse;
}
// 默认的property是private, 只在component内部使用
// in 表示input, 可以被外部user修改/binding, assignment by callback。 内部理论上也可以。
// out 表示output, 可以被component内部修改,但是外部user只有read-only.
// in-out both
7. Binding
// 普通绑定
import { Button } from "std-widgets.slint";
export component Example inherits Window {
preferred-width: 50px;
preferred-height: 50px;
Button {
property counter: 3;
clicked => { self.counter += 3 }
text: self.counter * 2; // 根据counter动态计算 binding
}
}
// 双向绑定
export component Example {
in property rect-color <=> r.background;
// It's allowed to omit the type to have it automatically inferred
in property rect-color2 <=> r.background;
r:= Rectangle {
width: parent.width * 50%; // 单向 Relative Lengths
height: parent.height * 50%; // 单向 Relative Lengths
background: blue; // 双向同步
}
}
8. Function
// function 关键字定义函数,默认 private
export component Example {
in-out property min;
in-out property max;
protected function set-bounds(min: int, max: int) {
root.min = min;
root.max = max
}
public pure function inbound(x: int) -> int {
return Math.min(root.max, Math.max(root.min, x));
}
}
9. Callback
communicate changes of state to the outside
export component Example inherits Rectangle {
// declare a callback
callback hello(int, string);
callback clicked <=> area.clicked; // 双向绑定两个 callback
hello(aa, bb) => { aa + bb } // callback的实现,可以在其他地方通过 => 绑定一个callback
area := TouchArea {
// sets a handler with `=>`
clicked => {
// emit the callback
root.hello(1, "abc")
}
}
}
10. Repetition and condition
// 通过for循环创建重复component
export component Example inherits Window {
preferred-width: 300px;
preferred-height: 100px;
for my-color[index] in [ #e11, #1a2, #23d ]: Rectangle {
height: 100px;
width: 60px;
x: self.width * index;
background: my-color;
}
}
// if 条件执行不同渲染
export component Example inherits Window {
preferred-width: 50px;
preferred-height: 50px;
if area.pressed : foo := Rectangle { background: blue; }
if !area.pressed : Rectangle { background: red; }
area := TouchArea {}
}
11. Animation
// 属性动画,具体效果参考 https://slint.dev/releases/1.3.0/docs/slint/src/language/syntax/animations
export component Example inherits Window {
preferred-width: 100px;
preferred-height: 100px;
background: area.pressed ? blue : red;
animate background {
duration: 250ms;
}
area := TouchArea {}
}
12. States
13. Global Singletons
14. Modules
// button.slint
component Button inherits Rectangle {
// ...
}
export { Button as ColorButton } // option1
export { Button } // Option2
// main.slint
import { Button } from "./button.slint";
import { Button as CoolButton } from "../other_theme/button.slint";
export component App inherits Rectangle {
// ...
Button {
// ...
}
}
// 相对路径引入
import { MySwitch } from "@mylibrary";
component MyButton inherits Rectangle {
in-out property text: "Initial";
init => {
// If `text` is queried here, it will have the value "Hello".
debug("first");
}
}
component MyCheckBox inherits Rectangle {
init => { debug("second"); }
}
export component MyWindow inherits Window {
MyButton {
text: "Hello";
init => { debug("third"); }
}
MyCheckBox {
}
}
// print “first”, then “second”, and then “third”
Layout
Miscellaneous
Drop Shadows(support Rectangle)
Accessibility
Image
Path(SVG or slint)
custom the Path in slint:
// more command: https://slint.dev/releases/1.3.0/docs/slint/src/language/builtins/elements#path-using-svg-path-elements
export component Example inherits Path {
width: 100px;
height: 100px;
stroke: blue;
stroke-width: 1px;
MoveTo {
x: 0;
y: 0;
}
LineTo {
x: 0;
y: 100;
}
ArcTo {
radius-x: 1;
radius-y: 1;
x: 100;
y: 100;
}
LineTo {
x: 100;
y: 0;
}
Close {
}
}
PopupWindow
Rectangle
TextInput
Text
TouchArea
Window
functions/global
The widget style is determined at your project’s compile time.
If no style is selected, native is the default.
Slint可以选择多种渲染后端,各有利弊。
https://slint.dev/releases/1.3.0/docs/slint/src/advanced/backends_and_renderers
Qt Renderer
Software Renderer
FemtoVG Renderer
Skia Renderer