删除了之前的所有内容,重新开始

This commit is contained in:
cvraindays 2024-03-02 16:03:42 +08:00
parent 1a6267a043
commit 20312d25c0
30 changed files with 17 additions and 2786 deletions

View File

@ -1,18 +1,28 @@
# Slint 参考文档 中文(非官方翻译)
# Slint 简明阐微 中文教程
> 原文:<https://slint.dev/releases/1.3.2/docs/slint/>
本系列文档是Slint文档的官方翻译本人是Slint的爱好者苦于在国内找不到中文文档因此决定翻译官方文档以供国内Slint爱好者学习。
文档翻译工作正在进行中,欢迎感兴趣的朋友加入。
## 前言
本仓库原来是想做一个对Slint官方文档的本地化工作的翻译项目也顺利的完成了许多章节的翻译。但是有一天转念一想现在使用Slint的开发者不少对文档翻译的更多拥有翻译软件和AI加持下看文档并不需要有一个特定的项目完成这些。
然而经过个人几个月的研究和学习觉得似乎有必要做一套对新人比较友好的教程指有编程基础但没有接触过GTK, QML等设计的。官方文档固然详细但不是一个很舒适的新手手册。本人对Slint很喜欢Slint也想尝试做一些贡献。做此教程分享自己的学习路径和心得供大家相互学习交流。
## 简介
本系列文档共有四个部分,分别是:Slint language, Apis using Rust, Apis using C++, Example。因为本人对Javascript并不够了解因此Javascript部分将不会翻译。
本系列教程一共包括四个模块Slint标记语言、C++ API、Rust API、简单案例。由于本人对NodeJs相关只是未曾过多涉猎所以NodeJs API目前不在完成的计划中。虽然当看到本文的时候之前的翻译内容已经删除但是依然可以从本人的博客中获得之前以及最新的翻译内容。
本人对Slint的学习也是从官方文档开始的因为在翻译的过程中也加入了个人的一些注释和补充内容在具体的文章中可以看到有不同的标注希望能够帮助到大家也接受大家的反馈。
## 目录
伴随此翻译文档的有本人的个人博客,更新的文档会先放在博客中,待一个小节均翻译完毕后再上传至本仓库。此外,文档也配套了相关的视频教程。
| 章 | 标题 | 进度 |
| :-: | :--------- | :-: |
| 起步 | 前言 | 完成 |
| 起步 | 什么是Slint | |
| 起步 | 搭建C++开发环境 | |
| 起步 | 搭建Rust开发环境 | |
| 起步 | 试一下在线编辑器 | |
| 起步 | 我们的第一个窗口 | |
## 参考连接
- 官方文档https://slint.dev/releases/1.4.1/docs/slint/
- 博客地址http://cvrain.cloudvl.cn
- 教程地址https://www.bilibili.com/video/BV1qK4y1673D

View File

@ -1,96 +0,0 @@
---
title: Slint C++ 环境配置
date: 2023-12-09 17:53:52
tags:
- Cpp
- Slint
---
# Slint C++ 环境配置
## 准备部分
`Slint` 支持使用`C++`,`Rust`,`JavaScript`进行开发。使用C++进行开发需要准备如下环境:
- C++ >= 20
- CMake >= 3.21
- Ninja
实际上Slint的实现库使用的语言是Rust 简单的可以理解在C++中使用Slint时会将Rust代码编译成为C++可以调用的库。`.slint`文件也会编译成为C++头文件以供调用。来看一下原文:
> 我们还没有提供Slint的二进制文件所以我们将使用CMake集成它将自动从源代码构建工具和库。由于它是用Rust编程语言实现的这意味着您还需要安装Rust编译器1.70或更新版本。您可以按照Rust网站上的说明轻松安装Rust编译器。我们将使用cmake的内置FetchContent模块来获取Slint的源代码。
上一个初始使用到的`CMakeLists.txt`文件一定要记得安装Rust并且还拥有git
```CMake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(memory LANGUAGES CXX)
include(FetchContent)
FetchContent_Declare(
Slint
GIT_REPOSITORY https://github.com/slint-ui/slint.git
# `release/1` will auto-upgrade to the latest Slint >= 1.0.0 and < 2.0.0
# `release/1.0` will auto-upgrade to the latest Slint >= 1.0.0 and < 1.1.0
GIT_TAG release/1
SOURCE_SUBDIR api/cpp
)
FetchContent_MakeAvailable(Slint)
add_executable(memory_game main.cpp)
target_link_libraries(memory_game PRIVATE Slint::Slint)
slint_target_sources(memory_game memory.slint)
# On Windows, copy the Slint DLL next to the application binary so that it's found.
if (WIN32)
add_custom_command(TARGET memory_game POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:memory_game> $<TARGET_FILE_DIR:memory_game> COMMAND_EXPAND_LISTS)
endif()
```
在第一次配置CMake的时候会自动下载并编译Slint的Rust库。可以在cmake build 文件夹中看到:
在加载CMakeLists.txt中前几次可能出现加载失败的情况在信息中可以找到下面几行
```
[cmake] 正克隆到 'slint-src'...
[cmake] 致命错误:在 '/mnt/Workspace/CLang/Slint/HelloWorld/build/_deps/slint-src' 检测到可疑的仓库所有权
[cmake] 要为本仓库创建特例,请运行:
[cmake]
[cmake] git config --global --add safe.directory /mnt/Workspace/CLang/Slint/HelloWorld/build/_deps/slint-src
[cmake] CMake Error at slint-subbuild/slint-populate-prefix/tmp/slint-populate-gitclone.cmake:49 (message):
[cmake] Failed to checkout tag: 'release/1'
```
然后我们从善如流,将这条指令敲一下:
```Bash
git config --global --add safe.directory /mnt/Workspace/CLang/Slint/HelloWorld/build/_deps/slint-src
git config --global --add safe.directory /mnt/Workspace/CLang/Slint/HelloWorld/build/_deps/corrosion-src
```
然后就可以喝杯`java`等待一下了
## 代码部分
熟悉CMake的人应该对此很熟悉。我们看到这个CMakeLists.txt引用了一个main.cpp我们稍后会添加它它还有一行slint_target_sourcesmemory_game memory.slint这是一个slint函数用于将memory.slinnt文件添加到目标。然后我们必须在同一目录中创建memory.slint文件。现在让我们用一个你好的世界来填充它
```Slint
// memory.slint
export component MainWindow inherits Window {
Text {
text: "hello world";
color: green;
}
}
```
这是一个名为MainWindow的组件它继承自Window组件。下面是代码的逐行解释
1. `export component MainWindow inherits Window {`这行代码定义了一个名为MainWindow的组件它继承自Window组件。Slint是一种JavaScript静态代码检查工具它可以帮助你发现代码中的错误和问题。
2. `Text {`这行代码定义了一个名为Text的子组件。子组件通常包含在父组件中使用的UI元素。
3. `text: "hello world"`这行代码定义了Text组件的text属性其值为"hello world"。
4. `color: green`这行代码定义了Text组件的color属性其值为"green"。
这个看上去有一种QML的味道但是实际上又不太一样不过QML也是通过编译成为头文件提供给C++使用的,所以猜猜接下来需要配置什么?
```C++
// main.cpp
#include "memory.h" // generated header from memory.slint
int main()
{
auto main_window = MainWindow::create();
main_window->run();
}
```

View File

@ -1,145 +0,0 @@
---
title: Slint C++ 实现最后的逻辑
date: 2023-12-21 14:26:09
tags:
- Slint
- Cpp
---
# 实现最后的逻辑
我们也将用 C++ 实现游戏规则。 Slint 的总体理念是,仅用 .slint 语言实现用户界面,并用您最喜欢的编程语言实现业务逻辑。游戏规则应强制规定最多有两块牌的窗帘打开。如果图块匹配,那么我们认为它们已解决并且它们保持打开状态。否则,我们会等待一段时间,以便玩家可以记住图标的位置,然后再次关闭它们。
<!--more-->
我们将修改 memory.slint 文件中的 .slint 标记,以便在用户单击图块时向 C++ 代码发出信号。需要对 MainWindow 进行两处更改: 我们需要为 MainWindow 添加一种调用 C++ 代码的方法以便检查一对图块是否已被解决。我们需要添加一个属性C++ 代码可以切换该属性以禁用进一步的图块交互,以防止玩家打开超过允许的图块。不允许作弊!首先,我们将回调和属性声明粘贴到 MainWindow 中:
```slint
export component MainWindow inherits Window {
width: 326px;
height: 326px;
callback check_if_pair_solved(); // 在这里添加一个回调函数
in property <bool> disable_tiles; // 对外暴露一个禁用磁贴的变量
in-out property <[TileData]> memory_tiles: [
{ image: @image-url("icons/at.png") },
```
之后修改组件MainWindow中的内容修改其中的点击事件在原来是让图片从可视化到不可视化的切换现在则首先判断是否是禁用状态的再修改图片可视化状态。
```Slint
for tile[i] in memory_tiles : MemoryTile {
x: mod(i, 4) * 74px;
y: floor(i / 4) * 74px;
width: 64px;
height: 64px;
icon: tile.image;
open_curtain: tile.image_visible || tile.solved;
// propagate the solved status from the model to the tile
solved: tile.solved;
clicked => {
// old: tile.image_visible = !tile.image_visible;
// new:
if (!root.disable_tiles) {
tile.image_visible = !tile.image_visible;
root.check_if_pair_solved();
}
}
}
```
在 C++ 方面,我们现在可以向 check_if_pair_solved 回调添加一个处理程序,该处理程序将检查是否打开了两个图块。如果它们匹配,则已求解的属性在模型中设置为 true。如果它们不匹配则启动一个计时器该计时器将在一秒钟后关闭它们。当计时器运行时我们禁用每个图块以便在此期间无法单击任何内容。
**官方代码**
```C++
auto tiles_model = std::make_shared<slint::VectorModel<TileData>>(new_tiles);
main_window->set_memory_tiles(tiles_model);
main_window->on_check_if_pair_solved(
[main_window_weak = slint::ComponentWeakHandle(main_window)] {
auto main_window = *main_window_weak.lock();
auto tiles_model = main_window->get_memory_tiles();
int first_visible_index = -1;
TileData first_visible_tile;
for (int i = 0; i < tiles_model->row_count(); ++i) {
auto tile = *tiles_model->row_data(i);
if (!tile.image_visible || tile.solved)
continue;
if (first_visible_index == -1) {
first_visible_index = i;
first_visible_tile = tile;
continue;
}
bool is_pair_solved = tile == first_visible_tile;
if (is_pair_solved) {
first_visible_tile.solved = true;
tiles_model->set_row_data(first_visible_index,
first_visible_tile);
tile.solved = true;
tiles_model->set_row_data(i, tile);
return;
}
main_window->set_disable_tiles(true);
slint::Timer::single_shot(std::chrono::seconds(1),
[=]() mutable {
main_window->set_disable_tiles(false);
first_visible_tile.image_visible = false;
tiles_model->set_row_data(first_visible_index,
first_visible_tile);
tile.image_visible = false;
tiles_model->set_row_data(i, tile);
});
}
});
main_window->run();
}
```
**代码解析**
```C++
// 调用main_window的on_check_if_pair_solved函数检查是否是成对
main_window->on_check_if_pair_solved(
[main_window_weak = slint::ComponentWeakHandle(main_window)] {
auto main_window = main_window_weak.lock().value();
auto tiles_model = main_window->get_memory_tiles();
int first_visible_index = -1;
TileData first_visible_tile;
// 遍历每一行
for (int i = 0; i < tiles_model->row_count(); ++i) {
auto tile = tiles_model.get()->row_data(i).value();
// 如果tile不可见或者已经解决则跳过
if (!tile.image_visible || tile.solved)
continue;
// 如果当前行是第一个可见行则记录下当前tile
if (first_visible_index == -1) {
first_visible_index = i;
first_visible_tile = tile;
continue;
}
// 如果当前tile和第一个可见tile相同则将两个tile都设置为已解决
bool is_pair_solved = tile == first_visible_tile;
if (is_pair_solved) {
first_visible_tile.solved = true;
tiles_model->set_row_data(first_visible_index,
first_visible_tile);
tile.solved = true;
tiles_model->set_row_data(i, tile);
return;
}
// 如果不是成对则禁用所有tile1秒后恢复
main_window->set_disable_tiles(true);
slint::Timer::single_shot(std::chrono::seconds(1),
[=]() mutable {
main_window->set_disable_tiles(false);
first_visible_tile.image_visible = false;
tiles_model->set_row_data(first_visible_index,
first_visible_tile);
tile.image_visible = false;
tiles_model->set_row_data(i, tile);
});
}
});
```
**至此整个Slint C++ tutorial 就完结了(撒花)**
基本摸清了创建一个简单Slint应用的简单流程之后便是研究研究其他控件还有通信的东西了。

