首页 文章

是否可以将QAbstractTableModel与QtQuick.Controls中的TableView一起使用?

提问于
浏览
3

我正在尝试实现以下内容:

有2d表的值 . 我需要实现用于查看数据和编辑数据的UI . 为了简化来自后端的编辑和来自后端的表更新之间的同步,我希望模型存储未提交的编辑值,并公开一些方法来接受/拒绝挂起的更改 .

根据我的理解,这对QtWidgets模型来说相当容易:

QAbstractTableModel上的基础模型 . 添加一些额外的角色来存储/查询挂起的更改等 . 使用QTableView和自定义项委托,可以查询模型是否可以编辑单元格,显示未提交的更改等 .

但我很困惑如何实现它QtQuick.Controls.TableView . 从我的实验中,TableView不能与QAbstractTableModel一起使用 - 它迭代模型的第一列并使用角色来模拟第二维 .

有没有办法让TableView正确使用QAbstractTableModel?作为替代方案 - 我可以更改模型以使用列的角色,但我不确定如何处理单元格数据的其他方面(修改标志,未提及的值等) . 到目前为止,我唯一的想法是为每个单元格返回复合(字典)值 . 例如 . 将QMap或QJsonObject作为“cell”的值返回并在QML端解释它 .

有没有其他方法可以做到这一点?如果我决定实现我的第二个解决方案 - QMap或QJsonObject,那会更有效吗?

1 回答

  • 1

    这是一个例子,它可能会对你有所帮助

    假设我们的sqlite数据库包含一个表“mytable”,其中包含三列“nom”(文本),“prenom”(文本)和“image”(url as text)

    --------------------------- PRESENCEMODEL.h

    #include <QSqlTableModel>
    typedef  QHash<int,QByteArray> qMyHash  ;
    
    class PresenceModel : public QSqlTableModel {
    
        Q_OBJECT
        Q_PROPERTY(QStringList dictionary READ dictionary NOTIFY dictionaryChanged)
        Q_PROPERTY(QString filterString READ filterString WRITE setFilterString NOTIFY filterStringChanged)
        Q_PROPERTY(qMyHash roles READ roles NOTIFY rolesChanged)
    
    public:
    
        PresenceModel(QSqlDatabase, QObject* parent = 0);
        void generateRoleNames();
    
        QString filterString() const { return p_filterString; }
        void setFilterString(const QString&);
    
        Q_INVOKABLE QStringList getData(int currentRow);
    
        QVariant data(const QModelIndex&, int role) const;
    
        Q_INVOKABLE void insert(const QString& url, const QString& title);
        void populate();
    
        QHash<int, QByteArray> roleNames() const;
        Q_INVOKABLE void p_setTable(const QString &tableName);
        QStringList dictionary() const;
        void setDictionary(const QStringList &value);
        QHash<int, QByteArray> roles() const;
    
    
    
    Q_SIGNALS:
    
        void dataChanged();
        void gotData();
    
        void rolesChanged();
    
    private:
    
    
        enum ColumnRH {
            nom= Qt::UserRole + 1,
            prenom= Qt::UserRole + 2,
            image= Qt::UserRole + 3
        };
    
        QHash<int, QByteArray> p_roles;
        QString p_filterString;
        QStringList p_dictionary;
    };
    

    --------------------------- PRESENCEMODEL.cpp

    #include "presencemodel.h"
    #include <QtCore/QDateTime>
    #include <QtSql/QSqlError>
    #include <QtSql/QSqlQuery>
    #include <QtSql/QSqlRecord>
    #include <QDebug>
    
    PresenceModel::PresenceModel(QSqlDatabase database, QObject *parent)
        : QSqlTableModel(parent,  database)
    {
    }
    
    void PresenceModel::generateRoleNames()
    {
    
        p_roles[nom] = "nom";
        p_roles[prenom] = "prenom";
        p_roles[image] = "image";
    }
    
    
    
    void PresenceModel::populate()
    {
    
        select();
    
    }
    
    void PresenceModel::insert(const QString& url, const QString& title)
    {
    
    }
    
    
    
    QVariant PresenceModel::data(const QModelIndex& index, int role) const
    {
        if (role < Qt::UserRole)
            return QSqlQueryModel::data(index, role);
    
        const int columnId = role - Qt::UserRole;
        const QModelIndex modelIndex = createIndex(index.row(), columnId-1);
        return QSqlTableModel::data(modelIndex, Qt::DisplayRole);
    
    }
    
    
    
    QStringList PresenceModel::getData(int currentRow)
    {
        QStringList rowDataList;
    
        for (int i=0;i<columnCount();i++)
    
            rowDataList.append(data(this->index(currentRow,i),Qt::DisplayRole).toString());
    
        emit gotData();
    
        return rowDataList;
    }
    
    
    QHash<int, QByteArray> PresenceModel::roleNames() const
    {
        return p_roles;
    }
    
    
    QHash<int, QByteArray> PresenceModel::roles() const
    {
        return roleNames();
    }
    

    --------------------------- main.cpp

    int main(int argc, char *argv[])
     {
     QGuiApplication app(argc, argv);
    
     QQmlApplicationEngine engine;
    
     QSqlDatabase m_database = QSqlDatabase::addDatabase("QSQLITE");
    
     m_database.setDatabaseName("/.../mydatabase.sqlite");
    
    
     PresenceModel  *p_pModel= new PresenceModel(m_database);
    
     p_pModel->setTable("mytable");
    
     m_database.open(); 
    
     QQmlContext *ctxt = engine.rootContext();
    
     ctxt->setContextProperty("ppModel", (PresenceModel*) p_pModel);
    
     engine.load(QUrl("qrc:/main.qml"));
    
     return app.exec();
    
      }
    

    QML

    --------------------------- main.qml

    Rectangle {
    
        Component.OnCompleted : ppModel.populate()
        TableView{
            id:tableview_actes
            TableViewColumn{ role: "nom"  ; title: "nom" ; width: 330 }
            TableViewColumn{ role: "prenom" ; title: "prénom" ; width: 65}
            TableViewColumn{ role: "image" ; title: "Photo" ; width:65}
    
            model:ppModel
            onCurrentRowChanged:  {
                var list=   myModel.getData(currentRow)   // invoke c++ function                                    
    
                console.log(list[0])
    
    
    
            }
            Listview{
                model:ppModel
                delegate:
                    Item {
                    Text{
    
                        text: nom + " " +prenom // our roles 
                    }
    
                    Image{
                        source : image // image : url in our table 
                    }
                }
    
    
            }
    
        }
    }
    

相关问题