1

因此,我认为我会成为更通用且易于使用的类之一,即用于 ListBox 数据的 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

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

4

1 回答 1

2

gcc要记住的重要一点是,Vala 实际上编译为 C,然后将其输入 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,这是绑定中的错误,因此可以忽略

运行附带运行时警告

(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

所以你有2个问题

  1. 您的应用程序 ID 错误。查看HowDoI/ChooseApplicationID以帮助决定使用什么而不是“TestApp”,通常类似于com.githost.me.App
  2. 您实际上还没有设置绑定模型的方法,因此 Gtk 拒绝它,请确保您实际上在那里传递了一个函数

但是,这些都没有告诉我们您为什么要获得 SEGV

答案在于您的 GListModel 包含类型的元素,int而 GtkListBox 期待一个集合Object

于 2019-02-06T22:39:30.210 回答