拖放
使用 DragArea 和 DropArea 通过拖放手势在 UI 的各个部分之间移动数据。 在支持该功能的平台上,DropArea 还可以接受来自其他应用的放置。
负载是一个 data-transfer 值,它抽象了各平台支持的文件类型传输机制。
data-transfer 值在 Slint 代码中是不透明的:
需通过宿主语言实现的回调来构造和读取它们。
export global Api { pure callback string-to-transfer(string) -> data-transfer; pure callback transfer-to-string(data-transfer) -> string; pure callback can-drop(data-transfer) -> bool;}
export component Example inherits Window { width: 300px; height: 200px;
VerticalLayout { spacing: 8px; padding: 8px;
Rectangle { background: #f0c000; DragArea { data: Api.string-to-transfer("Hello World"); allow-copy: true; } Text { text: "Drag me"; } }
Rectangle { background: drop.has-drag ? #80e080 : #a0a0a0; drop := DropArea { can-drop(event) => { Api.can-drop(event.data) ? DragAction.copy : DragAction.none } dropped(event) => { debug("Got: ", Api.transfer-to-string(event.data)); return event.proposed-action; } } Text { text: "Drop here"; } } }}can-drop 和 dropped 都返回一个 DragAction:DragAction.copy、DragAction.move、DragAction.link 表示以该操作接受,或者 DragAction.none 表示拒绝。can-drop 在悬停期间运行(驱动光标和 current-action);dropped 在释放时运行,返回的操作会通过 drag-finished 报告回源。
DragArea 声明它允许哪些操作(allow-copy、allow-move、allow-link)。
至少要将其中一个设为 true;不允许任何操作的 DragArea 永远不会启动拖动(编译器会发出警告)。
当没有按下修饰键时,建议的操作是 move、copy、link 中第一个被允许的;
修饰键会请求特定的操作(Ctrl -> copy,Shift -> move,Ctrl+Shift -> link)。在 macOS 上,使用 Command (⌘) 代替 Ctrl。
目标在 can-drop(用于悬停)和 dropped(最终结果)中选择最终操作,运行时会根据源允许的操作集合进行限制,当放置完成时,源的 drag-finished(action) 会触发,这样 “move” 源就可以移除原始数据。
DragArea { data: Api.make-data(); allow-copy: false; allow-move: true; // Dim the source while the drag is in flight. opacity: self.dragging ? 0.4 : 1.0; drag-finished(action) => { if action == DragAction.move { Api.remove-source(); } }}
DropArea { // Accept the action the user is asking for; the runtime clamps it to what the source allows. can-drop(event) => event.proposed-action; dropped(event) => { Api.accept-drop(event.data); return event.proposed-action; }}悬停目标所选择的操作也会通过 current-action 暴露出来,这对于视觉反馈很有用(每个操作使用不同的光标、图标或高亮)。
fn main() { let app = Example::new(); // For simple plain text and image transfers, a simple conversion is supplied // which handles the common case. let api = app.global::<Api>(); api.on_string_to_transfer(Into::into); // A helper for reading plain text from a `DataTransfer` is also supplied. api.on_transfer_to_string(|data| data.plain_text().unwrap_or_default()); api.on_can_drop(|data| { // This helper abstracts over various "plain text" MIME types data.has_plain_text() }); // ...}int main(){ auto app = Example::create(); auto api = app->global<Api>(); // For simple plain text and image transfers, a simple conversion is supplied // which handles the common case. api.on_string_to_transfer( [](const slint::SharedString &text) { return slint::DataTransfer(text); }); // A helper for reading plain text from a `DataTransfer` is also supplied. api.on_transfer_to_string( [](const slint::DataTransfer &data) { return data.plain_text().value_or(""); }); api.on_can_drop([](const slint::DataTransfer &data) { // This helper abstracts over various "plain text" MIME types return data.has_plain_text(); }); // ...}import * as slint from 'slint-ui';
const ui = slint.loadFile(new URL('example.slint', import.meta.url));const window = new ui.Example();
window.Api.string_to_transfer = (text) => { const transfer = new slint.DataTransfer(); transfer.plainText = text; return transfer;};
// A helper for reading plain text from a `DataTransfer` is also supplied.window.Api.transfer_to_string = (data) => data.plainText ?? '';
// This helper abstracts over various "plain text" MIME typeswindow.Api.can_drop = (data) => data.hasPlainText;import slintfrom slint import DataTransfer
class App(slint.loader.example.Example):
@slint.callback(global_name="Api", name="string-to-transfer") def string_to_transfer(self, text: str) -> DataTransfer: transfer = DataTransfer() transfer.plain_text = text return transfer
# A helper for reading plain text from a `DataTransfer` is also supplied. @slint.callback(global_name="Api", name="transfer-to-string") def transfer_to_string(self, data: DataTransfer) -> str: return data.plain_text or ""
# This helper abstracts over various "plain text" MIME types @slint.callback(global_name="Api", name="can-drop") def can_drop(self, data: DataTransfer) -> bool: return data.has_plain_text© 2026 SixtyFPS GmbH