Qt tablView with model containg pointer to custom

2019-08-11 06:43发布

问题:

I created my custom class (CustomObject), that inherit from QGraphicsItem. I use those object to draw on scene (rectangles, polygons and stuff) and I store pointers to them in QList. Now I need to display all my CustomOBjects in tableView, but there are 2 conditions:

  1. When I select and interact with object in tableview - I must be able to interact with "real" CustomObject represented by it (example: I selected obj1 in tableview and click button "delete" or "edit" - and I want to be able to interact with acctaul object (delet or edit it).
  2. When I add new or change it - i wish to see change in tableView.

I'm not sure if i can achieve that with jsut table view and soem custom mdoel - or shoud I make my own QAbstractItemModel class, but if i do - how do i do it? Shoud i make class inherit from QAbstractItemModel and add pointer to my CustomObject, or just force my CustomObjects into soem specific model?

Little bits of my code:

Here is my CustomObject.h //I removed some code that was stricly related to "personal" functions related with specific features of my app

    class CustomObject : public QGraphicsItem
    {
    public:
        CustomObject();
        CustomObject(int _x, int _y, int _w, int _h);
        virtual QRectF boundingRect() const;

        void set_Name(QString name);
        QString get_Name();

    protected:
        void mousePressEvent(QGraphicsSceneMouseEvent *event);
        void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
        void mouseMoveEvent(QGraphicsSceneMouseEvent *event);

    private:
            QString Name;

I store them in list, in my "Overseer" class:

    class ObjOverseer 
    public:
            void drawingCustomObject_Do(int x, int y); //This function creates new "CustomObject" and adds it to the list (below)

        QList<CustomObject*> ObjectsList_CustomObjects;

In my mainwindow - I simply create that ObjOverseer and keep its pointer.

EDIT 1

I used this example: https://doc.qt.io/archives/4.6/itemviews-addressbook.html and created this class:

    CustomModelOfCustomObject::CustomModelOfCustomObject()
    {
    }

    CustomModelOfCustomObject::CustomModelOfCustomObject(QObject *parent)
         : QAbstractTableModel(parent)
     {
     }

    CustomModelOfCustomObject::CustomModelOfCustomObject(QList<CustomObject*> objects, QObject *parent)
         : QAbstractTableModel(parent)
     {
         ListOfObjects=objects;
     }

    int CustomModelOfCustomObject::rowCount(const QModelIndex &parent) const
    {
        Q_UNUSED(parent);
        return ListOfObjects.size();
    }

    int CustomModelOfCustomObject::columnCount(const QModelIndex &parent) const
    {
        Q_UNUSED(parent);
        return 2;//TODO - ZMIENIC ILOSC KOLUMN
    }

    QVariant CustomModelOfCustomObject::data(const QModelIndex &index, int role) const
    {
        if (!index.isValid())
        return QVariant();

        if (index.row() >= ListOfObjects.size() || index.row() < 0)
        return QVariant();

        if (role == Qt::DisplayRole) {
        CustomObject* obj = ListOfObjects.at(index.row());

        if (index.column() == 0)
            return obj->get_Name();
        else if (index.column() == 1)
            return obj->get_Address();
        }
        return QVariant();
    }

    QVariant CustomModelOfCustomObject::headerData(int section, Qt::Orientation orientation, int role) const
    {
        if (role != Qt::DisplayRole)
        return QVariant();

        if (orientation == Qt::Horizontal) {
        switch (section) {
            case 0:
            return tr("Name");

            case 1:
            return tr("Address");

            default:
            return QVariant();
        }
        }
        return QVariant();
    }

    bool CustomModelOfCustomObject::insertRows(int position, int rows, const QModelIndex &index)
    {
        Q_UNUSED(index);
        beginInsertRows(QModelIndex(), position, position+rows-1);

        for (int row=0; row < rows; row++) {
        CustomObject* obj;
        ListOfObjects.insert(position, obj);
        }

        endInsertRows();
        return true;
    }

    bool CustomModelOfCustomObject::removeRows(int position, int rows, const QModelIndex &index)
    {
        Q_UNUSED(index);
        beginRemoveRows(QModelIndex(), position, position+rows-1);

        for (int row=0; row < rows; ++row) {
        ListOfObjects.removeAt(position);
        }

        endRemoveRows();
        return true;
    }

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

            CustomObject* p = ListOfObjects.value(row);

            if (index.column() == 0)
                    p->set_Name(value.toString());
            else if (index.column() == 1)
                    p->set_Address(value.toString());
        else
            return false;

        ListOfObjects.replace(row, p);
            emit(dataChanged(index, index));

        return true;
        }

        return false;
    }

    Qt::ItemFlags CustomModelOfCustomObject::flags(const QModelIndex &index) const
    {
        if (!index.isValid())
        return Qt::ItemIsEnabled;

        return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
    }

    QList<CustomObject*> CustomModelOfCustomObject::getList()
    {
        return ListOfObjects;
    }

But still, when i reach point in my function where i shoud use this model- i dont know hwo i shoud add it or even if i will be able to use it as intended.

EDIT 2 When i chaned ListOfObject to public and tried:

   MyModel->ListOfObjects.append(newObj);

all crashed

回答1:

First thing to note is, you list in ObjOverseer and CustomModelOfCustomObject are not connected, you need to save the pointer of ObjOverseer list instead of copy it to CustomModelOfCustomObject. This one :

CustomModelOfCustomObject::CustomModelOfCustomObject(QList<CustomObject*> objects, QObject *parent)
     : QAbstractTableModel(parent)
 {
     ListOfObjects=objects;
 }

You need to add function to your CustomModel that will handle adding new customobject :

 bool CustomModelOfCustomObject::insertNewData(CustomObject  *obj, int rowposition = -1)
{
    int row = rowposition < 0 ? ListOfObjects.size : row;
    beginInserRows(QModelIndex(), row, row);
    ListOfObjects.insert(row, obj);
    endInsertRow();
}

And when you want to add new object, simply call those function. If you list on model is connected to ObjOverseer (pointer type), you does not need to add new object to your ObjOverseer.



回答2:

Solved it. Now i only add "representation" of object to model and whenever i need to update any object (ew. change name or color) i just do it via my overseer, passing soem kind of guid/identifier/id/anything that woudl let me tell objects apart form eachother.