Slint作为静态类型的UI开发语言,藏着一套简洁却强大的核心体系 —— 从灵活的数据类型到直观的视觉属性,从绚丽的颜色渐变到精准的计时器控制,掌握这些就能快速搭建出交互流畅、视觉精美的 UI。我将利用本文带你沉浸式吃透 Slint 的核心能力!

一、数据类型

Slint的类型系统既严谨又灵活,基本类型覆盖日常开发需求,复杂类型则专为 UI 场景优化,上手无压力。

1. 字符串(string):不止是文本,更是交互载体

字符串是UI中最常用的类型,支持直接赋值、特殊字符插入,还有丰富的属性和方法,适配各种文本场景。

基础用法:直接赋值

slint

export component Example inherits Text {
    text: "hello"; // 简单字符串赋值,支持UTF-8编码
}
转义序列:插入特殊字符

遇到双引号、换行等难以直接输入的字符,用转义序列就能轻松解决:

转义序列 结果 实用场景
" "(双引号) 在字符串中包含引号,如"He said \"Hello\""
\ \(反斜杠) 插入文件路径或特殊符号,如"C:\\Users\\name"
\n 换行 实现多行文本,如"Line1\nLine2"
\u{x} x 为十六进制数,对应 Unicode 码点 插入特殊符号、emoji 或稀有字符,如"\u{1F60A}"(😊)
{expression} 表达式计算结果 动态拼接文本,如"Count: \{count}"

注意:未转义的\后接其他字符会报错;Rust 的 slint! 宏中不支持\{...}语法。

核心属性:快速判断字符串状态
  • is-empty:判断字符串是否为空,返回 bool 值,常用于表单校验。

    slint

    export component LengthOfString {
        property<bool> empty: "".is-empty; // true(空字符串)
        property<bool> not-empty: "hello".is-empty; // false(非空字符串)
    }
    
  • character-count:统计 “用户感知到的字符数”(即 grapheme clusters),而非 Unicode 码点数量,完美适配多语言和 emoji。

    slint

    export component CharacterCountOfString {
        property<int> empty: "".character-count; // 0(空字符串)
        property<int> hello: "hello".character-count; // 5(普通英文)
        property<int> hiragana: "あいうえお".character-count; // 5(日语平假名)
        property<int> surrogate-pair: "😊𩸽".character-count; // 2(emoji和特殊字符)
        property<int> zero-width-joiner: "👨‍👩‍👧‍👦".character-count; // 1(家庭emoji,虽多码点但算1个字符)
    }
    
实用方法:文本格式自由切换
  • to-lowercase()/to-uppercase():按 Unicode 规则转换大小写,支持多语言,不会出现格式错乱。

    slint

    export component ChangeCaseOfString {
        property<string> hello: "HELLO".to-lowercase(); // "hello"(英文小写)
        property<string> bye: "tschüß".to-uppercase(); // "TSCHÜSS"(德语大写)
        property<string> odysseus: "ὈΔΥΣΣΕΎΣ".to-lowercase(); // "ὀδυσσεύς"(希腊语小写)
        property<string> new_year: "农历新年".to-uppercase(); // "农历新年"(中文无大小写,保持原样)
    }
    

2. 数值类型:精准控制 UI 尺寸与逻辑

Slint 的数值类型专为 UI 场景设计,不仅有基础的整数、浮点数,还有角度、时长、长度等带单位的类型,避免计算错误。

类型 用途 示例
int 整数逻辑(计数、索引等) property<int> count: 5
float 浮点计算(比例、透明度等) property<float> scale: 1.5
angle 角度控制(旋转、渐变方向) 90deg(直角)、1.2rad(弧度)
duration 时长控制(动画、计时器) 1s(1 秒)、250ms(250 毫秒)
length 尺寸与坐标(宽、高、位置) 100px(像素)、1in(英寸)、1cm(厘米)
percent 百分比数值(占比、进度) 50%(占比一半)

提示:不同编程语言中这些类型的 API 映射不同,需参考对应语言的官方文档。

3. 图像(image):让 UI 更具视觉张力

