柚子快報(bào)激活碼778899分享:slint ui學(xué)習(xí)筆記
柚子快報(bào)激活碼778899分享:slint ui學(xué)習(xí)筆記
slint學(xué)習(xí)筆記
slint是一個(gè)類似qml的標(biāo)記語言(xml/css之類方便界面設(shè)計(jì)的語言),經(jīng)過編譯器slint compile(類似QT的moc/uic/rcc工具)可完整的轉(zhuǎn)換成Cpp或者Rust。 其開發(fā)方式類似qml+cpp,這得益于slint ui的兩位初始創(chuàng)建人來自QT團(tuán)隊(duì)。
與qt的qml相比,slint有幾個(gè)優(yōu)點(diǎn):
全slint代碼轉(zhuǎn)換成本地語言原生多本地語言支持(Rust/Cpp/NodeJs)無歷史包袱開源協(xié)議(手機(jī)和嵌入式收費(fèi))
slint 優(yōu)點(diǎn)
流暢:平滑,觸摸友好的用戶接口跨平臺:目標(biāo)平臺包括嵌入式設(shè)備和桌面應(yīng)用軟件(手機(jī)和網(wǎng)頁)多語言:可以使用自己擅長的語言API(C++,Rust,JavaScript)
許可協(xié)議
GPLv3 + 商業(yè)
1.1版本以后: 許可證變更:新增更寬松的免版稅許可證 除了 GPLv3 和專有商業(yè)許可,此版本添加了新的免版稅許可作為第三個(gè)選項(xiàng),該許可證可免費(fèi)用于構(gòu)建桌面或 Web 應(yīng)用程序,并消除了 Copyleft 許可證的限制。 所有示例、教程中的示例代碼等現(xiàn)在都可以在寬松的 MIT 許可證下使用。這可以在應(yīng)用程序中自由復(fù)制、修改和使用代碼,而不受任何 Copyleft 條款的限制。 簡化了 CLA 協(xié)議,所有貢獻(xiàn)現(xiàn)在均在 MIT 無署名許可證下實(shí)現(xiàn),沒有版權(quán)限制。
https://github.com/slint-ui/slint/blob/release/1.3/LICENSES/LicenseRef-Slint-Royalty-free-1.1.md
個(gè)人結(jié)論
思路很好,做UI感受很不錯(cuò)(IDE+預(yù)覽)。 有種LVGL Pro的感覺,對于簡單UI的程序,完全夠用。對于復(fù)雜UI缺失內(nèi)容太多。 支持多種前端和后端,支持很廣泛,點(diǎn)贊。 支持嵌入式設(shè)備,點(diǎn)贊?。ㄊ召M(fèi)問題很坑)
值得入手學(xué)習(xí)一下,作為小工具語言。(替代flutter) 如果做商業(yè),用在嵌入式領(lǐng)域rust+slint還可以。(如果不用rust,可以完全使用LVGL替代)
所以,以語言為導(dǎo)向,rust系,推薦。c++系,不推薦。
基礎(chǔ)用法
// Explicit positioning
export component Example inherits Window {
width: 200px;
height: 200px;
Rectangle {
x: 100px;
y: 70px;
width: parent.width - self.x; // 動(dòng)態(tài)計(jì)算
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循環(huán)
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; }
}
}
常規(guī)屬性:
px像素, phx物理像素(考慮縮放)preferred-width/preferred-height: 優(yōu)先的size,不指定時(shí)由子元素決定
如果制定了 width、height 那么大小就不可變了horizontal-stretch、vertical-stretch 非零時(shí),表示拉伸 VerticalLayout / HorizontalLayout / GridLayout:布局,默認(rèn)子元素拉伸padding/padding-left/padding-right/padding-top/bottom: 子元素與layout之間的空白spacing: layout內(nèi)子元素之間的空白alignment: stretch/start/end/center/space-between/space-around
容器(可重用組件)
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; }
}
}
高階用法
多國語言參考 https://slint.dev/releases/1.3.0/docs/slint/src/language/concepts/translations
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"; // 默認(rèn)字體
GridLayout {
Button {
text: "press me";
clicked => { label.focus(); } // 組件的事件
}
// 為組件起名
label := LabeledInput {
}
}
}
完整語法
1. comments
// 或者 /* .. */
2. 命名
a-zA-Z 0-9 _ -
注意: _會被統(tǒng)一改為-,所以 foo_bar 等價(jià)于 foo-bar
3. 數(shù)據(jù)類型
參考 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} 轉(zhuǎn)義符
4. 數(shù)據(jù)結(jié)構(gòu)
// 結(jié)構(gòu)體
export struct Player {
name: string,
score: int,
}
anonymous structures using
{ identifier1: type2, identifier1: type2 }
// 枚舉
export enum CardSuit { clubs, diamonds, hearts, spade }
// 數(shù)組
[int] l1 : [1,12,35];
l1.length
l1[index]
5. 類型轉(zhuǎn)換
int,float可以直接轉(zhuǎn)string
physical-length,length 可以直接轉(zhuǎn)
struct直接如果有相同屬性名可以直接轉(zhuǎn)
array不能直接互相轉(zhuǎn)
string轉(zhuǎn)float: "3.14".to-float()/is-float()
6. Properties
每個(gè)element都有built-in的屬性,比如width、color等。
屬性的值可以是值,也可以是表達(dá)式`{42px}`,支持各種運(yùn)算符.
//自定義屬性
export component Example {
// declare a property of type int with the name `my-property`
property
// declare a property with a default value
property
// This is meant to be set by the user of the component.
in property
// This property is meant to be read by the user of the component.
out property
// This property is meant to both be changed by the user and the component itself.
in-out property
// This property is internal to this component.
private property
}
// 默認(rèn)的property是private, 只在component內(nèi)部使用
// in 表示input, 可以被外部user修改/binding, assignment by callback。 內(nèi)部理論上也可以。
// out 表示output, 可以被component內(nèi)部修改,但是外部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
clicked => { self.counter += 3 }
text: self.counter * 2; // 根據(jù)counter動(dòng)態(tài)計(jì)算 binding
}
}
// 雙向綁定
export component Example {
in property
// 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 關(guān)鍵字定義函數(shù),默認(rèn) private
export component Example {
in-out property
in-out property
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; // 雙向綁定兩個(gè) callback
hello(aa, bb) => { aa + bb } // callback的實(shí)現(xiàn),可以在其他地方通過 => 綁定一個(gè)callback
area := TouchArea {
// sets a handler with `=>`
clicked => {
// emit the callback
root.hello(1, "abc")
}
}
}
10. Repetition and condition
// 通過for循環(huán)創(chuàng)建重復(fù)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 條件執(zhí)行不同渲染
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
// 屬性動(dòng)畫,具體效果參考 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";
內(nèi)建功能
init()
component MyButton inherits Rectangle {
in-out property
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”
Common properties Geometry
width/height: lengthx/y: lengthz: floatabsolute-position: point
Layout
col/row/colspan/rowspan: inthorizontal-stretch/vertical-stretch: floatmax-width/max-height/min-width/min-height: lengthpreferred-width/preferred-height: length
Miscellaneous
cache-rendering-hint: booldialog-button-role: enum DialogButtonRoleopacity: float, 0-1, 0 is fully transparent (invisible), and 1 is fully opaquevisible: bool
Drop Shadows(support Rectangle)
drop-shadow-blur: length // The radius of the shadowdrop-shadow-color: color // The base color of the shadowdrop-shadow-offset-x/y: length // The horizontal and vertical distance of the shadow from the element’s frame
Accessibility
accessible-role: enum AccessibleRoleaccessible-checkable: boolaccessible-checked: boolaccessible-description: stringaccessible-has-focus: boolaccessible-label: stringaccessible-value-maximum/minimum/step: floataccessible-value: string
Image
colorize: brush // is used as an alpha mask and is drawn in the given colorimage-fit: enum ImageFit // default contain, fill parentimage-rendering: enum ImageRendering //image scaled, default smoothrotation-angle: anglerotation-origin-x/y: length // Rotates the image by the given origin point.source: image // @image-url(“…”)source-clip-x/y/width/height: int // define the region of the source image that is renderedwidth/height: length
Path(SVG or slint)
fill: brush // The color for filling the shape of the pathfill-rule: enum FillRule // nonzerostroke: brush // the outline of the path.stroke-width: lengthwidth/height: length // If non-zero, the path will be scaled to fit into the specified heightviewbox-x/viewbox-y/viewbox-width/viewbox-height: float // the position and size of the viewport of the pathclip: bool // default false. if true, rendering will be clipped at the boundaries of the view boxcommands: string // SVG Path, such as: “M 0 0 L 0 100 A 1 1 0 0 0 100 100 L 100 0 Z”
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
close-on-click : in boolshow()close()
Rectangle
background : in brushborder-color : in brushborder-radius : in lengthborder-width : in lengthclip : in bool //default false, 超出parent border時(shí),子元素是顯示還是裁剪掉
TextInput
color: brushfont-family: stringfont-size: lengthfont-weight: int // 100-900font-italic: boolhas-foucs: out boolvertical/horizontal-alignment: enum TextVerticalAlignment/TextHorizontalAlignmentinput-type: enum InputType // default text, password/number/decimalletter-spacing: lengthread-only: boolselection-background/foreground-color: color // 選中文本顏色single-line: bool // default truetext-cursor-width: lengthwrap: enum TextWrap //default no-wrap, Only makes sense when single-line is falsefocus()select-all()clear-selection()copy() // 剪切板cut() // 剪切板paste() //剪切板accepted() : callback // when enter key is pressedcursor-position-changed(Point) : callback // cursor was moved to the new (x, y) positionedited() : callback // the text has changed because the user modified it
Text
color: brushfont-family: stringfont-size: lengthfont-weight: int // 100-900font-italic: boolvertical/horizontal-alignment: enum TextVerticalAlignment/TextHorizontalAlignmentletter-spacing: lengthwrap: enum TextWrap //default no-wrap, Only makes sense when single-line is falseoverflow: enum TextOverflow // default clip. What happens when the text overflowstext: string
TouchArea
has-hover : out boolmouse-cursor: enum MouseCursormouse-x, mouse-y: length //pressed-x, pressed-y: length // the position of the mouse at the moment it was last pressedpressed : boolclicked() : callbackmoved() : callback // his will only be called if the mouse is also pressedpointer-event(PointerEvent) : callback // when a button was pressed or released.scroll-event(PointerScrollEvent) -> EventResult: callback // when the mouse wheel was rotated or another scroll gesture was made
Window
preferred-width/preferred-height: length // initial window sizealways-on-top: boolbackground: brush // default depends on window styledefault-font-family: stringdefault-font-size: lengthdefault-font-weight: int // 100-900, 400 normalicon: image // window icon shown in the title bar or the task barno-frame: bool // window should be borderless/frameless or nottitle: string // window title that is shown in the title bar
functions/global
animation-tick()debug(…)TextInputInterface.text-input-focused:bool //全局輸入狀態(tài),做屏幕鍵盤用rgb(int, int, int) -> color, rgba(int, int, int, float) -> colorabs(float) -> float / ceil(float) -> int / floor(float) -> int / mod(T, T) -> TColors.aquamarine/Colors.redKey.F1/Key.Home
Widgets All widgets support all properties common to builtin elements.
AboutSlintButton // icon, checkable, text, primary, clicked()CheckBox // checked, text, toggled()Switch // checked, text, toggled()ComboBox // current-index, model [], selected(string)GroupBox // titleLineEdit // input-type, placeholder-text, text, accepted(string), edited(string)TextEdit // text, wrap, edited(string)ListView // like ScrollView, 虛擬的list容器,需要自定義itemScrollView // viewport-width/height, visible-width/heightStandardListView // 標(biāo)準(zhǔn)list. current-item, model, set-current-item(int), current-item-changed(int)ProgressIndicator //indeterminate, progressSpinner // indeterminate, progressSlider // value, maximum, minimum, orientation, changed(float)SpinBox // value, maximum, minimum, edited(int)StandardButton // kind, pressed, clicked()StandardTableView // 標(biāo)準(zhǔn)table, current-sort-column, columns, rows, current-row, set-current-row(int), current-row-changed(int)TabWidget // current-index, content-width/height. For Tab: icon, num-tabs, tab-index, title, current-focusedVerticalBox/HorizontalBox/GridBox // as with VerticalLayout/HorizontalLayout/GridLayout
Widget Style
The widget style is determined at your project’s compile time. If no style is selected, native is the default.
Renderer
Slint可以選擇多種渲染后端,各有利弊。 https://slint.dev/releases/1.3.0/docs/slint/src/advanced/backends_and_renderers
Qt Renderer
Software Renderer
FemtoVG Renderer
Skia Renderer
柚子快報(bào)激活碼778899分享:slint ui學(xué)習(xí)筆記
好文鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。