拖放¶
拖放是处理大量文件的应用程序的重要组成部分,并且很容易添加到应用程序中。
添加拖放目标¶
您需要创建一个 GtkDropTarget,这是一个事件控制器,连接到小部件后,如果拖动对象被拖放到该小部件上,则会发出“drop”信号。要接收数据,请连接到该信号。
对于第一个示例,我们将设置程序以接收来自另一个程序(例如 Nautilus)的文件。为了方便复制和粘贴,此代码片段中包含信号连接。
GtkDropTarget *target = gtk_drop_target_new (G_TYPE_INVALID, GDK_ACTION_COPY);
gtk_drop_target_set_gtypes (target, (GType[1]) { GDK_TYPE_FILE_LIST, }, 1);
g_signal_connect (target, "drop", G_CALLBACK (on_drop), NULL);
g_signal_connect (target, "enter", G_CALLBACK (on_enter), my_window);
g_signal_connect (target, "leave", G_CALLBACK (on_leave), my_window);
gtk_widget_add_controller (GTK_WIDGET (my_window), GTK_EVENT_CONTROLLER (target));
content = Gdk.ContentFormats.new_for_gtype(Gdk.FileList)
target = Gtk.DropTarget(formats=content, actions=Gdk.DragAction.COPY)
target.connect('drop', on_drop)
target.connect('enter', on_enter)
target.connect('leave', on_leave)
# self here is a widget.
self.add_controller(target)
var target = new Gtk.DropTarget (typeof (Gdk.FileList), COPY);
target.on_drop.connect (on_drop);
// Visually emphasize the user that he is dropping a widget.
target.enter.connect (on_enter);
target.leave.connect (on_leave);
((Gtk.Widget) this).add_controller (target);
我们已经告知 GTK 该小部件已准备好用于拖放。如果您从文件管理器拖动文件,它将显示拖放图标。接下来,我们必须检索数据。
static gboolean
on_drop (GtkDropTarget *target,
const GValue *value,
double x,
double y,
gpointer data)
{
/* GdkFileList is a boxed value so we use the boxed API. */
GdkFileList *file_list = g_value_get_boxed (value);
GSList *list = gdk_file_list_get_files (file_list);
/* Loop through the files and print their names. */
for (GSList *l = list; l != NULL; l = l->next)
{
GFile* file = l->data;
g_print ("%s\n", g_file_get_path (file));
}
return TRUE;
}
def on_drop(self, drop_target, value: Gdk.FileList, x, y, user_data=None):
files: List[Gio.File] = value.get_files()
# Loop through the files and print their names.
for file in files:
print(file.get_path())
private bool on_drop (Value value, double x, double y) {
var file_list = (Gdk.FileList) value;
// Loop through the files and print their names.
foreach (var file in file_list.get_files ()) {
print ("%s\n", file.get_path ());
}
return true;
}
您可以在拖放操作期间,当指针进入小部件时执行一些自定义操作
static GdkDragAction
on_enter (GtkDropTarget *target,
double x,
double y,
gpointer data)
{
/* Custom code... */
/* Tell the callee to continue. */
return GDK_ACTION_COPY;
}
static void
on_leave (GtkDropTarget *target,
gpointer data)
{
/* Custom code... */
}
def on_enter(self, drop_target, x, y):
# Custom code...
# Tell the callee to continue
return Gdk.DragAction.COPY
def on_leave(self, drop_target):
# Custom code...
private Gdk.DragAction on_enter (double x, double y) {
// Custom code...
// Tell the callee to continue.
return COPY;
}
private void on_leave () {
// Custom code...
}
注意
GTK 已经提供在拖放操作期间将 :drop(active) 伪类设置在包含光标的小部件上,因此您无需自定义代码来处理样式更改。
可以使用 GObject 类型系统中支持的任何类型进行同一应用程序内的拖放操作,包括复杂类型。
如果您想支持跨应用程序拖放复杂类型,则必须使用 GdkContentSerializer 和 GdkContentDeserializer API。