View File

@ -1,182 +0,0 @@
---
title: Slint C++ 创建更多的磁贴
date: 2023-12-20 17:07:11
tags:
- Slint
- Cpp
---
# Slint C++ 创建更多的磁贴
前一个章节我们完成了一个磁贴的创建,接下来我们需要创建一个网格,在里面创建更多的磁贴来完成游戏的基本布局。当然,我们需要分两步走:
<!--more-->
1. 数据模型:这应该是一个数组,其中每个元素描述图块数据结构,例如图像的 url、图像是否可见以及该图块是否已解决。我们从 C++ 代码修改模型。 一种使用上面的 .slint 标记代码创建多个图块实例的方法。
2. 在 Slint 中,我们可以使用括号声明结构数组,以创建模型。我们可以使用 for 循环创建同一元素的多个实例。在 .slint 中for 循环是声明性的,并且在模型更改时自动更新。我们实例化所有不同的 MemoryTile 元素,并根据它们的索引将它们放置在网格上,图块之间有一点间距。
## 创建一个磁贴模型
现在我们需要控制多个磁贴了如果还是像之前那样操作单个磁贴就非常麻烦他有不同的属性图片地址是否可见是否被点击。在C++中可以使用结构体或者类来完成我们的需求,在`Slint`中也可以实现,让我们在`.slint`文件中最上面添加他们:
```Slint
struct TileData{
image: image,
image_visable: bool,
solved: bool,
}
```
创建了一个叫做`TileData`的结构体,结构体冒号左边的是名字,右边是类型:
- image: 图片类型,用来存放图片
- image_visable: 图片是否可见
- sovled是否被消除掉我不是很喜欢这个名字
## 修改MainWindow组件
接下来,我们使用以下代码片段替换 memory.slint 文件底部的导出组件
```Slint
export component MainWindow inherits Window {
width: 326px;
height: 326px;
in property <[TileData]> memory_tiles: [
{ image: @image-url("icons/at.png") },
{ image: @image-url("icons/balance-scale.png") },
{ image: @image-url("icons/bicycle.png") },
{ image: @image-url("icons/bus.png") },
{ image: @image-url("icons/cloud.png") },
{ image: @image-url("icons/cogs.png") },
{ image: @image-url("icons/motorcycle.png") },
{ image: @image-url("icons/video.png") },
];
for tile[i] in memory_tiles : MemoryTile {
x: mod(i, 4) * 74px;
y: floor(i / 4) * 74px;
width: 64px;
height: 64px;
icon: tile.image;
open_curtain: tile.image_visible || tile.solved;
// propagate the solved status from the model to the tile
solved: tile.solved;
clicked => {
tile.image_visible = !tile.image_visible;
}
}
}
```
1. `in property <[TileData]> memory_tiles: [ ... ]`:定义了一个名为`memory_tiles`的属性,其类型为`<[TileData]>`,表示它是一个数组,其中每个元素都是一个`TileData`类型的对象。`TileData`类型未知可能是一个包含图像URL和其他属性的对象。
2. `for tile[i] in memory_tiles : MemoryTile { ... }`这是一个使用QML的for循环语法遍历`memory_tiles`数组的过程。对于数组中的每个元素,都会创建一个名为`tile`的局部变量,并将其传递给名为`MemoryTile`的子组件。
3. `x: mod(i, 4) * 74px;``y: floor(i / 4) * 74px;`:这两个表达式用于计算`tile`组件的坐标。`mod(i, 4)`表示将`i`除以4的余数`floor(i / 4)`表示将`i`除以4的整数部分向下取整。然后这些值乘以74像素这是每个小方块的宽度以计算`tile`组件的x和y坐标。
4. `width: 64px;``height: 64px;`:定义了`tile`组件的宽度和高度均为64像素。
5. `icon: tile.image;`:将`tile.image`可能是图像URL或其他属性分配给`icon`属性,该属性将显示在`tile`组件上。
6. `open_curtain: tile.image_visible || tile.solved;`:这个表达式定义了`open_curtain`属性的值。`tile.image_visible`是一个布尔值,表示图像是否可见。`tile.solved`也是一个布尔值,表示该方块是否已解决。`||`表示逻辑或操作,即如果`tile.image_visible`为真或`tile.solved`为真,则`open_curtain`为真。这意味着`tile`组件的遮罩层(如果有的话)将始终显示。
7. `solved: tile.solved;`:将`tile.solved`(布尔值,表示方块是否已解决)分配给`solved`属性。
8. `clicked => { ... }`:这是一个事件处理程序,当`tile`组件被单击时触发。事件处理程序中的代码将在被单击的`tile`组件上执行。
## 完整代码
你也可以将数组复制一次这样可以得到4x4个完整的磁贴
```Slint
struct TileData {
image: image,
image_visible: bool,
solved: bool,
}
component MemoryTile inherits Rectangle{
callback clicked;
in property <bool> open_curtain;
in property <bool> solved;
in property <image> icon;
width: 64px;
height: 64px;
background: solved? darkgrey : grey;
animate background {
duration: 800ms;
}
Image {
width: parent.width;
height: parent.height;
source: icon;
}
// 左幕布
Rectangle {
width: open_curtain ? 0px : (parent.width / 2);
height: parent.height;
x: 0px;
background: darkgrey;
animate width {
duration: 250ms;
easing: ease-in;
}
}
// 右幕布
Rectangle {
width: open_curtain ? 0px : (parent.width / 2);
height: parent.height;
x: open_curtain ? parent.width : (parent.width / 2);
background: darkgrey;
animate width {
duration: 250ms;
easing: ease-in;
}
animate x {
duration: 250ms;
easing: ease-in;
}
}
TouchArea {
clicked => {
root.clicked();
}
}
}
export component MainWindow inherits Window {
width: 326px;
height: 326px;
in property <[TileData]> memory_tiles: [
{ image: @image-url("icons/at.png") },
{ image: @image-url("icons/balance-scale.png") },
{ image: @image-url("icons/bicycle.png") },
{ image: @image-url("icons/bus.png") },
{ image: @image-url("icons/cloud.png") },
{ image: @image-url("icons/cogs.png") },
{ image: @image-url("icons/motorcycle.png") },
{ image: @image-url("icons/video.png") },
{ image: @image-url("icons/at.png") },
{ image: @image-url("icons/balance-scale.png") },
{ image: @image-url("icons/bicycle.png") },
{ image: @image-url("icons/bus.png") },
{ image: @image-url("icons/cloud.png") },
{ image: @image-url("icons/cogs.png") },
{ image: @image-url("icons/motorcycle.png") },
{ image: @image-url("icons/video.png") },
];
for tile[i] in memory_tiles : MemoryTile {
x: mod(i, 4) * 74px;
y: floor(i / 4) * 74px;
width: 64px;
height: 64px;
icon: tile.image;
open_curtain: tile.image_visible || tile.solved;
// propagate the solved status from the model to the tile
solved: tile.solved;
clicked => {
tile.image_visible = !tile.image_visible;
}
}
}
```

View File

