我想用 Vala 在 Gtk+3 的树之间移动一些选定的项目。问题是,在将它们添加到第二棵树后,我无法创建一个列表来包含必须删除的所有项目迭代(如果我在添加它们后立即删除它们,则只有一半的选定项目被正确删除)。看来 Gtk.TreeIter 不是一种类型,所以我无法从中创建列表。如果你需要完整的代码,我可以很乐意发布它(只有109行代码),它是牙线。谢谢。
valac --pkg gtk+-3.0 --pkg gee-0.8 treeview-prueba.vala
treeview-prueba.vala:75.23-75.34: error: `Gtk.TreeIter' is not a supported generic type argument, use `?' to box value types
75 | GLib.List<Gtk.TreeIter> iter_list_to_remove;
| ^~~~~~~~~~~~
treeview-prueba.vala:87.17-87.39: error: The name `add' does not exist in the context of `GLib.List<Gtk.TreeIter>?' (glib-2.0)
87 | iter_list_to_remove.add(itera2);
| ^~~~~~~~~~~~~~~~~~~~~~~
Compilation failed: 2 error(s), 0 warning(s)
make: *** [makefile:2: all] Error 1
相关代码为:
delete_button.clicked.connect (() => {
var selection = view.get_selection ();
Value s= Value (typeof (string));
Gtk.TreeModel model;
Gtk.TreeIter itera;
Gtk.TreeIter itera2;
var selected_rows = selection.get_selected_rows(out model).data;
GLib.List<Gtk.TreeIter> iter_list_to_remove;
for (int i = 0; i<selection.count_selected_rows() ; i++) {
s="hola";
list_store.get_iter(out itera,selected_rows);
while (!selection.iter_is_selected (itera) ) {
list_store.get_iter(out itera,selected_rows);
selected_rows.next();
}
list_store.get_value(itera,0,out s);
stdout.printf( " %s ",s.get_string());
list_store2.append (out itera2);
list_store2.set (itera2,0,s.get_string());
iter_list_to_remove.add(itera2);
selected_rows.next();
}
foreach (var iteration in iter_list_to_remove){
list_store.remove(ref iteration);
}
});
我预计它会正确编译,但出现上述错误。
将
GLib.List<Gtk.TreeIter>
更改为 GLib.List<Gtk.TreeIter>
。
这实际上是 Vala 中泛型实现方式的结果,它反映了这些 API 是如何在 C 中实现的。如果您不熟悉 C(或类似语言),这可能有点难以理解,抱歉!基本上,在 C 级别,“通用”函数的 API 是使用
gpointer
类型的参数实现的,这只是 void*
的 typedef。换句话说,您传递的任何值都必须适合指针内部。
GtkTreeIter
(C 类型)通常作为值传递,而不是引用,因此对于这样的 API,您真正需要做的是传递指针(即,GtkTreeIter*
而不是 GtkTreeIter
)。让 Vala 执行此操作的最佳方法是将其标记为可为空 (GtkTreeIter?
)。从技术上讲,您也可以在 Vala 中使用指针,但说实话,您几乎不应该在 Vala 中使用指针;您基本上选择退出内存管理。使其可为空会使 Vala 在 C 级别将参数作为指针传递,但 Vala 仍将为您处理内存管理。