图像类型支持本地文件、网络资源加载,还能实现缩放、尺寸获取等功能,是 UI 视觉设计的核心。

基础用法:加载图像

通过@image-url("...")加载图像,地址支持绝对路径、相对路径(相对于当前.slint 文件),仅 SlintPad 支持 http 网络地址。

slint

export component Example inherits Window {
    preferred-width: 150px;
    preferred-height: 50px;

    // 加载网络图像(仅网页版本有效)
    in property <image> some_image: @image-url("https://slint.dev/logo/slint-logo-full-light.svg");

    HorizontalLayout {
        // 显示图像尺寸:通过width/height属性获取
        Text { text: "The image is " + some_image.width + "x" + some_image.height; }

        // 判空逻辑:尺寸大于0说明图像加载成功
        if some_image.width > 0 : Image { source: some_image; }
    }
}
支持格式:覆盖主流场景

本地图像支持 SVG、AVIF、BMP、GIF、JPEG、PNG 等多种格式(完整列表参考 image crate)。Rust 应用默认未启用所有格式,需通过 Cargo 的image-default-formats特性开启。

高级功能:9 切片缩放(九宫格)

对于边框、气泡等需要拉伸的图像,用nine-slice(...)参数指定边缘大小,拉伸时边缘不变形,完美适配各种尺寸。

slint

// 9切片缩放:边缘30px不变形,中间拉伸
export component Example inherits Window {
    width: 100px;
    height: 150px;
    VerticalLayout {
        Image {
            source: @image-url("https://interactive-examples.mdn.mozilla.net/media/examples/border-diamonds.png", nine-slice(30 30 30 30));
        }
    }
}

参数说明:nine-slice支持 1 个(所有边缘相同)、2 个(垂直 水平)、4 个(上 右 下 左)数值,按需灵活设置。

4. 动画(easing):让交互更丝滑

动画缓动曲线控制元素运动节奏,Slint 内置多种常用曲线,还支持自定义,让 UI 交互告别僵硬。

核心特性:缓动曲线类型

默认值为linear(线性),可通过Easing命名空间调用预设曲线,也可直接使用曲线名称(在 easing 表达式中)。

常用预设曲线(可视化参考easings.net):

  • 基础曲线:linear(线性)、ease(默认缓动)、ease-in(先慢后快)、ease-out(先快后慢)
  • 二次曲线:ease-in-quad、ease-out-quad(更明显的加速 / 减速)
  • 弹性曲线:ease-in-elastic、ease-out-elastic(带回弹效果)
  • 弹跳曲线:ease-in-bounce、ease-out-bounce(模拟弹跳)
  • 自定义曲线:cubic-bezier(a, b, c, d)(同 CSS,自由调节节奏)
用法示例:给元素添加入场动画

slint

// 定义动画数据结构体,用于存储动画相关的配置信息
struct AnimationData {
    // 动画曲线属性,类型为easing(缓动函数类型)
    curve: easing,
}

// 定义自定义组件Custom,继承自Rectangle组件(矩形组件)
component Custom inherits Rectangle {
    // 定义一个AnimationData类型的属性animation,用于配置动画相关数据
    property<AnimationData> animation: {
        // 此处使用Easing命名空间下的ease-in-circ缓动曲线
        curve: Easing.ease-in-circ,
    };

    // 对当前组件的x属性进行动画配置
    animate x {
        // 在缓动表达式中,缓动函数名称(如ease-out-bounce)可通过全局作用域直接访问
        // 此处指定x属性动画使用ease-out-bounce缓动函数
        easing: ease-out-bounce;
    }
}

5. 类型转换:灵活适配不同场景

Slint 支持类型间安全转换,既保证严谨性,又兼顾开发便捷性,无需复杂代码即可实现类型适配。

