Skip to content

拖放

使用 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"; }
}
}
}
slint

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;
}
}
slint

悬停目标所选择的操作也会通过 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()
});
// ...
}
rust

© 2026 SixtyFPS GmbH