Реализация ListModel с Gee.ArrayList
Поэтому я подумал, что мне нужен один из наиболее общих и простых в использовании классов, а именно Gee.ArrayList для данных для ListBox. Оказывается, что 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 ответ
Важно помнить, что 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 это ошибка в привязках, поэтому ее можно игнорировать
Запуск идет с предупреждениями времени выполнения
(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 проблемы
- Ваш идентификатор приложения неверен. Посмотрите на https://wiki.gnome.org/HowDoI/ChooseApplicationID, чтобы решить, что использовать вместо "TestApp", как правило, что-то вроде
com.githost.me.App
- На самом деле вы не установили метод для привязки модели, поэтому Gtk отклоняет ее, убедитесь, что вы действительно передали туда функцию
Однако ни один из них не говорит нам, почему вы получаете SEGV
Ответ заключается в том, что ваша GListModel содержит элементы типа int
в то время как GtkListBox ожидает коллекцию Object