核心转换规则(实用场景导向)
  1. 数值互转:int ↔ float(float 转 int 会截断小数),比如property<int> num: 45.8;(结果为 45)
  2. 数值转文本:int/float 可直接转 string,比如property<string> text: 123;(结果为 "123")
  3. 长度类型互转:length、physical-length、relative-font-size 在已知像素比的场景下可互转
  4. 带单位类型与数值:不能直接转,但可通过1px等单位实现,比如int * 1px(整数转长度)、length / 1phx(长度转浮点数)
  5. 字符串与数值:string 通过to-float()转 float(无效数字返回 0),用is-float()判断是否为有效数字
  6. 结构体互转:属性名相同、类型可转即可,支持缺失属性(用默认值)或额外属性(被忽略),但不能同时存在
实战示例:类型转换综合运用

slint

export component Example {
    // 结构体转换:缺失a用默认值,额外c被忽略
    property<{a: string, b: int}> prop1: {a: 12, b: 12 }; // a自动转string
    property<{a: string, b: int}> prop2: { b: 12 }; // a默认为""
    property<{a: string, b: int}> prop3: { a: "x", b: 12, c: 42 }; // c被忽略

    // 字符串与数值转换
    property<string> xxx: "42.1";
    property<float> xxx1: xxx.to-float(); // 42.1(转float成功)
    property<bool> xxx2: xxx.is-float(); // true(是有效数字)
}

二、通用属性与回调

通用属性与回调是UI 交互的 “骨架”,是指所有 Slint 元素都共享一套通用属性和回调,掌握这些就能快速控制元素的位置、外观和行为,无需重复学习。

1. 通用视觉属性:控制元素 “看得见的部分”

这类属性仅适用于视觉元素(如 Rectangle、Text、布局),非视觉元素(如 Timer)不具备。

位置与尺寸:精准定位元素
  • x/y:相对于父元素的坐标,默认 0px,比如x: 50px; y: 30px;(元素在父容器内的位置)
  • width/height:元素宽高,默认 0px,设置后覆盖默认尺寸,比如width: 200px; height: 100px;
  • z:堆叠顺序,数值越大越靠上,需为编译时常量(目前运行时无法修改),比如z: 1.0;(在同级元素上方)
变换效果:让元素 “动起来”

支持旋转、缩放,默认围绕元素中心变换,软件渲染器不支持该功能。

slint

Image {
    x: 0;
    y: 0;
    source: @image-url("images/slint-logo.svg");
    transform-rotation: 45deg; // 旋转45度
    transform-origin: {x: 0, y: 0}; // 旋转原点设为左上角(默认是中心)
    transform-scale: 150%; // 放大1.5倍,也可通过transform-scale-x/transform-scale-y单独控制轴缩放
}
不透明度(opacity):打造层次感

取值 0-1(或百分比),0 完全透明,1 完全不透明,子元素会继承父元素的透明度,适合制作半透明面板、渐变叠加效果。

slint

// 定义一个图片信息展示组件ImageInfo,继承自Rectangle(矩形组件)
component ImageInfo inherits Rectangle {
    // 定义输入属性img-opacity,类型为float,默认值1.0,用于控制图片透明度
    in property <float> img-opacity: 1.0;
    // 设置组件背景为透明
    background: transparent;
    
    // 垂直布局容器,用于垂直排列图片和文本
    VerticalLayout {
        // 子元素之间的间距为5px
        spacing: 5px;
        
        // 图片组件,用于展示指定图片
        Image {
            // 图片源路径:elements目录下的slint-logo.png
            source: @image-url("elements/slint-logo.png");
            // 图片透明度绑定到img-opacity属性,随其值变化
            opacity: img-opacity;
        }
        
        // 文本组件,用于显示当前透明度值
        Text {
            // 文本内容:"opacity: "加上当前img-opacity的值
            text: "opacity: " + img-opacity;
            // 文本颜色为白色
            color: white;
            // 文本水平居中对齐
            horizontal-alignment: center;
        }
    }
}

