Проблема с QListview с пользовательской моделью с использованием qabstractlistmodel

Попытка реализовать пользовательскую модель для моего qlistview. Я читал ссылки на прошлые сообщения, похожие на мои, но я не смог заставить его работать.

Я хотел перечислить мой объект, который должен быть создан пользователем динамически, нажав кнопку добавления. Чтобы удалить элемент из списка, пользователь должен выбрать элемент, а затем нажать кнопку удаления.

Изменить. Я пытаюсь создать qlistview с пользовательской моделью, которая наследуется от QAbstractListModel. qlistview отобразит Qlist, все элементы должны быть перечислены в qlistview. Я также хотел бы, чтобы пользователь создал и добавил новый MyCustomObject в Qlist.

Я пытался следовать примерам и сообщениям, которые я могу найти с помощью поиска Google, но в данный момент я потерялся.

Приложение вылетает при нажатии кнопки добавления.

главное окно.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QList<MyCustomObject*> *m_list = new QList<MyCustomObject*>;

    CustomListModel *lmodel = new CustomListModel(this);

    MyCustomObject *object = new MyCustomObject(this);

    m_list->append(object);

    ui->listView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    ui->listView->setEditTriggers(QAbstractItemView::NoEditTriggers);

    lmodel->setmylist(m_list);

    //Initialize the Listview
    ui->listView->setModel(lmodel);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_addpushButton_clicked()
{
    MyCustomObject *object = new MyCustomObject(this);

    lmodel->AddmycustomObject(object);
}

void MainWindow::on_removepushButto_clicked()
{

}

главное окно.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QListView>
#include <customlistmodel.h>
#include "mycustomobject.h"


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_addpushButton_clicked();

    void on_removepushButto_clicked();

private:
    Ui::MainWindow *ui;
    QList<MyCustomObject*> *m_list;
    CustomListModel *lmodel;


};

#endif // MAINWINDOW_H

customlistmodel.cpp

#include "customlistmodel.h"

CustomListModel::CustomListModel(QObject *parent) :
    QAbstractListModel(parent)
{
}
QVariant CustomListModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (index.row() >= Model_list->size())
        return QVariant();

    if (role == Qt::DisplayRole)
       return QVariant(QString("row [%1]").arg((Model_list->at(index.row()))->GetName() ));
    else
        return QVariant();
}
int CustomListModel::rowCount(const QModelIndex &parent) const
{
        Q_UNUSED(parent);
        return Model_list->size();
}
//bool CustomListModel::insertRows(int row, int count, const QModelIndex &parent)
//{
//    beginInsertRows(QModelIndex(), row, row+count-1);


//    endInsertRows();

//    return true;
//}


//bool CustomListModel::removeRows(int row, int count, const QModelIndex &parent)
//{
//    beginRemoveRows(QModelIndex(), row, row+count-1);


//    endRemoveRows();

//    return true;

//}





//bool CustomListModel::setData(const QModelIndex &index, const QVariant &value, int role)
//{
//   if (index.isValid() && role == Qt::EditRole) {

//      MyCustomObject *item = Model_list->at(index.row());
//      item->SetNam(value.toString());

//     // Model_list->at(index.row())->SetNam(value.toString());
//      emit dataChanged(index,index);
//      return true;
//   }
//   return false;

//}
//Custom Methods
void CustomListModel::setmylist(QList<MyCustomObject*> *list)
{
    beginResetModel();

    Model_list = list;

    endResetModel();
    reset();

}
void CustomListModel::AddmycustomObject(MyCustomObject *object)
{

    int first = Model_list->count();
    int last = first;

          beginInsertRows(QModelIndex(), first, last);
          Model_list->append(object);
          endInsertRows();

}

CustomListModel.h

#ifndef CUSTOMLISTMODEL_H
#define CUSTOMLISTMODEL_H

#include <QAbstractListModel>
#include <QList>
#include "mycustomobject.h"

class CustomListModel : public QAbstractListModel
{
    Q_OBJECT
public:
    explicit CustomListModel(QObject *parent = 0);
    QVariant data(const QModelIndex &index, int role) const;
    int rowCount(const QModelIndex &parent) const;
   // bool setData(const QModelIndex &index, const QVariant &value, int role);

   // bool insertRows(int row, int count, const QModelIndex &parent);
    //bool removeRows(int row, int count, const QModelIndex &parent);

    //Custom Methods
    void setmylist(QList<MyCustomObject*> *list);
    void AddmycustomObject(MyCustomObject *object);
private:
    QList<MyCustomObject*>* Model_list;

signals:

public slots:

};
#endif // CUSTOMLISTMODEL_H

MyCustomObject.h

#ifndef MYCUSTOMOBJECT_H
#define MYCUSTOMOBJECT_H

#include <QObject>

