拖放

拖放是处理大量文件的应用程序的重要组成部分,并且很容易添加到应用程序中。

添加拖放目标

您需要创建一个 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));

我们已经告知 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;
}

您可以在拖放操作期间,当指针进入小部件时执行一些自定义操作

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... */
}

注意

GTK 已经提供在拖放操作期间将 :drop(active) 伪类设置在包含光标的小部件上,因此您无需自定义代码来处理样式更改。

可以使用 GObject 类型系统中支持的任何类型进行同一应用程序内的拖放操作,包括复杂类型。

如果您想支持跨应用程序拖放复杂类型,则必须使用 GdkContentSerializerGdkContentDeserializer API。