// 定义导出的示例主组件Example,继承自Window(窗口组件),作为应用入口
export component Example inherits Window {
    // 窗口宽度设置为100px
    width: 100px;
    // 窗口高度设置为310px
    height: 310px;
    // 窗口背景设为透明
    background: transparent;
    
    // 背景矩形组件,用于装饰和衬托内容
    Rectangle {
        // 背景色为带透明度的深灰色(#141414df)
        background: #141414df;
        // 边框圆角半径为10px,使边角圆润
        border-radius: 10px;
    }
    
    // 垂直布局容器,用于垂直排列多个ImageInfo组件
    VerticalLayout {
        // 子组件之间的间距为15px
        spacing: 15px;
        // 顶部内边距为10px
        padding-top: 10px;
        // 底部内边距为10px
        padding-bottom: 10px;
        
        // 第一个ImageInfo实例,透明度设为1.0(完全不透明)
        ImageInfo {
            img-opacity: 1.0;
        }
        
        // 第二个ImageInfo实例,透明度设为0.6(半透明)
        ImageInfo {
            img-opacity: 0.6;
        }
        
        // 第三个ImageInfo实例,透明度设为0.3(更透明)
        ImageInfo {
            img-opacity: 0.3;
        }
    }
}
 Rectangle {
        opacity: 50%;
        Rectangle {
            x: 0;
            y: 0;
            width: 100px;
            height: 100px;
            background: blue;
        }

        Rectangle {
            x: 50px;
            y: 50px;
            width: 100px;
            height: 100px;
            background: green;
        }
    }
可见性(visible):控制元素 “显隐”
  • visible: true(默认):元素显示,响应鼠标输入
  • visible: false:元素隐藏,不响应输入,但仍占布局空间(适合临时隐藏,保留位置)
绝对位置(absolute-position):快速定位嵌套元素

只读属性,返回元素相对于所属 Window/PopupWindow 的绝对坐标,解决嵌套层级多、难以获取实际位置的问题。

2. 其他实用属性

  • cache-rendering-hint: true:提示渲染器缓存元素及其子元素,适合复杂且极少变化的 UI(如静态面板),可提升渲染速度,但会增加内存占用(仅为提示,并非所有渲染后端支持)。
  • dialog-button-role:指定 Dialog 中按钮的角色,自动适配平台按钮布局,取值包括 accept(确定)、reject(取消)、apply(应用)等。

3. 通用回调函数:响应元素 “生命周期与交互”

回调函数是元素行为的核心,最常用的是init()和各类交互回调。

init ():元素的 “初始化脚本”

所有元素都隐式拥有init()回调,在元素实例化、属性初始化完成后执行,执行顺序是 “从内到外”(子元素先执行,父元素后执行)。

slint

// 定义自定义按钮组件MyButton,继承自Rectangle(矩形组件)
component MyButton inherits Rectangle {
    // 定义双向绑定属性text,类型为字符串,默认值为"Initial"
    // in-out表示该属性可在组件内外双向传递值
    in-out property <string> text: "Initial";
    
    // 组件初始化时执行的代码块(init块)
    init => {
        // 注意:此处如果访问text属性,其值会是"Hello"
        // 因为在MyWindow中实例化MyButton时显式设置了text为"Hello",初始化时已生效
        debug("first"); // 输出调试信息"first"
    }
}

// 定义自定义复选框组件MyCheckBox,继承自Rectangle(矩形组件)
component MyCheckBox inherits Rectangle {
    // 组件初始化时执行的代码块
    init => { debug("second"); } // 输出调试信息"second"
}

// 定义导出的主窗口组件MyWindow,继承自Window(窗口组件),作为应用入口
export component MyWindow inherits Window {
    // 实例化MyButton组件
    MyButton {
        text: "Hello"; // 显式设置MyButton的text属性为"Hello"
        // 该MyButton实例自身的初始化代码块
        init => { debug("third"); } // 输出调试信息"third"
    }
    
    // 实例化MyCheckBox组件
    MyCheckBox {
        // 未额外设置属性,使用默认配置
    }
}

输出顺序:first → second → third

注意事项
  1. 不要用init()初始化属性,违反声明式原则;
  2. 无法从应用代码设置init()(生成的代码无on_init函数);
  3. 动态创建的元素(如if条件下的元素)可通过init()调用全局回调,静态元素(如窗口)不支持。

4. 无障碍属性与回调:让 UI 更包容

