代码之家  ›  专栏  ›  技术社区  ›  rasmus91

用Gee.ArrayList实现ListModel

  •  1
  • rasmus91  · 技术社区  · 6 年前

    所以我认为我应该是一个更通用、更易于使用的类,也就是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);
        }
    
    }
    

    /home/rasmus/Projects/Vala/Test/ObservableList.vala.c: In function ‘observable_array_list_g_list_model_interface_init’:
    /home/rasmus/Projects/Vala/Test/ObservableList.vala.c:189:18: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
      iface->get_item = (GObject* (*) (GListModel*, guint)) observable_array_list_real_get_item;
    

    虽然编译成功,但该类作为ListModel非常不可用:

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

    当试图运行编译程序时,其输出为:

    segmentationfault
    

    1 回复  |  直到 6 年前
        1
  •  2
  •   Zander Brown    6 年前

    需要记住的一件重要事情是,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_item返回 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
    

    所以你有两个问题

    1. HowDoI/ChooseApplicationID 帮助决定使用什么而不是“TestApp”,通常是 com.githost.me.App
    2. 你还没有真正设置一个方法来绑定模型,所以Gtk拒绝了它,确保你真的在那里传递了一个函数

    但是这两个都不能告诉我们为什么你会得到SEGV

    int 而GtkListBox期望 Object

    推荐文章