Slint Kit Documentation

Données virtualisées

Liste de contenus pour Slint

KitContentList · Slint Kit 0.3.1

Liste Slint virtualisée avec titres, extraits et sélection.

Liste Slint virtualisée avec titres, extraits et sélection.
Application native de l’exemple ci-dessous.

Essayer le composant

Télécharger le projet complet, le décompresser et lancer cargo run --locked dans son dossier. Rust 1.92+ ; Slint Kit 0.3.0 depuis crates.io. Vous pouvez aussi copier les quatre fichiers ci-dessous.

Sélectionnez un article à la souris, ou déplacez-vous avec les flèches et validez avec Entrée. Rust affiche le titre choisi.

ui/app.slint

export { KitFormValidation, HtmlInputKind, NumberInputFormat, KitInputConstraints, KitValidationResult, KitValidityState } from "@kit/kit.slint";
// SPDX-License-Identifier: GPL-3.0-or-later
import { KitContentList, KitThemes, ContentItem, NavigationStep } from "@kit/kit.slint";
export { ContentItem, NavigationStep }
export component App inherits Window {
    title: "Slint content list";
    preferred-width: 580px; preferred-height: 390px;
    max-width: 100000px; max-height: 100000px;
    background: KitThemes.light.canvas;
    in property <[ContentItem]> items;
    in property <int> active-index: -1;
    in property <string> selected-label: "Choose an article";
    callback choose(int, int);
    callback move(NavigationStep);
    VerticalLayout {
        padding: 24px; spacing: 16px;
        list := KitContentList { height: 280px; items: root.items; generation: 1;
            active-index: root.active-index;
            activate(token, generation) => { root.choose(token, generation); }
            navigate(step) => { root.move(step); }
        }
        Text { text: root.selected-label; color: KitThemes.light.text-primary; }
    }
}

src/main.rs

// SPDX-License-Identifier: GPL-3.0-or-later
use slint::{ComponentHandle, ModelRc, VecModel};
use std::{cell::RefCell, rc::Rc};
mod ui {
    slint::include_modules!();
}

fn next_index(current: Option<usize>, length: usize, step: ui::NavigationStep) -> usize {
    use ui::NavigationStep::*;
    let current = current.unwrap_or(0);
    match step {
        First => 0,
        Last => length.saturating_sub(1),
        Previous | PagePrevious => current.saturating_sub(1),
        Next | PageNext => (current + 1).min(length.saturating_sub(1)),
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]
enum Article {
    Setup,
    State,
}
impl Article {
    fn token(self) -> i32 {
        match self {
            Self::Setup => 11,
            Self::State => 23,
        }
    }
    fn title(self) -> &'static str {
        match self {
            Self::Setup => "Install Slint Kit",
            Self::State => "Keep selection stable",
        }
    }
    fn excerpt(self) -> &'static str {
        match self {
            Self::Setup => "Import a component and connect its Rust callback.",
            Self::State => "Use an application key when the display order changes.",
        }
    }
}
const ARTICLES: [Article; 2] = [Article::Setup, Article::State];
#[derive(Default)]
struct State {
    selected: Option<Article>,
    active: Option<Article>,
}
fn publish(state: &RefCell<State>, app: &ui::App) {
    let state = state.borrow();
    let items = ARTICLES
        .iter()
        .map(|article| ui::ContentItem {
            token: article.token(),
            title: article.title().into(),
            excerpt: article.excerpt().into(),
            metadata: "Guide".into(),
            link_label: "Select article".into(),
            thumbnail: slint::Image::default(),
            selected: state.selected == Some(*article),
            disabled: false,
        })
        .collect::<Vec<_>>();
    let index = ARTICLES
        .iter()
        .position(|a| Some(*a) == state.active)
        .map_or(-1, |i| i as i32);
    let label = state.selected.map_or("Choose an article".to_owned(), |a| {
        format!("Selected: {}", a.title())
    });
    drop(state);
    app.set_items(ModelRc::new(VecModel::from(items)));
    app.set_active_index(index);
    app.set_selected_label(label.into());
}
fn main() -> Result<(), slint::PlatformError> {
    let app = ui::App::new()?;
    slint_kit::init_form_validation!(ui, app);
    let state = Rc::new(RefCell::new(State::default()));
    publish(&state, &app);
    let (model, weak) = (state.clone(), app.as_weak());
    app.on_choose(move |token, generation| {
        if generation != 1 {
            return;
        }
        let Some(article) = ARTICLES.iter().copied().find(|a| a.token() == token) else {
            return;
        };
        {
            let mut state = model.borrow_mut();
            state.selected = Some(article);
            state.active = Some(article);
        }
        if let Some(app) = weak.upgrade() {
            publish(&model, &app);
        }
    });
    let weak = app.as_weak();
    app.on_move(move |step| {
        {
            let mut state = state.borrow_mut();
            let current = ARTICLES.iter().position(|a| Some(*a) == state.active);
            state.active = Some(ARTICLES[next_index(current, ARTICLES.len(), step)]);
        }
        if let Some(app) = weak.upgrade() {
            publish(&state, &app);
        }
    });
    app.run()
}