@ -1,173 +0,0 @@
---
title: Slint C++ 开幕动画
date: 2023-12-10 10:20:26
tags:
- Cpp
- Slint
---
# Slint C++ 图片开幕动画
按照小游戏的设定一开始图片是被挡住的当鼠标点击了所在图片之后图片就被掀开。现在我们需要做一个类似开幕的效果他的实现方式也不是很困难给这个矩形上面附加两个1/2大小的矩形再叠加一个透明矩形用来接受鼠标事件当点击之后左边的矩形往左走右边的矩形往右走为他们两个顺便加上过度动画效果。
<!-- more -->
## 动画设计
- 左幕布
- 高度设置为磁贴块的大小
- 宽度设置为磁贴块的一半大小
- 位置设置在磁贴块的左边
- 当点击之后宽度逐渐到0,到0后设置为不可见
- 右幕布
- 高度设置为磁贴块的大小
- 宽度设置为磁贴块的一半大小
- 位置设置在磁贴块的右边
- 当点击之后宽度逐渐到0,到0后设置为不可见
## 添加一块幕布
```Slint
component MemoryTile inherits Rectangle{
width: 64px;
height: 64px;
background: gray;
Image {
width: parent.width;
height: parent.height;
source: @image-url("icons/bus.png");
}
// 左幕布
Rectangle {
width: parent.width / 2;
height: parent.height;
x: 0px;
background: darkgray;
}
}
export component MainWindow inherits Window {
MemoryTile {}
}
```
添加一块的效果
![添加一块的效果](/img/slint-polish-tile/img01.png)
## 添加两块幕布
```Slint
component MemoryTile inherits Rectangle{
width: 64px;
height: 64px;
background: gray;
Image {
width: parent.width;
height: parent.height;
source: @image-url("icons/bus.png");
}
// 左幕布
Rectangle {
width: parent.width / 2;
height: parent.height;
x: 0px;
background: darkgray;
}
// 右幕布
Rectangle {
width: parent.width / 2;
height: parent.height;
x: parent.width / 2;
background: darkgray;
}
}
export component MainWindow inherits Window {
MemoryTile {}
}
```
## 最终代码
定义了一个名为`MemoryTile`的组件,以及一个名为`MainWindow`的窗口组件。`MemoryTile`组件继承自`Rectangle`,具有以下属性和回调函数:
1. `callback clicked`:定义了一个名为`clicked`的回调函数。
2. `in property <bool> open_curtain`:定义了一个名为`open_curtain`的属性,类型为布尔值,表示幕布的打开状态。
3. `in property <bool> solved`:定义了一个名为`solved`的属性,类型为布尔值,表示组件的状态。
4. `in property <image> icon`:定义了一个名为`icon`的属性,类型为图像,表示组件的图标。
组件的宽度和高度分别为64像素背景颜色根据`solved`属性的值来决定,如果是`solved`则为深灰色,否则为灰色。
接下来,代码定义了一个名为`animate`的动画属性用于改变组件的背景颜色。动画的持续时间为800毫秒使用`ease-in`ease-in` easing函数。
然后,代码定义了一个名为`Image`的子组件,其宽度、高度和源图像都来自父组件的`icon`属性。
接下来,代码定义了两个名为`Rectangle`的子组件,分别表示左幕布和右幕布。左幕布的宽度根据`open_curtain`属性的值来决定,如果是`open_curtain`则为0像素否则为父组件宽度的一半。背景颜色为深灰色。当`open_curtain`属性改变时,宽度会通过动画进行更新。
右幕布的宽度、高度和背景颜色与左幕布相同。此外,当`open_curtain`属性改变时,还会通过动画更新位置和宽度。
最后,代码定义了一个名为`TouchArea`的子组件,当用户点击时,会调用父组件的`clicked`回调函数。
最后,代码导出了`MainWindow`组件,并在其中定义了一个`MemoryTile`组件,其`icon`属性为`icons/bus.png`,当点击时会改变`open_curtain`属性的值。
```Slint
component MemoryTile inherits Rectangle{
callback clicked;
in property <bool> open_curtain;
in property <bool> solved;
in property <image> icon;
width: 64px;
height: 64px;
background: solved? darkgrey : grey;
animate background {
duration: 800ms;
}
Image {
width: parent.width;
height: parent.height;
source: icon;
}
// 左幕布
Rectangle {
width: open_curtain ? 0px : (parent.width / 2);
height: parent.height;
x: 0px;
background: darkgrey;
animate width {
duration: 250ms;
easing: ease-in;
}
}
// 右幕布
Rectangle {
width: open_curtain ? 0px : (parent.width / 2);
height: parent.height;
x: open_curtain ? parent.width : (parent.width / 2);
background: darkgrey;
animate width {
duration: 250ms;
easing: ease-in;
}
animate x {
duration: 250ms;
easing: ease-in;
}
}
TouchArea {
clicked => {
root.clicked();
}
}
}
export component MainWindow inherits Window {
MemoryTile {
icon: @image-url("icons/bus.png");
clicked => {
self.open-curtain = !self.open-curtain;
}
}
}
```

View File

@ -1,48 +0,0 @@
---
title: Slint C++ 画一个矩形
date: 2023-12-10 09:34:55
tags:
- Cpp
- Slint
---
# Slint C++ 画一个矩形
官方在教程中给的一个案例是记忆磁贴,也就是一组图片里选择两个相同图案的消除。这个是官方给的[demo](https://slint.dev/blog/memory-game-tutorial/memory_clip.mp4)
现在我们已经有了一个窗口,接下来就是研究一下怎么画一个矩形然后在里面塞一个图片。
打开熟悉的memory.slint
```slint
component MemoryTile inherits Rectangle{
width: 64px;
height: 64px;
background: gray;
}
export component MainWindow inherits Window {
MemoryTile {}
}
```
我们在这里创建了一个叫做`MemoryTile`的组件,他继承了`Rectangle`在其中我们设置了宽度、高度、背景颜色和QML不同的是.slint语言中的长度有一个单位这里是px后缀。这使得代码更容易阅读编译器可以检测到何时意外地将值与附加的不同单元混合在一起。
![运行效果](/img/slint-rectangle/img01.png)
请注意我们导出MainWindow组件。这是必要的以便我们以后可以从业务逻辑中访问它。
接下来就是往里面塞图片
```slint
component MemoryTile inherits Rectangle{
width: 64px;
height: 64px;
background: gray;
Image {
width: parent.width;
height: parent.height;
source: @image-url("icons/bus.png");
}
}
export component MainWindow inherits Window {
MemoryTile {}
}
```
在矩形中我们放置了一个Image元素该元素使用@Image-url宏加载一个图标。该路径是相对于memory.slint所在的文件夹的。这个图标和我们稍后要使用的其他图标需要先安装。图片素材可以自己做一套也可以直接下载 [Zip archive](https://slint.dev/blog/memory-game-tutorial/icons.zip)
![贴图片的效果](/img/slint-rectangle/img02.png)

View File

@ -1,70 +0,0 @@
---
title: Slint C++ 生成随机排列的磁贴
date: 2023-12-21 00:17:24
tags:
---
# Slint C++ 生成随机排列的磁贴
我们要做的就是获取以 .slint 语言声明的图块列表,复制它,然后对其进行打乱。我们将通过 C++ 代码访问 memory_tiles 属性来完成此操作。对于每个顶级属性,都会生成一个 getter 和 setter 函数 - 在我们的例子中为 get_memory_tiles 和 set_memory_tiles。由于 memory_tiles 是 .slint 语言中的数组,因此它表示为 std::shared_ptr<slint::Model>。我们无法修改 .slint 生成的模型,但我们可以从中提取图块,并将其放入继承自 Model 的 slint::VectorModel 中。 VectorModel允许我们进行修改我们可以用它来替换静态生成的模型。
**官方的示例代码**
```C++
// ...
#include <random> // Added
int main()
{
auto main_window = MainWindow::create();
auto old_tiles = main_window->get_memory_tiles();
std::vector<TileData> new_tiles;
new_tiles.reserve(old_tiles->row_count() * 2);
for (int i = 0; i < old_tiles->row_count(); ++i) {
new_tiles.push_back(*old_tiles->row_data(i));
new_tiles.push_back(*old_tiles->row_data(i));
}
std::default_random_engine rng {};
std::shuffle(new_tiles.begin(), new_tiles.end(), rng);
auto tiles_model = std::make_shared<slint::VectorModel<TileData>>(new_tiles);
main_window->set_memory_tiles(tiles_model);
main_window->run();
}
```
**修改后并添加注释的代码**
```C++
#include "memory.h"
#include <random>
#include <vector>
int main() {
// Create the main window
auto main_window = MainWindow::create();
// Get the current tiles and store them
const auto old_tiles = main_window->get_memory_tiles();
// Create a new vector to store the new tiles
std::vector<TileData> new_tiles{};
// Reserve space for the new tiles
new_tiles.reserve(old_tiles->row_count() * 2);
// Copy the old tiles into the new vector
for (int i = 0; i < old_tiles->row_count(); i++) {
new_tiles.emplace_back(*old_tiles->row_data(i));
new_tiles.emplace_back(*old_tiles->row_data(i));
}
// Create a random number generator
std::default_random_engine rng(std::random_device{}());
// Shuffle the new tiles
std::shuffle(new_tiles.begin(), new_tiles.end(), rng);
// Create a new model with the shuffled tiles
auto &&tiles_model = std::make_shared<slint::VectorModel<TileData>>(new_tiles);
// Set the new tiles as the memory tiles
main_window->set_memory_tiles(tiles_model);
// Run the main window
main_window->run();
}
```

View File

@ -1,46 +0,0 @@
---
title: Slint 内置函数-回调
date: 2024-01-27 08:57:17
tags:
- Slint
---
# 内置回调函数
# `init()`
每一个组件都隐式定义了一个`init`回调函数。您可以为其分配一个代码块该代码块将在实例化元素时以及使用其最终绑定的值初始化所有属性后调用。调用顺序是从内到外。以下示例将打印“first”然后“second”然后“third”
```Slint
component MyButton inherits Rectangle {
in-out property <string> 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 {
}
}
```
不要使用回调函数用来初始化组件的属性,因为这违反了描述式语法的规则。避免以这样的方式使用回调,除非真的需要它,例如,为了通知某些本机代码:
```Slint
global SystemService {
// This callback can be implemented in native code using the Slint API
callback ensure_service_running();
}
export component MySystemButton inherits Rectangle {
init => {
SystemService.ensure_service_running();
}
// ...
}
```

View File

@ -1,15 +0,0 @@
---
title: Slint 内置元素
date: 2024-01-27 09:06:22
tags:
- Slint
---
# 内置元素
## 通用属性
### 几何坐标
这些属性对所有可见项目都有效:
- `width``height` (length):元素的尺寸,被设置后可以重写默认的大小
- `x`和`y`length元素相对于其父级元素的偏移位置
- `z`(float):允许指定不同的顺序来将项目与其同级项目堆叠。 默认值0
- `absolute-position`(float):元素在所包含窗口中的位置。

View File

@ -1,171 +0,0 @@
---
title: Slint 内置枚举元素
date: 2024-01-28 20:33:33
tags:
- Slint
---
# Slint 内置枚举元素
## `AccessibleRole`
此枚举表述了`accessible-role`属性中的不同值, 用于描述辅助技术(例如屏幕阅读器)中元素的作用。
- `none` 此元素是不可访问的
- `button` 此元素是一个`Button`组件其或者行为类似`Button`
- `checkbox` 此元素是一个`CheckBox`或者其行为类型`CheckBox`
- `combobox` 此元素是一个`ComboBox`或者其行为类型`ComboBox`
- `slider` 此元素是一个`Slider`或者其行为类型`Slider`
- `spinbox` 此元素是一个`SpinBox`或者其行为类型`SpinBox`
- `tab` 此元素是一个`Tab`或者其行为类型`Tab`
- `text` 此元素是一个`Text`或者其行为类型`Text`
- `progress-indicator` 此元素是一个`ProcessIndicator`或者其行为类型`ProcessIndicator`
## `DialogButtonRole`
此枚举表示`dialog-button-role`属性的值,该属性可以添加到`Dialog`的任何元素以将该项目放入按钮行中,其确切位置取决于角色和平台。
- `none` 这个按钮不是用来进入最下面一排的
- `accept` 此规则让主按钮点击后为确认对话框,如“确实"或者”是“
- `reject` 此规则让主按钮点击为拒绝对话框,如“取消”或者”不“
- `apply` “Apply接受”按钮的职责
- `reset`“Rest (重置)” 按钮的职责
- `help` “Help帮助”按钮的职责
- `action` 执行其他操作的任何其他按钮的的功能。
## `EventResult`
该枚举描述事件处理程序是否拒绝或接受事件。
- `reject` 该事件被此事件处理程序拒绝,然后可能由父项处理
- `accept` 该事件已被接受,不会进一步处理
## `FillRule`
该枚举描述了决定路径所描述的形状内部应该是什么的不同方法。
- **`nonzero`**: The [“nonzero” fill rule as defined in SVG](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule#nonzero).
- **`evenodd`**: The [“evenodd” fill rule as defined in SVG](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule#evenodd)
## `ImageFit`
该枚举定义了图片资源在`Image`组件中怎样的适配方式
- `fill` 图片的尺寸和缩放根据`Image`元素的宽度和高度自己适配
- `contain` 源图像被缩放以适应图像元素的尺寸,同时保留纵横比。
- `cover` 源图像被缩放以覆盖图像元素的尺寸,同时保留纵横比。如果源图像的长宽比与元素的长宽比不匹配,则图像将被剪裁以适合。
## `ImageRendering`
该枚举指定如何缩放源图像。
- `smooth` 使用线性插值算法缩放图像。
- `pixelated` 使用最近邻算法缩放图像。
# `InputType`
该枚举用于定义输入字段的类型。
- `text` 默认值。以标准的方式渲染所有的字符
- `password` 默认的将所有的字符均渲染为“\*”
- `number` 输入将只能接受并渲染数字字符0-9
- `decimal` 如果字符是小数的有效部分,这将接受并呈现字符
## `LayoutAlignment`
枚举类型描述了在`HorizontalBox`, `VerticalBox`, `HorizontalLayout`, `VerticalLayout`中的布局对其方式
- `stretch` 使用布局中所有元素的最小大小,在所有元素之间基于 `*-stretch `分配剩余空间。
- `center` 对所有元素使用首选大小,在第一个元素之前和最后一个元素之后均匀分配剩余空间。
- `start` 对所有元素使用首选大小,将剩余空间放在最后一个元素之后。
- `end` 对所有元素使用首选大小,将剩余空间放在第一个元素之前。
- `space-between` 对所有元素使用首选大小,在元素之间均匀分配剩余空间。
- `space-around` 对所有元素使用首选大小,在第一个元素之前、最后一个元素之后以及元素之间均匀分配剩余空间。
## `MouseCurosr`
该枚举代表不同类型的鼠标光标。它是 CSS 中可用鼠标光标的子集。有关详细信息和象形图,请参阅光标的 MDN 文档([MDN Documentation for cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#values))。根据后端和使用的操作系统,单向调整大小光标可能会替换为双向光标。
- **`default`**: 系统默认的光标
- **`none`**: 无光标展示。
- **`help`**: 表明是帮助信息的光标。
- **`pointer`**: 表示为具有链接的光标。
- **`progress`**: 程序正在忙,但仍然可以交互。
- **`wait`**: 程序正在忙,需要等待。
- **`crosshair`**: 一个十字线 。
- **`text`**: 选中文本。
- **`alias`**: 正在创建别名或快捷方式。
- **`copy`**: 一个副本已被创建。
- **`move`**: 某些东西被移动了。
- **`no-drop`**: 一些东西不能往这里丢。
- **`not-allowed`**: 一个不被允许的行为。
- **`grab`**: 有东西是可以抓住的。
- **`grabbing`**: 有东西被抓住了。
- **`col-resize`**: 指示列可水平调整大小。
- **`row-resize`**: 指示行可垂直调整大小。
- **`n-resize`**: 向北单向调整大小。
- **`e-resize`**: 向东单向调整大小。
- **`s-resize`**: 向南单向调整大小。
- **`w-resize`**: 向西单向调整大小。
- **`ne-resize`**: 向东北方向单向调整大小。
- **`nw-resize`**: 向西北单向调整大小。
- **`se-resize`**: 单向调整东南方向大小。
- **`sw-resize`**: 向西南方向单向调整大小。
- **`ew-resize`**: 东西向双向调整大小。
- **`ns-resize`**: 南北双向调整大小。
- **`nesw-resize`**: 东北-西南双向调整大小。
- **`nwse-resize`**: 西北-东南方向双向调整大小。
## `Orientation`
表示元素或小部件(例如滑块)的方向。
- `horizontal`: 水平元素定向
- `vertical`: 垂直元素定向
## `PathEvent`
PathEvent 是描述路径组成的低级数据结构。通常,它是在编译时根据更高级别的描述(例如 SVG 命令)生成的。
- **`begin`**:路径的开始。
- **`line`**:路径上的直线。
- **`quadratic`**:路径上的二次贝塞尔曲线。
- **`cubic`**:路径上的三次贝塞尔曲线。
- **`end-open`**:保持开放的路径末端。
- **`end-closed`**:闭合路径的末端。
## `PointerEventButton`
该枚举描述了指针事件的不同类型的按钮,通常是鼠标或铅笔上的按钮。
- `other` 非左、右、中按钮。例如,这用于具有多个按钮的鼠标上的第四个按钮。
- `left`:左按钮。
- `right`:右按钮。
- `middle`:中按钮。
## `PointerEventKind`
枚举描述了 `PointerEventButton` 事件中存在的元素
- `cancel`:行动被取消了。
- `down`:按钮被按下了。
- `up`:按钮被释放了(抬起按钮)。
## `SortOrder`
该枚举表示排序顺序属性的不同值。它用于按列对 [`StandardTableView`](https://slint.dev/releases/1.3.2/docs/slint/src/language/widgets/standardtableview.html) 进行排序。
- `unsorted`:此列未能排序。
- `ascending`:该列按升序排序。
- `descending`:该列按降序排序。
## `StandardButtonKind`
使用此枚举将标准按钮添加到[`Dialog`](https://slint.dev/releases/1.3.2/docs/slint/src/language/builtins/elements.html#dialog)中。这些[`StandardButton`](https://slint.dev/releases/1.3.2/docs/slint/src/language/widgets/standardbutton.html)标准按钮的外观和位置取决于应用程序运行的环境操作系统、UI 环境等)。
(按照本人的理解是,在一个弹出的对话框中可以添加多个按钮,每个按钮有不同作用以及相对应的功能)
- `ok`:接受对话框的“确定”按钮,单击时将其关闭。
- `cancel`:一个“取消”按钮,用于拒绝对话框,单击时将其关闭。
- `apply`:一个“应用”按钮,应该接受来自对话框的值而不关闭它。
- `close`:“关闭”按钮,它应该关闭对话框而不查看值。
- `reset`:“重置”按钮,该按钮应将对话框重置为其初始状态。
- `help`:“帮助”按钮,单击时应显示上下文相关文档。
- `yes`:“是”按钮,用于确认操作。
- `no`:“否”按钮,用于拒绝操作。
- `abort`:“中止”按钮,用于中止操作。
- `retry`:“重试”按钮,用于重试失败的操作。
- `ignore`:“忽略”按钮,用于忽略失败的操作。
## `TextHorizontalAlignment`
该枚举描述了文本沿 Text 元素水平轴的不同类型的对齐方式。
- `left`:文本将与包含框的左边缘对齐。
- `center`:文本将在包含框中水平居中。
- `right`:文本将与包含框的右侧对齐。
## `TextOverflow`
该枚举描述了当文本太宽而无法适应文本宽度时文本的显示方式。
- `clip`:文本将被简单地剪切。
- `elide`:多出的文本会以省略号呈现
## `TextVerticalAlignment`
该枚举描述了文本沿 Text 元素垂直轴的不同类型的对齐方式。
- `top`:文本将与包含框的顶部对齐。
- `center`:文本将在包含框中垂直居中。
- `bottom`:文本将与包含框的底部对齐。
## `TextWrap`
该枚举描述了文本太宽而无法适应文本宽度时如何换行。
- `no-warp`:文本不会换行,而是会溢出。
- `word-warp`:文本将在单词边界处换行。

View File

@ -1,29 +0,0 @@
# 介绍
Slint提供了一种易于学习和使用的语言供您用来描述用户界面。它对于人类和机器来说都是可读的。
这样,我们一方面拥有出色的工具,同时还使设计人员和开发人员能够通过阅读他们的机器用于显示用户界面的代码来准确了解发生了什么。
这种 Slint 语言要么在运行时解释要么编译为本机代码它与提供业务逻辑的相同编程语言的代码一起内置到您的应用程序中。Slint 编译器可以优化用户界面及其在编译时使用的任何资源,以便使用 Slint 编写的用户界面在性能和存储方面使用很少的资源。
Slint 语言使用您可以为项目定义的接口强制将用户界面与业务逻辑分离。这使得专注于设计的团队成员和专注于项目编程方面的团队成员之间能够进行无畏的合作。
Slint 语言使用Slint 框架描述可扩展的图形用户界面
使用文本表示在窗口中放置并组成视觉元素树。
通过属性配置元素的外观。例如,文本元素具有文本属性,而矩形元素具有背景颜色。
将绑定表达式分配给属性以自动计算依赖于其他属性的值。
将绑定表达式与命名状态和条件组合在一起。
声明属性和状态的动画以使用户界面感觉生动。
构建您自己的可重用组件并在.slint模块文件中共享它们。
定义数据结构和模型并通过编程语言访问它们。
使用提供的内置元素和预构建小部件构建高度定制的用户界面。
它仅描述用户界面,而不是编程语言。业务逻辑是使用 Slint API 以不同的编程语言编写的。

View File

@ -1,364 +0,0 @@
---
title: Slint 元素的定位和布局
date: 2023-12-22 18:14:21
tags:
- Slint
---
2# Slint 元素的定位和布局
所有视觉元素都显示在一个窗口中。 x 和 y 属性存储元素相对于其父元素的坐标。 Slint 通过将父元素的位置添加到元素的位置来确定元素的绝对位置。如果父元素存在了一个坐标,那么子类就会从进行坐标的累加计算,直到顶级元素。
`width`和`height`会存储元素的宽度和高度(很容易理解不是)
您可以通过两种方式放置元素来创建整个图形用户界面:
- 通过`x`,`y`,`width`,`height`属性显式创建
- 通过布局元素自动设置
显式放置非常适合元素很少的静态场景。布局适用于复杂的用户界面,并有助于创建可扩展的用户界面。布局元素表达元素之间的几何关系。
## 显式放置
```slint
export component Example inherits Window {
width: 200px; //设置窗口宽度为200px
height: 200px; //设置窗口高度为200px
Rectangle { //定义一个矩形
x: 100px;
y: 70px;
width: parent.width - self.x; // 宽度是父元素宽度减自身x位置
height: parent.height - self.y;
background: blue; // 背景颜色是蓝色
Rectangle {
x: 10px;
y: 5px;
width: 50px;
height: 30px;
background: green;
}
}
}
```
两个矩形的位置和内部绿色矩形的大小都是固定的。外部蓝色矩形的大小是使用宽度和高度属性的绑定表达式自动计算的。计算结果是左下角与窗口的角对齐 - 只要窗口的宽度和高度发生变化,它就会更新。
当为任何几何属性指定显式值时Slint 要求您为数字附加一个单位。您可以选择两种不同的单位:
- 逻辑像素使用px单位后缀。这是推荐单位。
- 物理像素使用phx单位后缀
逻辑像素会根据系统配置的设备像素比率自动缩放。 宽度和高度属性也可以指定为百分比单位该单位相对于父元素应用。例如宽度50% 表示父级宽度的一半。
x 和 y 属性的默认值使得元素在其父元素中居中。
宽度和高度的默认值取决于元素的类型。有些元素会根据它们的内容自动调整大小比如Image、Text和大多数小部件。以下元素没有内容当它们没有子元素时默认会填充它们的父元素:
- `Rectangle`
- `TouchArea`
- `FocusScope`
- `Flickable`
布局也默认填充父级,无论它们自己的首选大小如何。
其他元素(包括没有基础的自定义元素)默认使用其首选尺寸。
## 首选尺寸
元素的首选大小可以通过preferred-width和preferred-height属性指定。
当未显式设置时首选大小取决于子元素并且是具有更大首选大小的子元素的首选大小其x和y属性未设置。因此首选大小从子到父计算就像其他约束(最大和最小大小)一样,除非显式覆盖。
一种特殊情况是使用100%作为值将首选大小设置为父元素的大小。例如,这个组件将默认使用父组件的大小:
```slint
component MyComponent {
preferred-width: 100%;
preferred-height: 100%;
// ...
}
```
## 使用布局自动放置
Slint带有不同的布局元素可以自动计算其子元素的位置和大小:
- `verticallout` / `HorizontalLayout`:子元素沿着垂直或水平轴放置。可以理解是水平对齐和垂直布局
- `GridLayout` 元素通过行列进行放置
布局是可以嵌套的,通过嵌套布局可以完成更加复杂的组建排布
您可以使用不同的约束来调整自动放置,以适应用户界面的设计。每个元素都有最小大小、最大大小和首选大小。使用以下属性显式设置这些属性:
- `min-width`
- `min-height`
- `max-width`
- `max-height`
- `preferred-width`
- `preferred-height`
任何指明了`width`和`height`的元素都会存在固定的大小比如给MainWindow设置了大小那么就无法再放大和缩小窗口了
当布局中有额外的空间时,元素可以沿着布局轴拉伸。你可以用这些属性来控制元素和它的兄弟元素之间的拉伸系数:
- `horizontal-stretch`
- `vertical-stretch`
值为 0 意味着元素根本不会拉伸。如果所有元素的拉伸因子都为 0则所有元素都会同等拉伸。
这些约束属性的默认值可能取决于元素的内容。如果元素的 x 或 y 未设置,这些约束也会自动应用于父元素。
## 布局元素的通用属性
- `spacing` 控制两个并列元素的间距
- `padding` 这指定布局内的填充、元素之间的空间以及布局的边框距离可以参考css的盒子模型
如果不设置spacing的大小默认为0则会导致两个元素堆积在一起。为了进行更细粒度的控制可以将 padding 属性拆分为布局每一侧的属性:
- `padding-left`
- `padding-right`
- `padding-top`
- `padding-bottom`
## `VerticalLayout``HorizontalLayout`
`verticalalLayout`和`HorizontalLayout`元素将它们的子元素放置在列或行中。默认情况下,它们会拉伸或收缩以占用整个空间。您可以根据需要调整元素的对齐方式。
下面的示例将蓝色和黄色矩形放在一行中并均匀地拉伸到200个逻辑像素的宽度上:
```slint
// Stretch by default
export component Example inherits Window {
width: 200px;
height: 200px;
HorizontalLayout {
Rectangle { background: blue; min-width: 20px; }
Rectangle { background: yellow; min-width: 30px; }
}
}
```
另一方面,下面的示例指定矩形应对齐布局的开始(可视左侧)。这将导致不拉伸,而是矩形保留其指定的最小宽度:
```slint
// Unless an alignment is specified
export component Example inherits Window {
width: 200px;
height: 200px;
HorizontalLayout {
alignment: start;
Rectangle { background: blue; min-width: 20px; }
Rectangle { background: yellow; min-width: 30px; }
}
}
```
下面的例子包含了两个更复杂场景的布局:
```slint
export component Example inherits Window {
width: 200px;
height: 200px;
HorizontalLayout {
// Side panel
Rectangle { background: green; width: 10px; }
VerticalLayout {
padding: 0px;
//toolbar
Rectangle { background: blue; height: 7px; }
Rectangle {
border-color: red; border-width: 2px;
HorizontalLayout {
Rectangle { border-color: blue; border-width: 2px; }
Rectangle { border-color: green; border-width: 2px; }
}
}
Rectangle {
border-color: orange; border-width: 2px;
HorizontalLayout {
Rectangle { border-color: black; border-width: 2px; }
Rectangle { border-color: pink; border-width: 2px; }
}
}
}
}
}
```
## 对齐方式
如果指定了每个元素的宽度或高度则根据它们的宽度或高度设置大小否则它将被设置为最小大小这是通过min-width或min-height属性设置的或者是内部布局的最小大小无论大小较大。
元素按照对齐方式放置。只有当布局的对齐属性为layoutalalignment时元素的大小才会大于最小尺寸。拉伸(默认)
这个例子展示了不同的对齐可能性
```slint
export component Example inherits Window {
width: 300px;
height: 200px;
VerticalLayout {
HorizontalLayout {
alignment: stretch;
Text { text: "stretch (default)"; }
Rectangle { background: blue; min-width: 20px; }
Rectangle { background: yellow; min-width: 30px; }
}
HorizontalLayout {
alignment: start;
Text { text: "start"; }
Rectangle { background: blue; min-width: 20px; }
Rectangle { background: yellow; min-width: 30px; }
}
HorizontalLayout {
alignment: end;
Text { text: "end"; }
Rectangle { background: blue; min-width: 20px; }
Rectangle { background: yellow; min-width: 30px; }
}
HorizontalLayout {
alignment: start;
Text { text: "start"; }
Rectangle { background: blue; min-width: 20px; }
Rectangle { background: yellow; min-width: 30px; }
}
HorizontalLayout {
alignment: center;
Text { text: "center"; }
Rectangle { background: blue; min-width: 20px; }
Rectangle { background: yellow; min-width: 30px; }
}
HorizontalLayout {
alignment: space-between;
Text { text: "space-between"; }
Rectangle { background: blue; min-width: 20px; }
Rectangle { background: yellow; min-width: 30px; }
}
HorizontalLayout {
alignment: space-around;
Text { text: "space-around"; }
Rectangle { background: blue; min-width: 20px; }
Rectangle { background: yellow; min-width: 30px; }
}
}
}
```
## 拉伸算法
当对齐设置为拉伸(默认值)时元素的大小将达到最小大小然后额外的空间将在元素之间共享这些元素与使用水平拉伸和垂直拉伸属性设置的拉伸因子成比例。拉伸后的尺寸不会超过最大尺寸。拉伸因子是一个浮点数。具有默认内容大小的元素通常默认为0而默认为其父元素大小的元素默认为1。伸缩因子为0的元素将保持其最小大小除非所有其他元素的伸缩因子也为0或达到其最大大小。
```slint
export component Example inherits Window {
width: 300px;
height: 200px;
VerticalLayout {
// Same stretch factor (1 by default): the size is divided equally
HorizontalLayout {
Rectangle { background: blue; }
Rectangle { background: yellow;}
Rectangle { background: green;}
}
// Elements with a bigger min-width are given a bigger size before they expand
HorizontalLayout {
Rectangle { background: cyan; min-width: 100px;}
Rectangle { background: magenta; min-width: 50px;}
Rectangle { background: gold;}
}
// Stretch factor twice as big: grows twice as much
HorizontalLayout {
Rectangle { background: navy; horizontal-stretch: 2;}
Rectangle { background: gray; }
}
// All elements not having a maximum width have a stretch factor of 0 so they grow
HorizontalLayout {
Rectangle { background: red; max-width: 20px; }
Rectangle { background: orange; horizontal-stretch: 0; }
Rectangle { background: pink; horizontal-stretch: 0; }
}
}
}
```
```slint
export component Example inherits Window {
width: 200px;
height: 50px;
HorizontalLayout {
Rectangle { background: green; }
for t in [ "Hello", "World", "!" ] : Text {
text: t;
}
Rectangle { background: blue; }
}
}
```
## 表格对齐
GridLayout将元素放置在网格中。每个元素获得row、col、rowspan和colspan属性。可以使用Row子元素也可以显式设置Row属性。这些属性在编译时必须是静态已知的因此不可能使用算术运算或依赖属性。到目前为止在网格布局中不允许使用for或if。
```slint
export component Foo inherits Window {
width: 200px;
height: 200px;
GridLayout {
spacing: 5px;
Row {
Rectangle { background: red; }
Rectangle { background: blue; }
}
Row {
Rectangle { background: yellow; }
Rectangle { background: green; }
}
}
}
```
```slint
export component Foo inherits Window {
width: 200px;
height: 150px;
GridLayout {
spacing: 0px;
Rectangle { background: red; }
Rectangle { background: blue; }
Rectangle { background: yellow; row: 1; }
Rectangle { background: green; }
Rectangle { background: black; col: 2; row: 0; }
}
}
```
## 一个综合实例
```slint
component GridRectangle {
GridLayout {
spacing: 5px;
Row{
Rectangle {
width: 50px;
height: 50px;
background: #FFDDDD;
}
Rectangle {
width: 50px;
height: 50px;
background: #FFEEDD;
}
}
Row{
Rectangle {
width: 50px;
height: 50px;
background: #FFEEEE;
}
Rectangle {
width: 50px;
height: 50px;
background: #FFDDEE;
}
}
}
}
export component MainWindow inherits Window {
in property <int> window_width;
in property <int> window_height;
preferred-width: 640px;
preferred-height: 480px;
max-height: 640px;
max-width: 480px;
Rectangle {
width: parent.width;
height: parent.height;
background: #FFEEFF;
HorizontalLayout {
alignment: space-between;
GridRectangle{}
Rectangle {
height: parent.height;
width: 15%;
background: #FFCCBB;
}
}
}
}
```

View File

@ -1,115 +0,0 @@
---
title: Slint 容器组件
date: 2024-01-08 21:00:53
tags:
- Slint
---
# Slint 容器组件
在创建组件时,有时影响子元素在使用时的位置是很有用的。例如,假设有一个组件在用户放置的元素上方绘制一个标签:
<!--more-->
```Slint
export component MyApp inherits Window {
BoxWithLabel {
Text {
// ...
}
}
// ...
}
```
您可以使用布局实现这样的BoxWithLabel。默认情况下像Text元素这样的子元素成为BoxWithLabel的直接子元素但是我们需要它们成为布局的子元素。为此你可以在组件的元素层次结构中使用@children表达式来改变默认的子节点位置:
```Slint
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; }
}
}
```
上面说的有点弯弯绕了,甚至前五分钟我没有理解这到底在说什么,简单来说。假设一个用户创建了一个组件,但是这个组件实际的工作性质是一个容器,也就是可以嵌入其他组件,那么就在需要嵌入的地方塞一个`@children`
```Slint
component GridRectangle {
GridLayout {
spacing: 5px;
Row{
Rectangle {
width: 50px;
height: 50px;
background: #FFDDDD;
}
Rectangle {
width: 50px;
height: 50px;
background: #FFEEDD;
}
}
Row{
Rectangle {
width: 50px;
height: 50px;
background: #FFEEEE;
@children
}
Rectangle {
width: 50px;
height: 50px;
background: #FFDDEE;
}
}
}
}
component ColordRectangle {
Rectangle {
background: lightpink;
@children
}
}
export component MainWindow inherits Window {
preferred-width: 640px;
preferred-height: 480px;
max-height: 640px;
max-width: 480px;
ColordRectangle {
preferred-width: parent.width;
preferred-height: parent.height;
GridRectangle {}
}
}
```
@children是一个表达式它允许您在自定义组件中嵌套其他组件。例如如果您想在BoxWithLabel组件中添加一个标签您可以将子元素放在BoxWithLabel的布局中而不是直接作为BoxWithLabel的子元素。这样您就可以使用@children表达式来控制标签的位置。
**`@children`占位符只能在元素层次结构中出现一次**
比如上面的例子修改成为这样是不可以的
```Slint
component BoxWithLabel inherits GridLayout {
Row {
@children
}
Row {
@children
}
}
```

View File

@ -1,54 +0,0 @@
---
title: Slint 焦点处理
date: 2024-01-08 22:39:12
tags:
- Slint
---
# Slint 焦点处理
某些元素(如TextInput)不仅接受来自鼠标/手指的输入,还接受来自(虚拟)键盘的键事件。为了让控件接收这些事件它必须具有焦点。这可以通过has-focus (out)属性看到。
你可以通过调用focus()来手动激活元素的焦点:
```Slint
import { Button } from "std-widgets.slint";
export component App inherits Window {
VerticalLayout {
alignment: start;
Button {
text: "press me";
clicked => { input.focus(); }
}
input := TextInput {
text: "I am a text input field";
}
}
}
```
如果你已经在组件中包装了TextInput那么你可以使用forward-focus属性来转发这样的焦点激活以引用应该接收它的元素:
```Slint
import { Button } from "std-widgets.slint";
component LabeledInput inherits GridLayout {
forward-focus: input;
Row {
Text {
text: "Input Label:";
}
input := TextInput {}
}
}
export component App inherits Window {
GridLayout {
Button {
text: "press me";
clicked => { label.focus(); }
}
label := LabeledInput {
}
}
}
```
如果在窗口上使用forward-focus属性则指定的元素将在窗口第一次接收焦点时接收焦点-它将成为初始焦点元素。

View File

@ -1,26 +0,0 @@
---
title: Slint 字体处理
date: 2024-01-09 09:54:20
tags:
- Slint
---
# Slint 字体处理
一些元素诸如`Text`和`TextInput` 能够渲染文本以及允许通过不同的属性自定义文本的外观。以 font- 为前缀的属性,例如 font-family、font-size 和 font-weight 会影响用于渲染到屏幕的字体的选择。如果未指定任何这些属性,则应用周围 Window 元素中的 default-font- 值,例如 default-font-family。
选择用于渲染的字体会自动从系统中获取。还可以在您的设计中包含自定义字体。自定义字体必须是 TrueType 字体 (.ttf)、TrueType 字体集合 (.ttc) 或 OpenType 字体 (.otf)。您可以使用导入语句选择自定义字体:在 .slint 文件中导入“./my_custom_font.ttf”。这指示 Slint 编译器包含字体并使字体系列全局可与 font-family 属性一起使用。
简单来说Slint支持自定义字体而且方法并不复杂。甚至只需要两个步骤就可以了
1. `import` + 字体文件路径
2. `default-font-family` 设置字体样式
```Slint
import "./NotoSans-Regular.ttf";
export component Example inherits Window {
default-font-family: "Noto Sans";
Text {
text: "Hello World";
}
}
```

View File

@ -1,45 +0,0 @@
---
title: Slint 纯度
date: 2024-01-09 10:11:15
tags:
- Slint
---
# Slint 纯度
**友情提示**
本章节内容本人做了一定的补充,实际内容和原文有一定区别。原文内容使用引用符号标注。
> Slint中的属性是评估是惰性的并且”相对的、被动“的。当某个属性在被读取时才会评估属性绑定。属性之间的依赖关系是在属性评估过程中自动发现的。该属性存储评估的结果。当属性发生更改时会通知所有依赖属性以便下次读取其值时重新评估其绑定。
这种加载方式和编程时用的懒拷贝技术并不是完全一样的,当存在一个主控件,此组件下面又存在多个小组件,他们的的宽度属性是这样设置的: `width : parent.width % 75%`。我们可以得知子组件的宽度属性是父组件的75% 。
实际上实现的效果并不是在每一帧的渲染中将父组件的宽度属性乘上75%的值设置给子控件,而是在第一次设置之后,当上级组件发生属性改变之后,再将值传给后依赖此属性的后续组件。
> 为了让任何相对系统都能正常工作,评估一个属性不应该改变任何可观察的状态,而应该改变属性本身。如果是这样的话,那么这个表达是“纯的”,否则就被认为有副作用。副作用是有问题的,因为并不总是清楚它们何时会发生:懒惰的评估可能会改变它们的顺序,或者影响它们是否会发生。此外,在属性的绑定评估过程中,由于副作用而对属性进行的更改可能会导致意外行为。
如果我们写出类似这样的代码:
```Slint
component A {
Rectangle{
@children
}
}
component MainWindow inherits Window{
width: A.width
A{
width: parent.width
}
}
```
实际上这样的代码是无法运行的仅借此表示一个直观的含义。主窗口的宽度需要组件A的宽度然而组件A依赖MainWindow的宽度一旦有一个组件被i修改了这样就很难评估改变的顺序这也会导致产生以外的行为。
> 因此Slint 中的绑定必须是纯的。 Slint 编译器强制纯上下文中的代码没有副作用。纯上下文包括绑定表达式、纯函数体和纯回调处理程序体。在这种情况下,不允许更改属性或调用非纯回调或函数。
> 使用 pure 关键字注释回调和公共函数,以便可以从属性绑定和其他纯回调和函数访问它们。
> 私有函数的纯度是自动推断的。您可以显式声明私有函数为“pure”以使编译器强制执行其纯度。
```Slint
export component Example {
pure callback foo() -> int;
public pure function bar(x: int) -> int
{ return x + foo(); }
}
```

View File

@ -1,138 +0,0 @@
---
title: Slint 语言翻译
date: 2024-01-09 12:07:45
tags:
- Slint
---
# Slint 语言翻译
使用Slint自带基本翻译功能可以让你的程序实现切换不同的语言
完成下面几个步骤便可以完成程序的翻译工作:
1. 表明所有对用户可见且需要翻译的字符串并使用`@tr()`宏进行注释
2. 使用 `slint-tr-extractor` 工具提取带注释的字符串并生成 .pot 文件。
3. 使用第三方工具将字符串翻译为目标语言,如 .po 文件。
4. 使用 gettext 的 msgfmt 工具将 .po 文件转换为运行时可加载的 .mo 文件。
5. 根据用户的区域设置,使用 Slint 的 API 在运行时选择并加载 .mo 文件。此时,所有标记为翻译的字符串将自动以目标语言呈现。
# 注释可翻译字符串
在 .slint 文件中使用 @tr 宏来标记要翻译的字符串。该宏将通过替换 {} 占位符来处理翻译和格式设置。
第一个参数必须是纯字符串文字,后跟参数(这个写法好像printf)
```Slint
export component Example {
property <string> name;
Text {
text: @tr("Hello, {}", name);
}
}
```
## 格式化
`@tr `宏将标记为翻译的字符串中的每个` {} `占位符替换为相应的参数。还可以使用 `{0}、{1} `等对参数重新排序。即使原始字符串没有,翻译人员也可以使用有序占位符。
## 复数格式
当涉及可变数量元素的文本翻译应根据是单个元素还是多个元素而变化时,请使用复数格式。
在计算某些东西的个数时,使用`count`和表达式来表示,用 `| `形成复数形式和 `% `符号如下:
`@tr("I have {n} item" | "I have {n} items" % count)`.
也就是说slint会根据数字的单数还是复数来选择使用什么格式的翻译比如这里就会存在 "I have a/one item" 和 "I have two/three items"的情况)
在格式字符串中使用 {n} 来访问 % 之后的表达式。
```Slint
export component Example inherits Text {
in property <int> score;
in property <int> name;
text: @tr("Hello {0}, you have one point" | "Hello {0}, you have {n} point" % score, name);
}
```
## 语境
通过使用 "..." => 语法向 @tr(...) 宏添加语境,消除具有相同源文本但上下文语境含义不同的字符串的翻译歧义。
使用上下文为译者提供额外的上下文信息,确保翻译准确且符合当前语境。
上下文必须是纯字符串文字,并且在 .pot 文件中显示为 msgctx。如果未指定上下文默认为周围组件的名称。
```Slint
export component MenuItem {
property <string> name : @tr("Name" => "Default Name"); // Default: `MenuItem` will be the context.
property <string> tooltip : @tr("ToolTip" => "ToolTip for {}", name); // Specified: The context will be `ToolTip`.
}
```
## 提取可翻译字符串
使用`slint-tr-extractor` 工具从`.slint`文件生成出`.pot`文件,可以这样运行指令
```bash
find -name \*.slint | xargs slint-tr-extractor -o MY_PROJECT.pot
```
这将创建一个名为 MY_PROJECT.pot 的文件。将 MY_PROJECT 替换为您的实际项目名称。要了解项目名称如何影响翻译查找,请参阅以下部分。
`.pot` files are [Gettext](https://www.gnu.org/software/gettext/) template files.
# 翻译字符串
通过从 .pot 文件创建 .po 文件来开始新翻译。两种文件格式相同。您可以手动复制文件,也可以使用 Gettext 的 msginit 等工具来启动新的 .po 文件。
.po 文件将包含目标语言的字符串。
.po 和 .pot 文件是纯文本文件,您可以使用文本编辑器进行编辑。我们建议使用专用翻译工具来处理它们,例如:
- [poedit](https://poedit.net/)
- [OmegaT](https://omegat.org/)
- [Lokalize](https://userbase.kde.org/Lokalize)
- [Transifex](https://www.transifex.com/) (web interface)
## 转换`.po`文件到`.mo`文件
人类可读的 .po 文件需要转换为机器友好的 .mo 文件,这是一种读取效率非常高的二进制表示形式。
使用 [Gettext](https://www.gnu.org/software/gettext/)的`msgfmt` 命令行工具以将`.po`文件转换到`.mo`文件
```Bash
msgfmt translation.po -o translation.mo
```
## 在运行时选择并加载`.mo`文件
Slint 使用 Gettext 库在运行时加载翻译。 Gettext 将翻译文件生成在以下指定位置下:
`dir_name/locale/LC_MESSAGES/domain_name.mo`
- dir_name: 你自由原则的根目录文件夹
- locale: 给定目标语言的用户区域设置名称,例如 fr 代表法语de 代表德语。区域设置通常是使用操作系统设置的环境变量来确定的。
- domain_name: 根据您使用 Slint 的编程语言进行选择。
# 在Rust中选择并加载翻译文件
首先,启用 `slint create``gettext `功能来访问翻译 API 并激活运行时翻译支持。
接下来,使用 `slint::init_translations`指定 `.mo` 文件的基本位置。这是上一节方案中的 dir_name。 .mo 文件应位于相应的子目录中,并且它们的文件名 - 域名 - 必须与 Cargo.toml 中的包名称匹配。这通常与crate名称相同。
举个🌰:
```Rust
slint::init_translations!(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/"));
```
假设您的 Cargo.toml 包含以下行,并且用户的区域设置为 fr
```toml
[package]
name = "gallery"
```
通过这些设置Slint 将在 lang/fr/LC_MESSAGES/gallery.mo 中查找 gallery.mo。
# 在C++中选择并加载翻译文件
首先,在编译 Slint 时启用 `SLINT_FEATURE_GETTEXT` cmake 选项,以访问翻译 API 并激活运行时翻译支持。
在C++应用中使用CMake用`domain_name`作为cmake目标名称
接下来,使用标准 gettext 库将文本域绑定到路径。
```CMake
find_package(Intl)
if(Intl_FOUND)
target_compile_definitions(gallery PRIVATE HAVE_GETTEXT SRC_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
target_link_libraries(gallery PRIVATE Intl::Intl)
endif()
```
(可以通过vcpkg安装第三方库非常的方便)
然后可以设置区域设置和文本域
```C++
#ifdef HAVE_GETTEXT
# include <locale>
# include <libintl.h>
#endif
int main()
{
#ifdef HAVE_GETTEXT
bindtextdomain("my_application", SRC_DIR "/lang/");
std::locale::global(std::locale(""));
#endif
//...
}
```
假设您正在使用上述内容,并且用户的区域设置设置为 frSlint 将在 lang/fr/LC_MESSAGES/gallery.mo 中查找 gallery.mo。
# 使用 slint-viewer 预览翻译
预览` .slint` 文件时使用 `slint-viewer `预览翻译:
1. 启用`gettext`功能在编译slint-viewer时
2. 使用`--translation-domain`和`translation-dir`选项加载并展示本地化翻译文件,语言的选择基于当前系统设定的语言。

View File

@ -1,249 +0,0 @@
---
title: Slint DSL 类型
date: 2024-01-10 13:58:41
tags:
- Slint
---
# 注释
Slint支持C类风格的注释
1. 使用两个斜杠(`//`) 的方式注释此行中在//之后的所有内容
2. 块注释(`/* ... */ `) 注释处于`/*` 到 `*/`之间的所有内容
例:
```Slint
component MyRectangle inherits Rectangle{ // 这是一个注释
/*
这是一个注释
这也是一个注释
*/
}
```
# 标识符
标识符可以由字母 `(a-zA-Z)`、数字` (0-9)`、下划线` (_) `或破折号 `(-)` 组成。它们**不能以数字或破折号开头**但可以以下划线开头下划线被标准化为破折号。这意味着这两个标识符是相同的foo_bar 和 foo-bar。
```Slint
hello_world // ok
hello-world // ok
helloWorld // ok
HelloWorld // ok
_hello_world // ok
123Apple // error
-apple // error
```
# 类型
在Slint中所有属性都是具有类型的下表展示了Slint中的基本类型
|类型 |描述 |默认值 |
|---|---|---|
|`angle`|角度单位,对应于文字如 90deg、1.2rad、0.25turn |0deg|
|`bool`|布尔值,`true`和`false` |false|
|`brush`|画笔是一种特殊类型,可以从颜色或渐变规范初始化。有关详细信息,请参阅颜色和画笔部分。 [Colors and Brushes Section](https://slint.dev/releases/1.3.2/docs/slint/src/language/syntax/types#colors-and-brushes) |transparent|
|`color`|具有 Alpha 通道的 RGB 颜色,每个通道具有 8 位精度。支持 CSS 颜色名称以及十六进制颜色编码,例如 `#RRGGBBAA` 或` #RGB`。 |transparent|
|`duration`|输入动画的持续时间。 ms毫秒或 s等后缀用于指示精度。 |0ms|
|`easing`|属性动画允许指定缓动曲线。有效值是线性的值是线性插值的CSS 中已知四个常见的立方贝塞尔函数:`ease`、`ease_in`、`ease_in_out`、`ease_out`。<br>[four common cubiz-bezier functions known from CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function#Keywords_for_common_cubic-bezier_easing_functions) |linear|
|`float`|有符号的 32 位浮点数。带有 % 后缀的数字会自动除以 100因此例如 30% 等于 0.30。 |0|
|`image`|对图像的引用可以使用 @image-url("...") 构造进行初始化 |empty image|
|`int`|带符号的整数。 |0|
|`length`|用于 x、y、宽度和高度坐标的类型。对应于 1px、1pt、1in、1mm 或 1cm 等文字。如果绑定在可以访问设备像素比的上下文中运行,则可以将其与长度进行转换。 |0px|
|`percent`|有符号的 32 位浮点数,可以理解为百分比。分配给该类型属性的文字数字必须带有 % 后缀。 |0%|
|`physical-length`|这是物理像素的数量。要将整数转换为长度单位,只需乘以 1px 即可。或者要将长度转换为浮点数,可以除以 1phx。 |0phx|
|`relative-font-size`|相对字体大小系数,与 `Window.default-font-size` 相乘,可以转换为长度。 |0rem|
|`string`|UTF-8 编码、引用计数字符串。 |`""`|
## 字符串
任何一个使用utf8编码字符组成的系列都可以称为一个字符串(`string`) 比如:"foo"
转义序列可以嵌入到字符串中以插入难以直接插入的字符(就是很难直接打出来的字符):
| 转移字符 | 结果 |
| :--- | :--- |
| `\"` | `"` |
| `\\` | `\` |
| `\n` | 换到新一行 |
| `\u{x}` | 其中 x 是一个十六进制数字,扩展为该数字表示的 unicode 代码点 |
| `\{expression}` | 表达式的求值结果 |
**非转义字符 \ 后面的任何其他内容都是错误。**
```Slint
export component Example inherits Text {
text: "hello";
}
```
**注意** 这种`\{...}`的语法在Rust语言中的`slint!`宏中使用是无效的
## 颜色和笔刷(画笔)
颜色文字遵循 CSS 语法:
```Slint
export component Example inherits Window {
background: blue;
property<color> c1: #ffaaff;
property<brush> b2: Colors.red;
}
```
除了纯色之外许多元素都有类型为brush而不是color的属性。画笔是一种可以是颜色也可以是渐变的类型。然后使用画笔填充元素或绘制轮廓。
CSS颜色名称仅在类型Color或brush表达式的作用域内。否则您可以从colors名称空间访问颜色。
### 方法
所以的`colors`和`brushed`遵从以下方法的定义:
**`brighter(factor: float) -> brush`**
返回从该颜色派生的新颜色但其亮度增加指定的因子。例如如果因子为0.5(或例如50%)则返回的颜色要亮50%。负面因素会降低亮度。
**`darker(factor: float) -> brush`**
返回从该颜色派生的新颜色但其亮度降低指定的因子。例如如果因子为0.5(或例如50%)则返回的颜色暗50%。负面因素增加了亮度。
**`mix(other: brush, factor: float) -> brush`**
返回一种新颜色,它是这种颜色和其他颜色的混合,混合的比例由参数`factor`决定(将被限制在0.0和1.0之间)。
**`transparentize(factor: float) -> brush`**
返回不透明度降低的新颜色。通过将alpha通道乘以(1 -`factor`)获得透明度。
**`with_alpha(alpha: float) -> brush`**
返回一个新的颜色alpha值设置为alpha(介于0和1之间)
### 线性渐变
线性梯度描述光滑、彩色的表面。它们是用一个角度和一系列颜色点来指定的。颜色将在止光点之间线性内插,与以指定角度旋转的假想线对齐。这被称为线性梯度,并使用带有以下签名的`@linear-gradient`宏指定:
**`@linear-gradient(angle, color percentage, color percentage, ...)`**
宏的第一个参数是一个角度(参见类型)。梯度线的起始点将以指定的值旋转。
在初始角度之后是一个或多个颜色停止,描述为一个颜色值和百分比的空格分隔对。颜色指定线性颜色插值在沿梯度轴的指定百分比处应达到的值。
下面的例子显示了一个矩形,填充了一个线性渐变,以浅蓝色开始,在中心插入一个非常浅的阴影,并以橙色色调结束:
```Slint
export component Example inherits Window {
preferred-width: 100px;
preferred-height: 100px;
Rectangle {
background: @linear-gradient(90deg, #3f87a6 0%, #ebf8e1 50%, #f69d3c 100%);
}
}
```
### 径向渐变
线性渐变就像真正的渐变,但颜色是在一个圆内插入而不是沿着一条线。要描述一个径向渐变,使用以下签名`@radial-gradient`宏:
**`@radial-gradient(circle, color percentage, color percentage ...) `**
该宏的第一个参数总是circle因为只支持圆形渐变。
语法是基于CSS `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%);
}
}
```
## 图片
图像类型是对图像的引用。它是使用 `@image-url("...")` 构造定义的。` @image-url` 函数中的地址必须在编译时已知。
Slint 在以下位置查找图像:
- 绝对路径或相对于当前 .slint 文件的路径。
- 编译器用来查找 .slint 文件的包含路径。
使用图像的宽度和高度属性访问图像的尺寸。
```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");
Text {
text: "The image is " + some_image.width + "x" + some_image.height;
}
}
```
## 结构体
使用关键字`struct`来定义结构体
```Slint
export struct Player {
name: string,
score: int,
}
export component Example {
in-out property<Player> player: { name: "Foo", score: 100 };
}
```
结构体的默认值是通过将其所有字段设置为其默认值来初始化的。
### 匿名结构体
使用 `{identifier1: type2,identifier1:type2 } `语法声明匿名结构,并使用 `{identifier1: expression1,identifier2: expression2 } `对其进行初始化。
```Slint
export component Example {
in-out property<{name: string, score: int}> player: { name: "Foo", score: 100 };
in-out property<{a: int, }> foo: { a: 3 };
}
```
## 枚举类型
使用关键字`enum`定义枚举类型
```Slint
export enum CardSuit { clubs, diamonds, hearts, spade }
export component Example {
in-out property<CardSuit> card: spade;
out property<bool> is-clubs: card == CardSuit.clubs;
}
```
枚举值可以通过使用枚举的名称和值的名称,中间用点分开来引用。 (例如CardSuit.spade)
在该枚举类型的绑定中,或者如果回调函数的返回值是该枚举,则可以省略枚举的名称。
每个枚举类型的默认值总是第一个值。
## 数组和模型
数组是通过将数组元素的类型括在` [` 和 `]` 方括号中来声明的。
数组文字以及保存数组的属性充当 for 表达式中的模型。
```Slint
export component Example {
in-out property<[int]> list-of-int: [1,2,3];
in-out property<[{a: int, b: string}]> list-of-structs: [{ a: 1, b: "hello" }, {a: 2, b: "world"}];
}
```
数组定义了以下操作:
`array.length`:可以使用内置的 .length 属性查询数组和模型的长度。
`array[index]`:索引运算符检索数组的各个元素。
对数组的越界访问将返回默认构造的值。
```Slint
export component Example {
in-out property<[int]> list-of-int: [1,2,3];
out property <int> list-len: list-of-int.length;
out property <int> first-int: list-of-int[0];
}
```
## 类型转换
Slint支持不同类型之间的转换。为了使UI描述更健壮需要显式转换但是为了方便在某些类型之间允许隐式转换。
可以进行以下转换:
- Int可以隐式地转换为float反之亦然
- Int和float可以隐式转换为string
- 物理长度和长度只能在像素比已知的情况下隐式地相互转换。
- 单位类型(长度、物理长度、持续时间等)不能转换为数字(float或int)但它们可以自己除以得到一个数字。同样一个数字可以乘以这些单位中的一个。这个想法是一个人将乘以1px或除以1px来进行这样的转换
- 字面值0可以转换为具有相关单位的任何这些类型。
- 如果结构类型具有相同的属性名,并且它们的类型可以转换,那么它们将与另一个结构类型转换。源结构可以有缺失的属性,也可以有额外的属性。但不是两者都有。
- 数组通常不会相互转换。如果元素类型是可转换的,则可以转换数组字面值。
- 使用to-float函数可以将String转换为float。如果字符串不是一个有效的数字该函数返回0。您可以使用is-float()检查字符串是否包含有效数字
```Slint
export component Example {
// OK: int converts to string
property<{a: string, b: int}> prop1: {a: 12, b: 12 };
// OK: even if a is missing, it will just have the default value ("")
property<{a: string, b: int}> prop2: { b: 12 };
// OK: even if c is too many, it will be discarded
property<{a: string, b: int}> prop3: { a: "x", b: 12, c: 42 };
// ERROR: b is missing and c is extra, this doesn't compile, because it could be a typo.
// property<{a: string, b: int}> prop4: { a: "x", c: 42 };
property<string> xxx: "42.1";
property<float> xxx1: xxx.to-float(); // 42.1
property<bool> xxx2: xxx.is-float(); // true
}
```

View File

@ -1,186 +0,0 @@
---
title: Slint 属性
date: 2024-01-11 09:57:49
tags:
- Slint
---
# Slint 属性
所有元素均有属性。内置元素具有常见特性,如颜色或尺寸特性。你可以为它们设定一个值或者一个完整的表达式。
```Slint
export component Example inherits Window {
// 简单表达式:以分号结尾
width: 42px;
// 或者用一个代码块包裹,这样就没有分号了
height: { 42px }
}
```
***一股浓郁的Rust语法味道扑面而来***
属性的默认值一般是属性的类型的默认值,比如说布尔的默认是`false`,整数`int`的默认值是`0`。
除了现有属性外,还可以通过指定名称、类型和默认值(可选)来定义额外的属性:
```Slint
export component Example {
// 定义了一个叫做my-property的int类型的扩展属性
property<int> my-property;
// 定义了一个叫做my-second-property的int类型的属性并设置其默认值为42
property<int> my-second-property: 42;
}
```
用限定符注释额外的属性,指定如何读取和写入属性:
- `private` :默认为此,属性仅能在当前组件内被访问
- `in`:这个属性能被输入,它可以由该组件的用户设置和修改,例如通过绑定或回调中的赋值。组件可以提供默认绑定,但不能通过赋值覆盖它
- `out`:只能由组件设置的输出属性。对于组件的用户来说,它是只读的。
- `in-out`:任何人都可以对此属性进行读写
```Slint
export component Button {
// 这意味着通过用户设置组件
in property <string> text;
// 表明了该属性将由组件的用户读取。
out property <bool> pressed;
// 此属性意味着用户和组件本身都可以更改。
in-out property <bool> checked;
// 此属性是该组件的内部属性。
private property <bool> has-mouse;
}
```
当使用组件作为元素时,或者通过业务逻辑的语言绑定,可以从外部访问在组件顶层声明的所有非私有属性。
# 绑定
当表达式中访问的属性发生更改时,会自动重新评估绑定表达式。
在以下示例中,当用户按下按钮时,按钮的文本会自动更改。增加计数器属性会自动使绑定到文本的表达式无效并触发重新计算。
```Slint
import { Button } from "std-widgets.slint";
export component Example inherits Window {
preferred-width: 50px;
preferred-height: 50px;
Button {
property <int> counter: 3;
clicked => { self.counter += 3 }
text: self.counter * 2;
}
}
```
在查询属性时惰性地进行重新计算。
在内部,在计算绑定时访问的任何属性都要注册依赖项。当属性更改时,会通知依赖项,并将所有依赖绑定标记为脏绑定。***(脏绑定是由于其所依赖的某个属性发生更改而被标记为无效的绑定。当查询属性时,脏绑定将被重新计算)***
默认情况下,本机代码中的回调不依赖于任何属性,除非它们查询本机代码中的属性。
## 双向绑定
使用<=>语法在属性之间创建双向绑定。这些属性将被链接在一起,并且总是包含相同的值。
<=>的右侧必须是对同一类型属性的引用。对于双向绑定,属性类型是可选的,如果没有指定,它将被推断出来。
```Slint
export component Example {
in property<brush> 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;
height: parent.height;
background: blue;
}
}
```
## 相对长度
有时用相对百分比来表示长度属性之间的关系是很方便的。例如,下面的内部蓝色矩形的大小是外部绿色窗口的一半
```Slint
export component Example inherits Window {
preferred-width: 100px;
preferred-height: 100px;
background: green;
Rectangle {
background: blue;
width: parent.width * 50%;
height: parent.height * 50%;
}
}
```
这种以百分比表示父元素同名属性的宽度或高度的模式很常见。为了方便起见,这里有一种简写的语法:
- 属性是`width`或者`height`
- 绑定的表达式求值是百分比
如果满足这些条件那么就没有必要指定parent属性而是可以简单地使用百分比。前面的例子如下所示:
```Slint
export component Example inherits Window {
preferred-width: 100px;
preferred-height: 100px;
background: green;
Rectangle {
background: blue;
width: 50%;
height: 50%;
}
}
```
## 示例
```Slint
import { LineEdit, Button } from "std-widgets.slint";
component InputWithLabel inherits HorizontalLayout{
in property <string> label_str;
in-out property <string> intput_src <=> input.text;
spacing: 2px;
Rectangle {
border-color: grey;
border-width: 2px;
border-radius: 5px;
Text{
text: label-str;
font-size: 14px;
}
}
Rectangle {
border-color: grey;
border-width: 2px;
border-radius: 5px;
input := LineEdit {
font-size: 14px;
input-type: number;
}
}
}
export component MainWindow inherits Window {
preferred-height: 480px;
preferred-width: 640px;
VerticalLayout {
spacing: 2px;
alignment: start;
input1 := InputWithLabel {
label-str: "number 1";
}
input2 := InputWithLabel {
label-str: "number 2";
}
VerticalLayout {
Button {
text: "sum";
clicked => {
result.text = add(input1.intput_src.to-float(), input2.intput_src.to-float());
}
}
result := TextInput{
enabled: false;
}
}
}
pure function add(a: int, b: int) -> int {
return a + b;
}
}
```

View File

@ -1,56 +0,0 @@
---
title: Slint 表达式
date: 2024-01-11 11:18:07
tags:
- Slint
---
# Slint 表达式
表达式是在用户界面中声明关系和连接的强大方式。它们通常用于将基本算术与访问其他元素的属性结合起来。当这些属性发生变化时,表达式会自动重新求值,并为与该表达式关联的属性赋一个新值:
```Slint
export component Example {
// declare a property of type int
in-out property<int> my-property;
// This accesses the property
width: root.my-property * 20px;
}
```
当`my-property`改变时,宽度也会自动改变
数字表达式中的算术运算与大多数编程语言中的操作符*、+、-、/类似:
```Slint
export component Example {
in-out property <int> p: 1 * 2 + 3 * 4; // same as (1 * 2) + (3 * 4)
}
```
用`+`串联字符串。
运算符&&和||表示布尔值之间的逻辑与或。操作符`==`、`!=`、`>`、`<`、`>=`和`<=`比较相同类型的值。
访问元素的属性,方法是使用元素的名称,后跟一个“`.`属性名”:
```Slint
export component Example {
foo := Rectangle {
x: 42px;
}
x: foo.x;
}
```
三目运算符`expression : expression ? expression` 在slint中也是被支持的就像C语言和JavaScript中一样
```Slint
export component Example inherits Window {
preferred-width: 100px;
preferred-height: 100px;
Rectangle {
touch := TouchArea {}
background: touch.pressed ? #111 : #eee;
border-width: 5px;
border-color: !touch.enabled ? #888
: touch.pressed ? #aaa
: #555;
}
}
```

View File

@ -1,37 +0,0 @@
---
title: Slint 函数
date: 2024-01-12 10:30:07
tags:
- Slint
---
# Slint 函数
在slint中定义一个函数需要使用到`function`关键字
函数可以在括号中添加参数,参数需要遵循`函数名:类型`的格式。这些参数可以通过函数体内的名称来引用。
函数也可以返回一个值,返回的类型需要使用`->`符号在函数中标明。
`function 函数名称(参数1: 类型) -> 返回类型`
`return `关键字在函数体内使用以返回声明类型的表达式。如果函数没有显式返回值则默认返回最后一条语句的值。这一点和Rust的函数语法很像
函数可以用 `pure` 关键字注释。这表明该功能不会引起任何副作用。更多详细信息可以在“纯度”章节中找到。
默认情况下,函数是私有的,无法从外部组件访问。但是,可以使用 `public``protected` 关键字修改它们的可访问性。
- 用 `public` 注解的函数可以被任何组件访问。
- 用 `protected` 注解的函数只能被直接继承它的组件访问。
## 例子
```Slint
export component Example {
in-out property <int> min;
in-out property <int> 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));
}
}
```
在上面的示例中set-bounds 是一个受保护的函数,用于更新根组件的 min 和 max 属性。入站函数是一个公共纯函数,它接受整数 x 并返回限制在最小和最大边界内的值。

View File

@ -1,51 +0,0 @@
---
title: Slint 消息回调
date: 2024-01-12 12:09:49
tags:
- Slint
---
# 消息回调
组件能够定义回调以和外界交流改变的状态信息。回调是通过“调用”它们来调用的,就像调用函数一样。
***个人的理解消息回调类似于Qt中常用的信号槽之槽函数。***
您可以通过使用 => 箭头语法声明处理程序来对回调调用做出反应。内置的 TouchArea 元素声明一个 clicked 回调当用户触摸该元素覆盖的矩形区域或用鼠标单击该区域时会调用该回调。在下面的示例中通过声明处理程序并调用我们的自定义回调将该回调的调用转发到另一个自定义回调hello
```Slint
export component Example inherits Rectangle {
// declare a callback
callback hello;
area := TouchArea {
// sets a handler with `=>`
clicked => {
// emit the callback
root.hello()
}
}
}
```
可以向回调添加参数:
```Slint
export component Example inherits Rectangle {
// declares a callback
callback hello(int, string);
hello(aa, bb) => { /* ... */ }
}
```
回调也可能返回一个值:
```Slint
export component Example inherits Rectangle {
// declares a callback with a return value
callback hello(int, int) -> int;
hello(aa, bb) => { aa + bb }
}
```
# 别名
可以用与双向绑定类似的方式声明回调别名:
```Slint
export component Example inherits Rectangle {
callback clicked <=> area.clicked;
area := TouchArea {}
}
```

View File

@ -1,40 +0,0 @@
---
title: Slint 语句statements
date: 2024-01-13 10:36:05
tags:
- Slint
---
# Slint Statements
在编程中,表达式是值、变量、操作符和函数调用的组合,其计算结果为单个值。例如,' 2 + 3 '是一个求值为' 5 '的表达式。表达式可以用作较大表达式的一部分,也可以用作函数的参数。
另一方面,语句是执行一个操作的完整代码行。语句可以包括表达式,但也可以包括关键字、循环、条件和其他编程结构。例如,' if (x > 0) {y = 1;}是一个检查' x '是否大于' 0 '的语句,如果大于' 0 ',则将' y '设置为' 1 '。
表达式和语句之间的主要区别在于表达式的计算结果是一个值,而语句执行一个操作。表达式可以用作语句的一部分,但语句不能用作表达式的一部分。
---
回调函数能够包含复杂的语句:
赋值:`clicked => { some-property = 42; }`
自赋值运算:`clicked => { some-property += 42; }`
调用一个回调函数:`clicked => { root.some-callback(); }`
条件语句:
```Slint
clicked => {
if (condition) {
foo = 42;
} else if (other-condition) {
bar = 28;
} else {
foo = 4;
}
}
```
空表达式:
```Slint
clicked => {}
clicked => {;}
```

View File

@ -1,47 +0,0 @@
---
title: Slint 重复repetition
date: 2024-01-13 12:25:35
tags:
- Slint
---
# Slint Repetition
使用 `for in`语句可以多次创建同一元素
语法看起来长这个样子:`for name[index] in model : id := Element { ... }
model 能够是以下类型:
- 一个整数,在这种情况下该元素将重复指定的次数
- 原生声明的数组类型或模型,在这种情况下,将为数组或模型中的每个元素实例化该元素。
该名称可用于在元素内查找,并且将类似于设置为模型值的伪属性。索引是可选的,将设置为模型中该元素的索引。 id 也是可选的。
# 示例
```Slint
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;
}
}
```
创建了一个`color`类型的数组`[ #e11, #1a2, #23d ]`,对它进行遍历,`index`的内容就会从0到2, my-color的颜色就会从`#e11, #1a2, #23d`进行选择。
```Slint
export component Example inherits Window {
preferred-width: 50px;
preferred-height: 50px;
in property <[{foo: string, col: color}]> model: [
{foo: "abc", col: #f00 },
{foo: "def", col: #00f },
];
VerticalLayout {
for data in root.model: my-repeated-text := Text {
color: data.col;
text: data.foo;
}
}
}
```

