是否可以将 QAbstractTableModel 与 QtQuick.Controls 中的 TableView 一起使用? [英] Is it possible to use QAbstractTableModel with TableView from QtQuick.Controls?

查看:18
本文介绍了是否可以将 QAbstractTableModel 与 QtQuick.Controls 中的 TableView 一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I’m trying to implement following thing:

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

There is 2d table with values. I need to implement UI for viewing data and editing it. To simplify synchronisation between edits from UI and table updates coming from the back-end, I want model to store uncommitted edited values and expose a couple of methods to accept/reject pending changes.

据我了解,使用 QtWidgets + 模型很容易做到这一点:

From what I understand this is reasonably easy to do with QtWidgets + models:

基于 QAbstractTableModel 的模型.添加一些额外的角色来存储/查询挂起的更改等.使用带有自定义item delegate的QTableView,可以查询模型cell是否可编辑、显示未提交的更改等.

Base model on QAbstractTableModel. Add a few extra roles for storing/querying pending changes, etc. Use QTableView with custom item delegate, which can query model whether cell is editable, show uncommitted changes, etc.

但是我很困惑如何实现它 QtQuick.Controls.TableView.根据我的实验,TableView 不能与 QAbstractTableModel 一起使用——它会遍历模型的第一列并使用角色来模拟第二维.

But I’m puzzled about how to implement it QtQuick.Controls.TableView. From my experiments, TableView doesn’t work with QAbstractTableModel — it iterates over the first column of the model and uses roles to simulate second dimension.

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

Is there a way to make TableView work with QAbstractTableModel correctly? As an alternative — I can change model to use roles for columns, but I’m not sure how to handle other aspects of cell data (modified flag, uncommited value, etc.). The only idea I have so far is to return composite (dictionary) value for each cell. E.g. return QMap or QJsonObject as a value of "cell" and interpret it on QML side.

还有其他方法吗?如果我决定实施我的第二个解决方案——QMap 或 QJsonObject,哪个更有效?

Are there any other ways to do it? What’s more effective if I decide to implement my second solution — QMap or QJsonObject?

推荐答案

这是一个例子,希望对你有帮助

This is an example maybe it'll help you hopefully

假设我们有一个 sqlite 数据库,其中包含一个表mytable",其中包含三列nom"(文本)、prenom"(文本)和image"(url 作为文本)

Suppose we have sqlite database containing a table "mytable" with three columns "nom" (text),"prenom"(text) and "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

--------------------------- 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 
                }
            }


        }

    }
}

这篇关于是否可以将 QAbstractTableModel 与 QtQuick.Controls 中的 TableView 一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