class MyCustomObject : public QObject
{
    Q_OBJECT
public:
    explicit MyCustomObject(QObject *parent = 0);
    QString Name;
    QString GetName() {return Name;}
    void SetNam(QString Value){ Name = Value;}
signals:

public slots:

};

#endif // MYCUSTOMOBJECT_H

мой пользовательский объект.cpp

#include "mycustomobject.h"

MyCustomObject::MyCustomObject(QObject *parent) :
    QObject(parent)
{
    this->Name = "TestName";
}

main.cpp

#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.ui введите здесь описание изображения


person Ninja Joey    schedule 10.12.2012    source источник
comment
Предлагаю подвести итог вашему посту. В любом случае, я думаю, что это опечатка, но вы повторно объявляете свою переменную lmodel в конструкторе MainWindow вместо того, чтобы назначать поле. Это то, что вы хотели?   -  person Daniel Castro    schedule 11.12.2012
comment
Я согласен. Хотя я признателен за то, что мне предоставлено много информации, я очень хотел бы увидеть краткое объяснение фактической проблемы, с которой вы столкнулись, а затем, при желании, просмотреть исходный код, необходимый для попытки определить вашу проблему. Какая часть вызывает у вас проблемы, дает сбой или работает не так, как ожидалось?   -  person jdi    schedule 11.12.2012
comment
Извините, когда я попытался нажать на кнопку добавления, приложение вылетает.   -  person Ninja Joey    schedule 11.12.2012
comment
Какая ошибка при сбое?   -  person jdi    schedule 11.12.2012


Ответы (1)


@DanielCastro коснулся этого в основном комментарии, но я расширяю его, так как думаю, что это может быть ваш настоящий сбой.

В вашем MainWindow вы объявляете закрытый член для модели:

private:
    ...
    CustomListModel *lmodel;

Но в вашем конструкторе MainWindow вы инициализируете совершенно новую модель и устанавливаете ее в своем представлении:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ...
    // Not actually initializing the private member
    CustomListModel *lmodel = new CustomListModel(this);
    ...

    lmodel->setmylist(m_list);

    //Initialize the Listview
    ui->listView->setModel(lmodel);
}

Это оставляет ваш частный lmodel в качестве нулевого указателя. Затем у вас есть слот, который пытается получить к нему доступ:

void MainWindow::on_addpushButton_clicked()
{
    MyCustomObject *object = new MyCustomObject(this);
    // CRASH because you access a NULL pointer
    lmodel->AddmycustomObject(object);
}

Таким образом, исправление, вероятно, будет состоять в том, чтобы убедиться, что вы инициализируете закрытый член, а не совершенно новую модель в конструкторе MainWindow:

lmodel = new CustomListModel(this);

Вы делаете то же самое со своим m_list, поэтому также:

m_list = new QList<MyCustomObject*>;

также кажется, что у вас могут быть потенциальные сбои сейчас или в будущем из-за использования указателя QList вместо просто QList в ваших классах. Я думаю, было бы лучше убедиться, что ваша модель имеет полностью инициализированный объект списка, а затем вы можете установить его или очистить от других списков.

private:
    QList<MyCustomObject*> Model_list;

И тогда вы бы передавали их так:

void setmylist(QList<MyCustomObject*> &list);
person jdi    schedule 11.12.2012
comment
Я внес изменение, но было вызвано прерывание, которое завершилось из приложения. Следующие сообщения также появлялись, если я не прервал программу. Программа неожиданно завершилась. C:\QTProject\ListViewWithAbstractListModel\debug\ListViewWithAbstractListModel.exe завершился с кодом -1073741819. - person Ninja Joey; 11.12.2012
comment
Теперь вылетает еще раньше? Попробуйте также исправить участника списка, которого я только что добавил. Это ошибка сег? Можете ли вы запустить его через отладчик и лучше понять, где он падает? - person jdi; 11.12.2012
comment
Но я все еще запутался в программировании модели-представления. Разве я не должен добавлять новый объект в Qlist, созданный в конструкторе? - person Ninja Joey; 11.12.2012
comment
Если у вас есть конкретный вопрос, я могу попытаться ответить на него для вас. На самом деле речь идет лишь об отделении кода, который управляет чистыми данными, от кода, который их отображает. Таким образом, у вас может быть один источник данных и 10 различных способов показать его пользователю полностью или частично. - person jdi; 11.12.2012
comment
Логично, мне удалось реализовать функцию удаления объекта из списка. Правильно ли моя общая реализация модели списка? - person Ninja Joey; 11.12.2012
comment
Если вы измените этот список моделей с указателя на объект, я думаю, вы на правильном пути. К тому же, когда он был у вас в качестве указателя, вы пропускали его каждый раз, когда устанавливали новый. - person jdi; 11.12.2012
comment
давайте продолжим это обсуждение в чате - person Ninja Joey; 11.12.2012