View File

@ -1,39 +0,0 @@
---
title: Slint 条件元素
date: 2024-01-13 13:43:59
tags:
- Slint
---
# Slint 条件元素
仅当给定条件为 true 时if 构造才会实例化元素。语法为 if 条件 : id := Element { ... }
***这东西让我有一种看rust里 if let的感觉***
```Slint
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 {}
}
```
推荐if语句从右往左读然后拆一下紧密布局的代码
```Slint
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 {}
}
```
效果就是有一个红色的矩形点击的时候就成了蓝色markdown里展示效果不太理想这里贴上原文链接
https://slint.dev/releases/1.3.2/docs/slint/src/language/syntax/conditions

View File

@ -1,73 +0,0 @@
---
title: Slint 动画效果
date: 2024-01-14 12:09:22
tags:
- Slint
---
# Slint 动画效果
定义具有动画效果的属性需要使用`animate`关键字,就像这样:
```Slint
export component Example inherits Window {
preferred-width: 100px;
preferred-height: 100px;
background: area.pressed ? blue : red;
animate background {
duration: 250ms;
}
area := TouchArea {}
}
```
效果是当鼠标点击窗口背景颜色会从红色变成蓝色名变化的过程为250毫秒
使用以下参数微调动画:
- `delay`:在动画开始前的等待时间。
- `duration`:动画完成所需要用到的时间。
- `iteration-count`:动画应运行的次数。负值指定无限重新运行。分形值是可能的。对于永久运行的动画,请参阅[`animation-tick()`](https://slint.dev/releases/1.3.2/docs/slint/src/language/builtins/functions.html#animation-tick-duration)。
- `easing`:可以是下方任意一个,从[`easings.net`](https://easings.net/)网站可以查看视觉效果。
- `linear`
- `ease-in-quad`
- `ease-out-quad`
- `ease-in-out-quad`
- `ease`
- `ease-in`
- `ease-out`
- `ease-in-out`
- `ease-in-quart`
- `ease-out-quart`
- `ease-in-out-quart`
- `ease-in-quint`
- `ease-out-quint`
- `ease-in-out-quint`
- `ease-in-expo`
- `ease-out-expo`
- `ease-in-out-expo`
- `ease-in-sine`
- `ease-out-sine`
- `ease-in-out-sine`
- `ease-in-back`
- `ease-out-back`
- `ease-in-out-back`
- `ease-in-circ`
- `ease-out-circ`
- `ease-in-out-circ`
- `ease-in-elastic`
- `ease-out-elastic`
- `ease-in-out-elastic`
- `ease-in-bounce`
- `ease-out-bounce`
- `ease-in-out-bounce`
- `cubic-bezier(a, b, c, d)`
还可以在图库示例的“缓动”选项卡上找到缓动示例。
---
还可以使用相同的动画为多个属性设置动画,比如这样:
`animate x, y { duration: 100ms; easing: ease-out-bounce; }`
这样编写也可以达到一样的效果:
```Slint
animate x { duration: 100ms; easing: ease-out-bounce; }
animate y { duration: 100ms; easing: ease-out-bounce; }
```

View File

@ -1,69 +0,0 @@
---
title: Slint Stats语句
date: 2024-01-14 13:02:43
tags:
- Slint
---
# Slint States
states 语句允许一次性声明状态并设置多个元素的属性:
```Slint
export component Example inherits Window {
preferred-width: 100px;
preferred-height: 100px;
default-font-size: 24px;
label := Text { }
ta := TouchArea {
clicked => {
active = !active;
}
}
property <bool> active: true;
states [
active when active && !ta.has-hover: {
label.text: "Active";
root.background: blue;
}
active-hover when active && ta.has-hover: {
label.text: "Active\nHover";
root.background: green;
}
inactive when !active: {
label.text: "Inactive";
root.background: gray;
}
]
}
```
在此示例中,活动和活动悬停状态是根据活动布尔属性的值和 TouchArea 的 has-hover 来定义的。当用户将鼠标悬停在示例上时,它将在蓝色和绿色背景之间切换,并相应地调整文本标签。单击可切换活动属性,从而进入非活动状态。
# Transitions
转换将动画绑定到状态更改
此示例定义了两个转换。首先out 关键字用于在离开禁用状态时为所有属性设置 800 毫秒的动画。第二个转换使用 in 关键字在转换到按下状态时对背景进行动画处理。
```Slint
export component Example inherits Window {
preferred-width: 100px;
preferred-height: 100px;
text := Text { text: "hello"; }
in-out property<bool> pressed;
in-out property<bool> is-enabled;
states [
disabled when !root.is-enabled : {
background: gray; // same as root.background: gray;
text.color: white;
out {
animate * { duration: 800ms; }
}
}
down when pressed : {
background: blue;
in {
animate background { duration: 300ms; }
}
}
]
}
```

View File

@ -1,89 +0,0 @@
---
title: Slint 全局单例
date: 2024-01-15 17:40:01
tags:
- Slint
---
# Slint 全局单例
定义一个全局单例的实例需要使用到`global Name { /*各种属性和回调函数*/} `的方式,以使属性和回调在整个项目中可用。使用 Name.property 访问它们。
```Slint
global Palette {
in-out property<color> primary: blue;
in-out property<color> secondary: green;
}
export component Example inherits Rectangle {
background: Palette.primary;
border-color: Palette.secondary;
border-width: 2px;
}
```
导出全局以使其可从其他文件访问(请参阅模块[Modules](https://slint.dev/releases/1.3.2/docs/slint/src/language/syntax/modules.html))。从文件中导出全局变量,同时导出主应用程序组件,以使其对业务逻辑中的本机代码可见。
```Slint
export global Logic {
in-out property <int> the-value;
pure callback magic-operation(int) -> int;
}
```
**在Rust中的使用方式**
```Rust
slint::slint!{
export global Logic {
in-out property <int> the-value;
pure callback magic-operation(int) -> int;
}
export component App inherits Window {
// ...
}
}
fn main() {
let app = App::new();
app.global::<Logic>().on_magic_operation(|value| {
eprintln!("magic operation input: {}", value);
value * 2
});
app.global::<Logic>().set_the_value(42);
// ...
}
```
**在C++中的使用方式**
```C++
#include "app.h"
fn main() {
auto app = App::create();
app->global<Logic>().on_magic_operation([](int value) -> int {
return value * 2;
});
app->global<Logic>().set_the_value(42);
// ...
}
```
可以使用双向绑定语法从全局重新公开回调或属性。
```Slint
global Logic {
in-out property <int> the-value;
pure callback magic-operation(int) -> int;
}
component SomeComponent inherits Text {
// use the global in any component
text: "The magic value is:" + Logic.magic-operation(42);
}
export component MainWindow inherits Window {
// re-expose the global properties such that the native code
// can access or modify them
in-out property the-value <=> Logic.the-value;
pure callback magic-operation <=> Logic.magic-operation;
SomeComponent {}
}
```

View File

@ -1,108 +0,0 @@
---
title: Slint 模块
date: 2024-01-15 17:58:12
tags:
- Slint
---
# Slint 模块
定义在`.slint`文件用的组件能够作为一个元素被其他`.slint`文件使用,也就是说可以被导出或者导入
在一般情况下,每一个被定义在`.slint`文件中的类型都是私有的,使用`export`属性可以改变。
```Slint
component ButtonHelper inherits Rectangle {
// ...
}
component Button inherits Rectangle {
// ...
ButtonHelper {
// ...
}
}
export { Button }
```
在这个例子中,`Button`能够被其他`.slint`文件访问,但是`ButtonHelper`不可以
也可以仅出于导出目的更改名称,而不影响其内部使用:
```Slint
component Button inherits Rectangle {
// ...
}
export { Button as ColorButton }
```
在这里例子中,`Button`不再能够被其他`.slint`文件访问到了,取而代之的是`ColorButton`这个名字
为了方便起见,导出组件的第三种方法是立即声明它已导出:
```Slint
export component Button inherits Rectangle {
// ...
}
```
同样,可以导入从其他文件导出的组件:
```Slint
import { Button } from "./button.slint";
export component App inherits Rectangle {
// ...
Button {
// ...
}
}
```
如果两个文件以相同的名称导出类型,则您可以选择在导入时分配不同的名称:
```Sint
import { Button } from "./button.slint";
import { Button as CoolButton } from "../other_theme/button.slint";
export component App inherits Rectangle {
// ...
CoolButton {} // from other_theme/button.slint
Button {} // from button.slint
}
```
元素,全局单例以及结构体都能够被导入和导出。
还可以导出从其他文件导入的全局变量(请参阅全局单例):
```Slint
import { Logic as MathLogic } from "math.slint";
export { MathLogic } // known as "MathLogic" when using native APIs to access globals
```
# 模块语法
导入类型支持以下语法:
```Slint
import { export1 } from "module.slint";
import { export1, export2 } from "module.slint";
import { export1 as alias1 } from "module.slint";
import { export1, export2 as alias2, /* ... */ } from "module.slint";
```
导出类型支持以下语法:
```Slint
// Export declarations
export component MyButton inherits Rectangle { /* ... */ }
// Export lists
component MySwitch inherits Rectangle { /* ... */ }
export { MySwitch };
export { MySwitch as Alias1, MyButton as Alias2 };
// Re-export all types from other module
export * from "other_module.slint";
```
# 组件库
将代码库拆分为单独的模块文件可以促进重用,并通过允许您隐藏帮助器组件来改进封装。这在项目自己的目录结构中效果很好。要在项目之间共享组件库而不对其相对路径进行硬编码,请使用组件库语法:
```Slint
import { MySwitch } from "@mylibrary";
```
在上面的示例中MySwitch 组件将从名为“mylibrary”的组件库中导入。该库的路径必须在编译时单独定义。使用以下方法之一帮助 Slint 编译器将“mylibrary”解析为磁盘上的正确路径
- 当使用Rust语言并存在`build.rs`文件,调用[`with_library_paths`](https://slint.dev/releases/1.3.2/docs/rust/slint_build/struct.CompilerConfiguration)来提供从库名称到路径的映射。
- 当在命令行中使用`slint-viewer`时,附加参数`-Lmylibrary=/path/to/my/library`为每一个组件库
- 在 VS 代码扩展中使用实时预览时,请使用`Slint: Library Paths`设置配置 Slint 扩展的库路径。

View File

@ -1,18 +0,0 @@
---
title: Slint 过时语法
date: 2024-01-27 08:40:51
tags:
- Slint
---
# Slint 过时语法
为了维护对早期版本的兼容性在1.0版本之前定义组件的语法`:=`目前也是支持的:
```Slint
export MyApp := Window {
//...
}
```
此语法更改还会影响属性查找规则和默认元素放置。
在新语法中定义的组件中,只有在组件内声明的属性才在范围内。默认情况下,父元素将其子元素呈现为居中,并将应用所有布局约束。
在使用旧语法定义的组件中,除了组件本身内部定义的所有属性之外, `self``root` 的基础的所有属性都在范围内。元素放置在位置 `x: 0` 和` y: 0` 处,并且不应用它们的约束。