通过accessible-*属性,可让 UI 兼容屏幕阅读器、盲文终端等辅助工具,提升应用可访问性(必须先设置accessible-role才能使用其他属性)。

核心无障碍属性
属性 用途 示例
accessible-role 定义元素在辅助工具中的角色 accessible-role: button;(按钮角色)
accessible-label 交互元素的标签(辅助工具读取) accessible-label: "确认提交";
accessible-checked 标记是否勾选(复选框、开关) accessible-checked: true;
accessible-description 元素详细描述 accessible-description: "点击后提交表单数据";
无障碍回调
  • accessible-action-default():触发元素默认操作(如按钮点击);
  • accessible-action-increment()/accessible-action-decrement():响应数值增减操作(如滑块、数值框);
  • accessible-action-expand():响应展开操作(如组合框下拉)。

三、颜色与画笔

颜色与画笔可以给 UI “穿上漂亮外衣”,是 UI 视觉设计的灵魂,Slint 支持 CSS 风格颜色、渐变效果,还有灵活的颜色操作方法,让配色既简单又专业。

1. 基础颜色:3 种常用定义方式

颜色字面量遵循 CSS 语法,支持颜色名、十六进制、函数创建,灵活适配不同开发习惯。

slint

export component Example inherits Window {
    background: blue; // 1. CSS颜色名(直接使用,仅在color/brush表达式中有效)
    property<color> c1: #ffaaff; // 2. 十六进制(#RRGGBB 或 #RRGGBBAA)
    property<brush> b2: Colors.red; // 3. Colors命名空间(所有场景通用,完整颜色名参考CSS规范)
}
颜色属性:精细控制色值

颜色暴露redgreenbluealpha四个属性,取值 0-255,可直接修改实现动态配色:

slint

property<color> my-color: #ff0000;
my-color.red = 200; // 红色通道改为200,颜色变为#c80000
my-color.alpha = 128; // 透明度改为128(半透明)

2. 全局颜色函数:自由创建颜色

rgb ()/rgba ():按 RGB 通道创建

前 3 个参数为 0-255 或百分比,第 4 个参数(可选)为 0-1 的透明度,参数逗号必须保留(区别于 CSS)。

slint

property<color> red: rgb(255, 0, 0); // 纯红色
property<color> semi-green: rgba(0, 255, 0, 0.5); // 半透明绿色
property<color> percent-red: rgb(100%, 0%, 0%); // 百分比表示,等同于rgb(255,0,0)
hsv ()/hsva ():按 HSV 模式创建

适合需要调整色相、饱和度的场景,色相(h)0-360 度,饱和度(s)、明度(v)0-1。

slint

property<color> bright-yellow: hsv(60, 1.0, 1.0); // 纯黄色(色相60度)
property<color> dark-blue: hsv(240, 0.8, 0.5); // 暗蓝色(色相240度,低明度)

3. 颜色方法:动态调整配色

所有颜色和画笔都支持以下方法,无需手动计算色值,轻松实现配色变化:

方法 效果 示例
brighter(factor) 提高亮度 red.brighter(0.5)(红色变亮 50%)
darker(factor) 降低亮度 blue.darker(0.3)(蓝色变暗 30%)
mix(other, factor) 混合两种颜色 red.mix(green, 0.7)(70% 红色 + 30% 绿色)
transparentize(factor) 增加透明度 white.transparentize(0.8)(白色 80% 透明)
with-alpha(alpha) 直接设透明度 black.with-alpha(0.5)(黑色半透明)
to-hsv() 转为 HSV 模式 color.to-hsv()(返回含 h/s/v/a 的结构体)

4. 渐变效果:让 UI 更有质感

Slint 支持线性、径向、圆锥三种渐变,用简单语法就能实现专业级视觉效果。

线性渐变(@linear-gradient):沿直线过渡

按角度和色标定义,颜色沿直线方向渐变,适合背景、按钮填充。

slint

