Gtk 使用Gee.ArrayList实现ListModel

Gtk 使用Gee.ArrayList实现ListModel,gtk,gtk3,vala,listmodel,Gtk,Gtk3,Vala,Listmodel,因此,我认为我应该是一个更通用、更易于使用的类,即用于列表框数据的Gee.ArrayList。结果是ListBox将采用一个ListModel,我想,因为我使用的是ArrayList,所以我最好创建一个既为Gee.ArrayList又为ListModel的类: public class ObservableArrayList<T> : ListModel, Gee.ArrayList<T>{ //Implement ListModel public Ob

因此,我认为我应该是一个更通用、更易于使用的类,即用于列表框数据的Gee.ArrayList。结果是ListBox将采用一个ListModel,我想,因为我使用的是ArrayList,所以我最好创建一个既为Gee.ArrayList又为ListModel的类:

public class ObservableArrayList<T> : ListModel, Gee.ArrayList<T>{

    //Implement ListModel
    public Object? get_item(uint position){
        if((int)position > size){
            return null;
        }

        return (Object?) this.get((int)position);
    }

    public Type get_item_type(){
        return element_type;
    }

    public uint get_n_items(){
        return (uint)size;
    }

    public new Object? get_object(uint position){
        if((int)position > size){
            return null;
        }
        return (Object) this.get((int)position);
    }

}
using Gtk;

public class TestApp : Gtk.Application{

    public TestApp () {
        Object (
            application_id: "TestApp",
            flags: ApplicationFlags.FLAGS_NONE
        );
    }

    protected override void activate(){
        var main_window = new Gtk.ApplicationWindow (this);
            main_window.default_height = 400;
            main_window.default_width = 600;
            main_window.title = "test";

        ListModel t = new ObservableArrayList<int>();

        var list_box = new Gtk.ListBox();

        list_box.bind_model(t, null);

        main_window.add(list_box);

        main_window.show_all ();

    }

    public static int main (string[] args) {
        Gtk.init (ref args);

        var app = new TestApp ();

        return app.run(args);
    }
}   
虽然编译成功,但该类作为ListModel非常不可用:

public class ObservableArrayList<T> : ListModel, Gee.ArrayList<T>{

    //Implement ListModel
    public Object? get_item(uint position){
        if((int)position > size){
            return null;
        }

        return (Object?) this.get((int)position);
    }

    public Type get_item_type(){
        return element_type;
    }

    public uint get_n_items(){
        return (uint)size;
    }

    public new Object? get_object(uint position){
        if((int)position > size){
            return null;
        }
        return (Object) this.get((int)position);
    }

}
using Gtk;

public class TestApp : Gtk.Application{

    public TestApp () {
        Object (
            application_id: "TestApp",
            flags: ApplicationFlags.FLAGS_NONE
        );
    }

    protected override void activate(){
        var main_window = new Gtk.ApplicationWindow (this);
            main_window.default_height = 400;
            main_window.default_width = 600;
            main_window.title = "test";

        ListModel t = new ObservableArrayList<int>();

        var list_box = new Gtk.ListBox();

        list_box.bind_model(t, null);

        main_window.add(list_box);

        main_window.show_all ();

    }

    public static int main (string[] args) {
        Gtk.init (ref args);

        var app = new TestApp ();

        return app.run(args);
    }
}   

有没有解决这个问题的好方法,或者我从一开始就尝试了一些错误的方法?

需要记住的一点是,Vala实际上编译成C,然后输入到GCC以构建一个可执行文件,您的编译器警告实际上是从
GCC
而不是
valac

在我的机器上,消息的格式略有不同

warning: assignment to ‘void * (*)(GListModel *, guint)’ {aka ‘void * (*)(struct _GListModel *, unsigned int)’} from incompatible pointer type ‘GObject * (*)(GListModel *, guint)’ {aka ‘struct _GObject * (*)(struct _GListModel *, unsigned int)’}
可以简化为

assignment to ‘void * (*)(GListModel *, guint)’ from incompatible type ‘GObject * (*)(GListModel *, guint)’
这基本上是说GLib希望get_项返回
void*
而不是GObject,这是绑定中的一个bug,因此可以忽略

运行时附带运行时警告

(list:4511): GLib-GIO-CRITICAL **: 21:44:24.003: g_application_set_application_id: assertion 'application_id == NULL || g_application_id_is_valid (application_id)' failed

(list:4511): Gtk-CRITICAL **: 21:44:24.008: gtk_list_box_bind_model: assertion 'model == NULL || create_widget_func != NULL' failed
所以你有两个问题

  • 您的应用程序id错误。请查看以帮助决定使用什么来代替“TestApp”,通常类似于
    com.githost.me.App
  • 您实际上还没有设置绑定模型的方法,因此Gtk拒绝了它,请确保您确实在那里传递了一个函数
  • 然而,这两个都没有告诉我们为什么你会得到SEGV


    答案在于,您的GListModel包含类型为
    int
    的元素,而GtkListBox则需要
    对象的集合

    您可以发布一个完整的/可编译的代码片段吗?我花了相当长的时间处理您的代码,只是发现它似乎可以工作,所以您必须在其他地方做其他事情。(这一点特别明显,因为您的类是
    observearraylist
    ,而您的用法和警告是针对
    observebalist
    )非常感谢您的时间。我根据记忆输入了这个类的调用,因此它是错误的。我现在已经用用法示例更新了帖子。请让我进一步了解。再次感谢您。“答案在于您的GListModel包含int类型的元素,而GtkListBox需要一个Object集合。”列表框需要一些与ListModel一致的东西,只要它得到的类实现了该接口的方法,这不是很好吗?我的意思是,否则,有什么意义呢?您应该尝试装箱int:newobservearraylist();这将它转换为一个引用类型,该类型适合基于Vala指针的泛型。理想情况下,Vala将自动装箱,但这需要一些工作GTKLISTBOX预期的对象,您可以在回调获取对象的位置看到这一点。如果需要,可以获取null。
    create\u widget
    ?不,它不能,
    null
    仅当模型也为
    null
    (有效地
    unbind\u model
    )时才有效。传递一个非null的模型,但是null
    create\u widget
    没有逻辑意义,会导致糟糕的事情发生