import { Button } from "std-widgets.slint";
export component MyApp inherits Window {
width: 400px;
height: 300px;
Text {
text: "Привет, мир!";
font-size: 24px;
color: blue;
}
Button {
text: "Нажми меня";
clicked => { /* обработчик события */ }
}
}
import { Component1, Component2 } from "library.slint";
import * as Lib from "another-library.slint";
export component MyComponent {
// свойства и элементы
width: 100px;
height: 100px;
Text {
text: "Содержимое компонента";
}
}
component ChildComponent inherits ParentComponent {
// дополнительные свойства и элементы
property<string> additional-text: "Дополнительный текст";
}
export component Example {
// Базовые типы
property<string> text: "Значение по умолчанию";
property<int> count: 0;
property<float> opacity: 1.0;
property<bool> is-enabled: true;
// Сложные типы
property<color> bg-color: #3498db;
property<length> width: 100px;
property<duration> animation-duration: 300ms;
property<brush> my-brush: @linear-gradient(90deg, #ff0000, #00ff00);
// Структуры и массивы
property<{x: int, y: int}> position: {x: 0, y: 0};
property<[int]> numbers: [1, 2, 3, 4, 5];
}
property<int> counter <=> parent.counter;
property<string> full-name: first-name + " " + last-name;
Rectangle {
width: 100px;
height: 100px;
color: red;
border-radius: 8px;
border-width: 1px;
border-color: black;
// Градиентная заливка
background: @linear-gradient(90deg, #ff0000, #00ff00);
// Тень
drop-shadow: 2px 2px 5px #00000080;
// Вложенные элементы
Text {
text: "Текст внутри прямоугольника";
color: white;
}
}
Text {
text: "Пример текста";
font-size: 16px;
font-weight: bold;
font-family: "Arial";
color: black;
horizontal-alignment: center;
vertical-alignment: center;
overflow: elide;
wrap: word-wrap;
letter-spacing: 1px;
}
Image {
source: @image-url("path/to/image.png");
width: 100px;
height: 100px;
image-fit: contain; // contain, cover, fill
colorize: #ff0000; // тонирование изображения
source-clip-x: 0;
source-clip-y: 0;
source-clip-width: 50%;
source-clip-height: 50%;
}
TextInput {
text: "Редактируемый текст";
font-size: 14px;
placeholder-text: "Введите текст...";
has-focus: true;
enabled: true;
read-only: false;
input-type: text; // text, password, number
selection-foreground-color: white;
selection-background-color: blue;
}
Button {
text: "Нажми меня";
icon: @image-url("icon.png");
enabled: true;
primary: true; // основная кнопка
clicked => {
debug("Кнопка нажата");
}
}
CheckBox {
text: "Выбери меня";
checked: false;
enabled: true;
toggled => {
debug("Состояние изменено: " + self.checked);
}
}
Slider {
width: 200px;
minimum: 0;
maximum: 100;
value: 50;
orientation: horizontal; // horizontal, vertical
changed => {
debug("Значение изменено: " + self.value);
}
}
ComboBox {
model: ["Опция 1", "Опция 2", "Опция 3"];
current-index: 0;
enabled: true;
selected => {
debug("Выбрана опция: " + self.current-value);
}
}
ScrollView {
width: 300px;
height: 200px;
viewport-width: 500px;
viewport-height: 400px;
Rectangle {
width: 500px;
height: 400px;
for i in 10: Rectangle {
y: i * 40px;
width: 100%;
height: 30px;
color: i % 2 == 0 ? #e0e0e0 : #f0f0f0;
Text {
text: "Элемент " + i;
}
}
}
}
Flickable {
width: 300px;
height: 300px;
viewport-width: 600px;
viewport-height: 600px;
interactive: true;
Rectangle {
width: 600px;
height: 600px;
color: blue;
}
}
Path {
width: 100px;
height: 100px;
commands: "M 10 10 L 90 10 L 90 90 L 10 90 Z";
stroke: black;
stroke-width: 2px;
fill: red;
}
VerticalLayout {
spacing: 10px;
alignment: center;
padding: 10px;
Text { text: "Первый элемент"; }
Text { text: "Второй элемент"; }
Rectangle { height: 50px; color: blue; }
}
HorizontalLayout {
spacing: 10px;
alignment: space-between;
padding-left: 5px;
padding-right: 5px;
Rectangle { width: 50px; height: 50px; color: red; }
Rectangle { width: 50px; height: 50px; color: green; }
Rectangle { width: 50px; height: 50px; color: blue; }
}
GridLayout {
spacing: 5px;
Row {
Rectangle { color: red; }
Rectangle { color: green; }
Rectangle { color: blue; }
}
Row {
Rectangle { color: yellow; }
Rectangle { color: cyan; }
Rectangle { color: magenta; }
}
}
TableLayout {
Row {
Text { text: "Имя"; }
Text { text: "Возраст"; }
Text { text: "Город"; }
}
Row {
Text { text: "Иван"; }
Text { text: "25"; }
Text { text: "Москва"; }
}
Row {
Text { text: "Мария"; }
Text { text: "30"; }
Text { text: "Санкт-Петербург"; }
}
}
export component Button {
callback clicked();
Rectangle {
// ...
TouchArea {
clicked => { root.clicked(); }
}
}
}
Button {
clicked => {
counter += 1;
debug("Счетчик: " + counter);
}
}
export component ItemList {
callback item-selected(int);
for item[i] in items: Rectangle {
TouchArea {
clicked => { root.item-selected(i); }
}
}
}
Rectangle {
color: white;
states [
pressed when touch-area.pressed: {
color: blue;
scale: 0.9;
}
hover when touch-area.has-hover: {
color: lightblue;
}
disabled when !enabled: {
opacity: 0.5;
}
]
TouchArea { }
}
Rectangle {
color: white;
// Анимация отдельных свойств
animate color { duration: 250ms; easing: ease-in-out; }
animate scale { duration: 150ms; easing: ease; }
// Анимация для состояний
states [
active when is-active: {
color: blue;
animate color { duration: 500ms; }
}
]
}
Rectangle {
x: 0px;
animate x {
duration: 2s;
iteration-count: infinite;
easing: cubic-bezier(0.42, 0, 0.58, 1);
alternate: true;
// Ключевые кадры
keyframes: [
{ value: 0px; easing: ease-in; },
{ value: 100px; easing: ease-out; },
{ value: 50px; }
];
}
}
// Простой цикл
for i in 5: Rectangle {
y: i * 30px;
height: 20px;
color: Colors.darker(blue, i / 5);
}
// Цикл по модели данных
for item[i] in model: Rectangle {
color: item.color;
Text { text: item.text + " (" + i + ")"; }
}
// Условный элемент
if condition: Rectangle {
// отображается только если condition == true
}
// Условное свойство
Rectangle {
visible: condition; // альтернативный способ
color: is-active ? blue : gray; // тернарный оператор
}
// Условие с else
if condition {
Rectangle { color: green; }
} else {
Rectangle { color: red; }
}
struct TodoItem {
text: string,
completed: bool,
}
export component TodoList {
property<[TodoItem]> items: [
{ text: "Купить молоко", completed: false },
{ text: "Выгулять собаку", completed: true },
];
VerticalLayout {
for item[i] in items: HorizontalLayout {
CheckBox {
checked: item.completed;
toggled => {
items[i].completed = self.checked;
}
}
Text {
text: item.text;
text-decoration: item.completed ? line-through : none;
}
}
}
}
export component TodoApp {
property<[TodoItem]> items: [];
property<string> new-item-text: "";
function add-item() {
items = [... items, { text: new-item-text, completed: false }];
new-item-text = "";
}
function remove-item(index: int) {
items = [... items.slice(0, index), ... items.slice(index + 1)];
}
}
Rectangle {
x: 10px;
y: 20px;
width: 100px;
height: 50px;
}
Rectangle {
x: parent.width / 2 - self.width / 2; // центрирование по горизонтали
y: parent.height / 2 - self.height / 2; // центрирование по вертикали
}
Rectangle {
width: 100px;
height: 100px;
Rectangle {
x: 0px;
y: 0px;
width: parent.width / 2;
height: parent.height / 2;
}
Rectangle {
x: parent.width - self.width;
y: parent.height - self.height;
width: 50px;
height: 50px;
}
}
Rectangle {
z: 0;
color: blue;
}
Rectangle {
z: 1; // будет отображаться поверх предыдущего прямоугольника
color: red;
opacity: 0.5;
}
FocusScope {
key-pressed(event) => {
if (event.text == "Enter") {
submit();
return accept;
}
return reject;
}
key-released(event) => {
debug("Клавиша отпущена: " + event.text);
return accept;
}
}
TextInput {
focus-on-tab: true;
tab-order: 1;
}
TextInput {
focus-on-tab: true;
tab-order: 2;
}
FocusScope {
key-pressed(event) => {
if (event.modifiers.control && event.text == "s") {
save-document();
return accept;
}
return reject;
}
}
import { translations } from "translations.slint";
Text {
text: translations.welcome-message;
}
// translations.slint
export global translations {
property<string> welcome-message: "Добро пожаловать";
property<string> save-button: "Сохранить";
property<string> cancel-button: "Отмена";
}
Text {
text: Format.decimal(value, 2); // 2 знака после запятой
}
Text {
text: Format.date(date, "dd.MM.yyyy");
}
Text {
text: Format.duration(duration, "mm:ss");
}
global Theme {
property<color> primary-color: #3498db;
property<color> secondary-color: #2ecc71;
property<color> background-color: white;
property<color> text-color: black;
property<length> spacing: 8px;
property<length> border-radius: 4px;
property<length> font-size: 14px;
}
Rectangle {
color: Theme.background-color;
border-radius: Theme.border-radius;
Text {
color: Theme.text-color;
font-size: Theme.font-size;
}
}
global Themes {
property<{
primary: color,
background: color,
text: color,
}> current: dark;
property<{
primary: color,
background: color,
text: color,
}> light: {
primary: #3498db,
background: white,
text: black,
};
property<{
primary: color,
background: color,
text: color,
}> dark: {
primary: #2980b9,
background: #2c3e50,
text: white,
};
function toggle-theme() {
current = current == light ? dark : light;
}
}
// Использование
Rectangle {
color: Themes.current.background;
Text {
color: Themes.current.text;
}
Button {
text: "Переключить тему";
clicked => { Themes.toggle-theme(); }
}
}
export component Example {
function calculate-area(width: length, height: length) -> length {
return width * height;
}
function is-valid-input() -> bool {
return input-text != "";
}
function increment-counter() {
counter += 1;
}
property<int> counter: 0;
property<string> input-text: "";
}
Rectangle {
width: 100px;
height: 50px;
property<length> area: calculate-area(self.width, self.height);
Button {
text: "Увеличить счетчик";
clicked => { increment-counter(); }
enabled: is-valid-input();
}
}
TouchArea {
pointer-event(event) => {
if (event.kind == pressed) {
debug("Нажатие в точке: " + event.x + ", " + event.y);
} else if (event.kind == released) {
debug("Отпускание в точке: " + event.x + ", " + event.y);
}
accept
}
moved => {
debug("Перемещение: " + self.mouse-x + ", " + self.mouse-y);
}
}
Rectangle {
property<bool> dragging;
property<length> drag-start-x;
property<length> drag-start-y;
TouchArea {
pressed => {
root.dragging = true;
root.drag-start-x = self.mouse-x;
root.drag-start-y = self.mouse-y;
}
moved => {
if (root.dragging) {
root.x += self.mouse-x - root.drag-start-x;
root.y += self.mouse-y - root.drag-start-y;
}
}
released => {
root.dragging = false;
}
}
}
TouchArea {
property<bool> multi-touch-enabled: true;
pointer-event(event) => {
if (event.kind == pressed) {
debug("Нажатие пальца " + event.pointer-id);
}
accept
}
}
export component Timer {
property<bool> running: false;
property<duration> interval: 1000ms;
property<int> count: 0;
callback timeout();
animate count {
duration: interval;
iteration-count: -1; // бесконечно
easing: linear;
// Вызывается при каждой итерации анимации
running: root.running;
// Вызывается при каждом обновлении свойства
update: {
if (running) {
timeout();
}
}
}
}
Timer {
running: true;
interval: 500ms;
timeout => {
counter += 1;
debug("Таймер сработал: " + counter);
}
}
Path {
commands: "M 0 0 L 100 0 L 50 100 Z"; // треугольник
fill: blue;
stroke: red;
stroke-width: 2px;
}
Path {
// Звезда
commands: "M 50 0 L 61 35 L 98 35 L 68 57 L 79 91 L 50 70 L 21 91 L 32 57 L 2 35 L 39 35 Z";
fill: gold;
stroke: black;
stroke-width: 1px;
}
export component CustomDrawing {
width: 200px;
height: 200px;
callback paint-callback(/* canvas context */);
Canvas {
width: parent.width;
height: parent.height;
paint => {
// Рисование на канвасе
paint-callback();
}
}
}
export component AsyncOperation {
property<bool> loading: false;
callback start-operation();
callback operation-completed(string);
Button {
text: "Начать операцию";
clicked => {
root.loading = true;
root.start-operation();
}
}
// Вызывается из бэкенда при завершении операции
public function complete(result: string) {
root.loading = false;
root.operation-completed(result);
}
}
export component LoadingIndicator {
property<bool> active: false;
Rectangle {
visible: active;
animate rotation {
duration: 1s;
iteration-count: -1;
easing: linear;
}
Image {
source: @image-url("spinner.png");
rotation-angle: rotation * 360deg;
}
}
}
export component FileViewer {
callback open-file(string);
callback save-file(string, string);
Button {
text: "Открыть файл";
clicked => { root.open-file("*.txt"); }
}
Button {
text: "Сохранить файл";
clicked => { root.save-file("document.txt", text-content); }
}
property<string> text-content: "";
}
Text {
color: ColorScheme.is-dark-color-scheme ? white : black;
text: "Текущая тема: " + (ColorScheme.is-dark-color-scheme ? "Тёмная" : "Светлая");
}
Text {
property<int> current-time: 0;
text: "Текущее время: " + Format.time(current-time, "HH:mm:ss");
animate current-time {
duration: 1s;
iteration-count: -1;
easing: linear;
}
}
Text {
text: "Ширина экрана: " + Math.round(Screen.width) + "px";
}
Rectangle {
x: Math.min(100, 200);
color: Colors.darker(Colors.blue, 0.2);
}
Rectangle {
width: Math.max(100px, parent.width / 2);
height: Math.sqrt(200px * 200px);
rotation-angle: Math.sin(time) * 30deg;
}
Rectangle {
color: Colors.mix(Colors.red, Colors.blue, 0.5); // фиолетовый
}
Rectangle {
color: Colors.brighter(Colors.blue, 0.2); // более светлый синий
}
Rectangle {
color: Colors.darker(Colors.green, 0.3); // более темный зеленый
}
Rectangle {
color: Colors.transparentize(Colors.red, 0.5); // полупрозрачный красный
}
component CachedItem {
cache-rendering: true; // кэшировать рендеринг
// сложный элемент с множеством дочерних элементов
VerticalLayout {
for i in 100: Rectangle {
height: 10px;
color: Colors.mix(blue, red, i / 100);
}
}
}
if is-visible: Rectangle {
// отрисовывается только если is-visible == true
}
Rectangle {
visible: is-visible; // альтернативный способ
}
if active-tab == "settings": SettingsPage { }
else if active-tab == "profile": ProfilePage { }
else: HomePage { }
// Линейный градиент
Rectangle {
background: @linear-gradient(90deg, red, blue);
}
// Радиальный градиент
Rectangle {
background: @radial-gradient(circle, red, blue);
}
// Градиент с несколькими точками остановки
Rectangle {
background: @linear-gradient(90deg, red 0%, yellow 50%, blue 100%);
}
Rectangle {
drop-shadow: 2px 2px 5px #00000080;
drop-shadow-color: #00000080;
drop-shadow-offset-x: 2px;
drop-shadow-offset-y: 2px;
drop-shadow-blur: 5px;
}
Rectangle {
background: @image-url("path/to/image.png");
background-size: cover; // contain, cover, fill
}
Text {
font-family: "Roboto";
font-weight: bold; // normal, bold
font-style: italic; // normal, italic
font-size: 16px;
letter-spacing: 1px;
text-decoration: underline; // none, underline, line-through
}
Rectangle {
debug: true; // показывает границы элемента в режиме отладки
}
debug(variable); // вывод в консоль
debug("Значение: " + variable);
export component DebugInfo {
property<string> debug-text;
function update-debug-info() {
debug-text = "Размер: " + width + "x" + height +
", Позиция: " + x + "," + y;
}
// Вызов при каждом изменении размера
width => { update-debug-info(); }
height => { update-debug-info(); }
x => { update-debug-info(); }
y => { update-debug-info(); }
}
export component App {
callback request-data();
function update-data(new-data: string) {
data = new-data;
}
property<string> data;
}
export component Counter {
property<int> value: 0;
public function increment() {
value += 1;
}
public function decrement() {
value -= 1;
}
public function reset() {
value = 0;
}
public function set-value(new-value: int) {
value = new-value;
}
}
export component Form {
property<string> username: "";
property<string> password: "";
callback submit-form(string, string);
Button {
text: "Отправить";
clicked => {
root.submit-form(root.username, root.password);
}
}
}
export component ApiClient {
property<bool> loading: false;
property<string> result: "";
property<string> error: "";
callback send-request(string);
public function handle-response(response: string) {
loading = false;
result = response;
error = "";
}
public function handle-error(error-message: string) {
loading = false;
result = "";
error = error-message;
}
Button {
text: "Отправить запрос";
clicked => {
loading = true;
result = "";
error = "";
send-request("https://api.example.com/data");
}
}
}
Image {
source: @image-url("path/to/image.png");
width: 200px;
height: 150px;
}
Image {
source: @image-url("path/to/image.png");
image-fit: contain; // contain, cover, fill
image-rendering: smooth; // smooth, pixelated
}
Image {
source: @image-url("path/to/image.png");
source-clip-x: 50px;
source-clip-y: 50px;
source-clip-width: 100px;
source-clip-height: 100px;
}
Image {
source: @image-url("path/to/icon.png");
colorize: Theme.primary-color; // применяет цвет к изображению
}
Text {
text: "Обычный текст";
font-size: 16px;
font-weight: bold; // normal, bold
font-style: italic; // normal, italic
text-decoration: underline; // none, underline, line-through
}
Text {
text: "Это длинный текст, который будет перенесен на несколько строк при необходимости.";
wrap: word-wrap; // no-wrap, word-wrap
height: 100px;
width: 200px;
}
Text {
text: "Очень длинный текст, который будет обрезан";
overflow: elide; // clip, elide
max-width: 100px;
elide-mode: middle; // start, middle, end
}
Text {
text: "Выровненный текст";
horizontal-alignment: center; // left, center, right
vertical-alignment: center; // top, center, bottom
}
// Шестнадцатеричная запись
property<color> red: #ff0000;
property<color> green: #00ff00;
property<color> blue: #0000ff;
// Запись с прозрачностью
property<color> semi-transparent-red: #ff000080;
// Функциональная запись
property<color> yellow: rgb(255, 255, 0);
property<color> cyan: rgba(0, 255, 255, 0.5);
// Смешивание цветов
property<color> purple: Colors.mix(red, blue, 0.5);
// Изменение яркости
property<color> light-blue: Colors.brighter(blue, 0.2);
property<color> dark-blue: Colors.darker(blue, 0.2);
// Изменение прозрачности
property<color> transparent-green: Colors.transparentize(green, 0.5);
// Линейный градиент
background: @linear-gradient(90deg, red, blue);
background: @linear-gradient(45deg, red 0%, yellow 50%, blue 100%);
// Радиальный градиент
background: @radial-gradient(circle, red, blue);
background: @radial-gradient(circle at top left, red 0%, blue 100%);
Rectangle {
x: 10px;
y: 20px;
width: 100px;
height: 50px;
}
Rectangle {
scale: 1.5; // увеличение в 1.5 раза
scale-x: 2.0; // растяжение по горизонтали
scale-y: 0.5; // сжатие по вертикали
}
Rectangle {
rotation-angle: 45deg;
rotation-origin-x: 50%;
rotation-origin-y: 50%;
}
Rectangle {
transform: skew(30deg, 0deg);
}
Rectangle {
transform: rotate(45deg) translate(10px, 20px) scale(1.5);
}
GridLayout {
Row {
Rectangle { colspan: 2; rowspan: 1; }
Rectangle { colspan: 1; rowspan: 2; }
}
Row {
Rectangle { horizontal-stretch: 1; }
Rectangle { horizontal-stretch: 2; } // займет в 2 раза больше места
}
}
VerticalLayout {
alignment: start; // start, center, end, space-between, space-around
spacing: 10px;
Rectangle { height: 50px; }
Rectangle { height: 50px; }
}
HorizontalLayout {
alignment: space-between;
spacing: 10px;
Rectangle { width: 50px; }
Rectangle { width: 50px; }
}
VerticalLayout {
padding: 10px;
padding-left: 20px;
padding-right: 20px;
padding-top: 5px;
padding-bottom: 5px;
Rectangle { }
Rectangle { }
}
// Пиксели
width: 100px;
height: 50px;
// Проценты
width: 50%;
height: 25%;
// Физические единицы
width: 2cm;
height: 1in;
// Относительные единицы
width: parent.width / 2;
height: parent.height * 0.75;
Rectangle {
width: 100px;
min-width: 50px;
max-width: 200px;
height: 100px;
min-height: 50px;
max-height: 200px;
}
Rectangle {
width: 100px;
height: self.width * 9/16; // соотношение 16:9
}
FocusScope {
key-pressed(event) => {
if (event.text == "Enter") {
submit-form();
return accept;
} else if (event.text == "Escape") {
cancel-form();
return accept;
}
return reject;
}
}
TouchArea {
clicked => {
debug("Клик по координатам: " + self.mouse-x + ", " + self.mouse-y);
}
moved => {
debug("Перемещение указателя: " + self.mouse-x + ", " + self.mouse-y);
}
pointer-event(event) => {
if (event.kind == pressed) {
debug("Нажатие кнопки: " + event.button);
}
return accept;
}
}
Rectangle {
property<bool> dragging: false;
property<length> start-x: 0px;
property<length> start-y: 0px;
TouchArea {
pressed => {
root.dragging = true;
root.start-x = root.x - self.mouse-x;
root.start-y = root.y - self.mouse-y;
}
moved => {
if (root.dragging) {
root.x = root.start-x + self.mouse-x;
root.y = root.start-y + self.mouse-y;
}
}
released => {
root.dragging = false;
}
}
}
TouchArea {
wheel-event(event) => {
scroll-position += event.delta-y;
return accept;
}
}
Rectangle {
color: blue;
animate color { duration: 250ms; easing: ease-in-out; }
}
Rectangle {
color: blue;
animate color { duration: 500ms; delay: 200ms; easing: ease; }
}
Rectangle {
property<float> rotation: 0;
animate rotation {
duration: 2s;
iteration-count: infinite; // -1 или infinite для бесконечного повторения
easing: linear;
}
rotation-angle: rotation * 360deg;
}
Rectangle {
property<float> progress: 0;
animate progress {
duration: 3s;
iteration-count: infinite;
easing: linear;
keyframes: [
{ target: 0; duration: 0ms; },
{ target: 0.25; duration: 1s; easing: ease-in; },
{ target: 0.75; duration: 1s; easing: ease-out; },
{ target: 1; duration: 1s; easing: ease-in-out; }
];
}
x: progress * (parent.width - self.width);
color: progress < 0.5 ? blue : red;
}
Rectangle {
color: blue;
states [
active when is-active: {
color: red;
}
]
// Анимация при переходе между состояниями
transitions [
transition active to !active: {
animate color { duration: 250ms; easing: ease-out; }
}
transition !active to active: {
animate color { duration: 500ms; easing: ease-in; }
}
]
}
struct Person {
name: string,
age: int,
address: Address,
}
struct Address {
street: string,
city: string,
zip: string,
}
export component PersonView {
property<Person> person: {
name: "Иван Иванов",
age: 30,
address: {
street: "Ленина 1",
city: "Москва",
zip: "123456"
}
};
VerticalLayout {
Text { text: "Имя: " + person.name; }
Text { text: "Возраст: " + person.age; }
Text { text: "Адрес: " + person.address.street + ", " +
person.address.city + ", " + person.address.zip; }
}
}
export component PeopleList {
property<[Person]> people: [
{
name: "Иван",
age: 30,
address: { street: "Ленина 1", city: "Москва", zip: "123456" }
},
{
name: "Мария",
age: 25,
address: { street: "Пушкина 2", city: "Санкт-Петербург", zip: "654321" }
}
];
VerticalLayout {
for person[i] in people: Rectangle {
VerticalLayout {
Text { text: person.name; }
Text { text: "Возраст: " + person.age; }
}
TouchArea {
clicked => {
selected-index = i;
}
}
background: i == selected-index ? #e0e0e0 : transparent;
}
}
property<int> selected-index: -1;
}
export component PersonEditor {
property<Person> person;
callback person-changed(Person);
function update-name(new-name: string) {
// Создаем новый объект с обновленным полем
var updated-person = person;
updated-person.name = new-name;
person = updated-person;
person-changed(person);
}
VerticalLayout {
TextInput {
text: person.name;
edited => {
update-name(self.text);
}
}
// Другие поля редактирования...
}
}
// Разделение на компоненты
component Header {
// ...
}
component Sidebar {
// ...
}
component Content {
// ...
}
export component MainWindow {
VerticalLayout {
Header { }
HorizontalLayout {
Sidebar { width: 200px; }
Content { }
}
}
}
component StyledButton {
property<string> text;
property<brush> background: Theme.button-background;
property<color> text-color: Theme.button-text;
callback clicked();
Rectangle {
background: root.background;
border-radius: Theme.border-radius;
Text {
text: root.text;
color: root.text-color;
}
TouchArea {
clicked => { root.clicked(); }
}
}
}
// Использование
StyledButton {
text: "Обычная кнопка";
clicked => { /* ... */ }
}
StyledButton {
text: "Важная кнопка";
background: Theme.primary-color;
text-color: white;
clicked => { /* ... */ }
}
export component ResponsiveLayout {
property<length> breakpoint: 600px;
if parent.width > breakpoint: HorizontalLayout {
Rectangle { background: blue; width: 30%; }
Rectangle { background: green; width: 70%; }
} else: VerticalLayout {
Rectangle { background: blue; height: 30%; }
Rectangle { background: green; height: 70%; }
}
}
- Используйте
cache-rendering: true
для сложных компонентов, которые редко меняются - Избегайте сложных вычислений в привязках свойств
- Используйте
visible: false
вместо условного рендеринга для временно скрытых элементов - Ограничивайте количество анимаций, выполняемых одновременно
// Пример оптимизации
component ComplexItem {
cache-rendering: true;
// Сложное содержимое
for i in 100: Rectangle {
y: i * 2px;
height: 1px;
color: Colors.mix(blue, red, i / 100);
}
}
// Отладка значений
debug("Значение: " + value);
// Отладка размеров
Rectangle {
debug: true; // показывает границы и размеры
}
// Отладка состояний
if debug-mode: Text {
text: "Текущее состояние: " + current-state;
color: red;
}
Эта шпаргалка охватывает большинство возможностей языка разметки Slint, от базовых элементов до продвинутых техник. Используйте ее как справочник при разработке пользовательских интерфейсов на Slint.
Помните, что Slint постоянно развивается, поэтому рекомендуется также обращаться к официальной документации для получения самой актуальной информации: https://slint.dev/docs/