export component Example inherits Window {
    preferred-width: 100px;
    preferred-height: 100px;
    Rectangle {
        // 90度方向(从左到右):浅蓝色 → 浅色调 → 橙色
        background: @linear-gradient(90deg, #3f87a6 0%, #ebf8e1 50%, #f69d3c 100%);
    }
}
径向渐变(@radial-gradient):圆形扩散过渡

从中心点向外圆形渐变,适合卡片、图标背景。

slint

export component Example inherits Window {
    preferred-width: 100px;
    preferred-height: 100px;
    Rectangle {
        // 中心红色 → 中间绿色 → 边缘蓝色
        background: @radial-gradient(circle, #f00 0%, #0f0 50%, #00f 100%);
    }
}
圆锥渐变(@conic-gradient):围绕中心旋转过渡

类似色轮效果,颜色围绕中心点旋转过渡,适合制作仪表盘、色轮控件。

slint

export component Example inherits Window {
    preferred-width: 100px;
    preferred-height: 100px;
    Rectangle {
        // 红(0deg)→ 绿(120deg)→ 蓝(240deg)→ 红(360deg),形成色轮
        background: @conic-gradient(#f00 0deg, #0f0 120deg, #00f 240deg, #f00 360deg);
    }
}
圆锥渐变注意事项

不能直接使用负角度(如#ff0000 -90deg),解决方案:

  1. 转正角度:-90deg → 270deg
  2. 使用变量:property <angle> start: -90deg; 后在渐变中使用start
  3. 显式减法:#ff0000 0deg - 90deg

四、计时器(Timer)

Timer可以精准控制时间逻辑,是 Slint 中处理定时任务的核心组件,无需复杂代码就能实现倒计时、轮询、定时刷新等功能,注意它不是可见元素,没有视觉属性。

1. 基础示例:10 秒倒计时(入门必看)

slint

import { Button } from "std-widgets.slint";
export component Example inherits Window {
    property <int> value: 10; // 倒计时初始值
    // 定义计时器
    timer := Timer {
        interval: 1s; // 触发间隔:1秒
        running: true; // 初始状态:运行中
        // 每次触发执行的逻辑
        triggered() => {
            value -= 1; // 数值减1
            if (value == 0) {
                self.running = false; // 倒计时结束,停止计时器
            }
        }
    }
    // 显示与控制界面
    HorizontalLayout {
        Text { text: value; } // 显示当前倒计时数值
        Button {
            text: "Reset";
            clicked() => { 
                value = 10; // 重置数值
                timer.running = true; // 重启计时器
            }
        }
    }
}

2. 核心特性:掌握计时器的 “开关与节奏”

关键属性
  • interval:触发间隔(必填项),支持ms(毫秒)、s(秒)等单位,比如250ms(每 250 毫秒触发一次);
  • running:控制运行状态(默认true,持续运行),可绑定表达式或直接修改。

⚠️ 重要提醒:默认running: true会持续占用 CPU 和功耗,不用时务必设为false

实用示例:触发 5 次后自动停止

slint

property <int> count: 0; // 计数触发次数
Timer {
    interval: 8s; // 每8秒触发一次
    triggered() => { 
        if (count >= 5) {
            self.running = false; // 触发5次后停止
        }
        count += 1;
    }
}

3. 回调与函数:灵活控制计时器

回调函数
  • triggered():每次间隔结束后触发,是计时器的核心逻辑入口。
控制函数
  • start():启动计时器(等同于running = true);
  • stop():停止计时器(等同于running = false);
  • restart():重启已启动的计时器(重置间隔,重新开始计时)。

总结:从基础到实战,快速搭建优质 UI

Slint 的核心特性围绕 “简洁、实用、高效” 设计 —— 数据类型适配 UI 场景,通用属性统一交互逻辑,颜色画笔简化视觉设计,计时器精准控制时间流程。掌握这些内容后,你可以:

  1. 用字符串、数值类型搭建 UI 基础逻辑;
  2. 用视觉属性和动画让 UI 动起来、变好看;
  3. 用颜色与渐变打造专业视觉效果;
  4. 用计时器实现定时任务、交互反馈。

现在就动手尝试吧!把这些特性组合起来,就能快速开发出交互流畅、视觉精美的跨平台 UI。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