Cargo.toml et build.rs

Cargo.toml

[package]
name = "slint-kit-content-list-example"
version = "0.1.0"
edition = "2024"
rust-version = "1.92"
license = "GPL-3.0-or-later"
publish = false

[dependencies]
slint-kit = "=0.3.0"
slint = { version = "=1.18.1", default-features = false, features = ["std", "compat-1-18", "backend-winit", "renderer-skia", "accessibility"] }

[build-dependencies]
slint-kit-build = "=0.3.0"

[workspace]

build.rs

fn main() {
    slint_kit_build::compile("ui/app.slint").expect("compile component example");
}

Fichiers : Cargo.toml · build.rs · ui/app.slint · src/main.rs

Fournissez items, generation et active-index. Traitez activate(token, generation) dans Rust avec la clé applicative, puis navigate pour déplacer le focus. Donnez une hauteur bornée à la liste.

Chaque ContentItem fournit son titre, sa description, ses métadonnées et une vignette facultative. Les lignes sont rendues dans le viewport. Définissez empty-label pour un modèle vide.

Choisir entre une option intégrée et une composition personnalisée

Options partagées

Composition visuelle

Le fichier ci-dessous produit la capture. Pour les composants pilotés par un contrôleur, il montre l’état affiché sans fournir le branchement Rust. Créer un projet.

Afficher le fichier de la capture
Liste Slint virtualisée avec titres, extraits et sélection.
Capture native du même exemple, moteur Skia.
// Public label overrides localize this fixture; toolkit/host defaults keep their language.
// SPDX-License-Identifier: GPL-3.0-or-later
import { KitContentList, KitTheme, KitThemes } from "@kit/kit.slint";

export component Example inherits Window {
    title: "KitContentList — exemple";
    preferred-width: 620px;
    preferred-height: 410px;
    max-width: 100000px;
    max-height: 100000px;
    background: root.theme.canvas;
    in-out property <KitTheme> theme: KitThemes.light;
    in-out property <string> status;
    VerticalLayout {
        padding: 24px; spacing: 16px; alignment: start;
        Text { text: "Liste de contenus"; color: root.theme.text-primary; font-size: 20px * root.theme.text-scale; font-weight: 600; }
        KitContentList { empty-label: "Aucun article trouvé"; label: "Articles"; theme: root.theme; height: 260px; generation: 1; items: [{ token: 101, title: "Guide du design natif", excerpt: "Créez des interfaces qui trouvent naturellement leur place sur le bureau.", metadata: "Design · 5 min de lecture", link-label: "Lire l’article", selected: false, disabled: false }, { token: 205, title: "Préserver l’exactitude des valeurs métier", excerpt: "Utilisez des valeurs validées et des identités stables dans l’application.", metadata: "Ingénierie · 8 min de lecture", link-label: "Lire l’article", selected: false, disabled: false }]; }
        if root.status != "": Text { text: root.status; color: root.theme.text-secondary; font-size: 12px * root.theme.text-scale; wrap: word-wrap; }
    }
}

Télécharger cet exemple

API publique

Hérite de Rectangle.

Propriétés

Nom Type Sens
theme KitTheme in
items [ContentItem] in
generation int in
active-index int in
label string in
empty-label string in
scroll-y length out

Types et variantes

Type Déclaration
struct ContentItem token: int, title: string, excerpt: string, metadata: string, link-label: string, thumbnail: image, selected: bool, disabled: bool
enum NavigationStep next, previous, first, last, page-next, page-previous

Signaux

Fonctions

Voir aussi