QSqlQueryModel - 覆盖未调用的函数数据

Posted

技术标签:

【中文标题】QSqlQueryModel - 覆盖未调用的函数数据【英文标题】:QSqlQueryModel - override function data not being called 【发布时间】:2021-03-03 19:44:08 【问题描述】:

我正在尝试使用从 mysql 数据库中检索到的一些信息来填充 QML 中的 TableView。

我可以使用 QSqlQuery 连接到数据库,但是当尝试使用 QSqlQueryModel 时,它无法正常工作(在最后的图像中获得了结果)。我一直在调试应用程序,但从未调用模型的覆盖函数data和覆盖函数roleNames

这是我的模型文件的样子:tableModel.h

#ifndef TABLEMODEL_H
#define TABLEMODEL_H

#include <QObject>
#include <QtQml/qqml.h>
#include <QSqlQueryModel>
#include <source/database/mySQL/mySqlQueries.h>

class TableModel : public QSqlQueryModel 
    Q_OBJECT
    public:
        // List all the roles that will be used in the TableView
        enum Roles 
            CHROM_ROLE = Qt::UserRole + 1,
            POS_ROLE,
            ID_ROLE,
            REF_ROLE,
            ALT_ROLE,
            QUAL_ROLE
        ;

        explicit TableModel(QObject *parent = 0);

        // Override the method that will return the data
        QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const override;

    protected:
        /* hashed table of roles for speakers.
         * The method used in the wilds of the base class QAbstractItemModel,
         * from which inherits the class QSqlQueryModel
         * */
        QHash<int, QByteArray> roleNames() const override;

;

#endif // TABLEMODEL_H

这里,执行文件:tableModel.cpp

#include "tableModel.h"

TableModel::TableModel(QObject *parent) : QSqlQueryModel(parent) 



// The method for obtaining data from the model
QVariant TableModel::data( const QModelIndex & index, int role) const 
    switch (role) 
    case CHROM_ROLE:
        return QString("%1, %2").arg(index.column()).arg(index.row());
    case POS_ROLE:
        return QString("%1, %2").arg(index.column()).arg(index.row());
    case ID_ROLE:
        return QString("%1, %2").arg(index.column()).arg(index.row());
    case REF_ROLE:
        return QString("%1, %2").arg(index.column()).arg(index.row());
    case ALT_ROLE:
        return QString("%1, %2").arg(index.column()).arg(index.row());
    case QUAL_ROLE:
        return QString("%1, %2").arg(index.column()).arg(index.row());
    default:
        break;
    

    return QVariant();


QHash<int, QByteArray> TableModel::roleNames() const 

    QHash<int, QByteArray> roles;
    roles[CHROM_ROLE] = "CHROM_ROLE";
    roles[POS_ROLE] = "POS_ROLE";
    roles[ID_ROLE] = "ID_ROLE";
    roles[REF_ROLE] = "REF_ROLE";
    roles[ALT_ROLE] = "ALT_ROLE";
    roles[QUAL_ROLE] = "QUAL_ROLE";
    return roles;

如您所见,我已经覆盖了dataroleNames。执行时不会调用这些函数。 (现在,data 应该返回行号和列号,而不是真实数据)。

包含TableView对象的qml文件对应部分如下:

import QtQuick.Controls 2.4
import QtQuick.Controls 1.4 as Controls
import QtQuick.Window 2.11
import Qt.labs.qmlmodels 1.0

Window 
    id: root
    visible: true
    width: 640
    height: 480
    title: qsTr("Title")

        Controls.TableView 
            id: tableview
            width: root.width * 0.8
            height: root.height * 0.8
            anchors.centerIn: parent
            clip: true

            Controls.TableViewColumn 
                role: "CHROM_ROLE"    // These roles are roles names coincide with a C ++ model
                title: "#Chrom"
            

            Controls.TableViewColumn 
                role: "POS_ROLE"    // These roles are roles names coincide with a C ++ model
                title: "Pos."
            

            Controls.TableViewColumn 
                role: "ID_ROLE"  // These roles are roles names coincide with a C ++ model
                title: "ID"
            

            Controls.TableViewColumn 
                role: "REF_ROLE" // These roles are roles names coincide with a C ++ model
                title: "Ref."
            

            Controls.TableViewColumn 
                role: "ALT_ROLE" // These roles are roles names coincide with a C ++ model
                title: "Alt."
            

            Controls.TableViewColumn 
                role: "QUAL_ROLE" // These roles are roles names coincide with a C ++ model
                title: "Qual."
            

            // We set the model in the TableView
            model: TableModel
        



如您所见,每个 TableViewColumns 的角色与 cpp 文件中的角色相对应。

pro 文件包含以下行(此外,SQL 查询正在运行):

QT += sql

在 main.cpp 文件中,我将像这样实例化所有内容。:

    QGuiApplication app(argc, argv);
    qmlRegisterType<TableModel>("TableModel", 1, 0, "TableModel");

    TableModel tableModel;

    MySqlConnector db;
    db.connectToDB("localhost", "dbname", "user", "Password");
    db.open();
    // I've tested that the query is working using just QSqlQuery and retrieves info from database 
    tableModel.setQuery(MySQLQueries::queryBodyOfVCF.arg(1), db.db);

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("TableModel", &tableModel);

    const QUrl url(QStringLiteral("qrc:/views/MasterView.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) 
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    , Qt::QueuedConnection);
    engine.load(url);

    return app.exec();

当我执行它时,这就是我得到的:

预期的结果应该是这样的(在真实的数据库中只有一行,并且如 cmets 中所述,tableModel.rowCount() 按预期返回 1)。这是应显示的真实数据示例:

  chrom   pos   ref      alt   qual      id
   ctg1     9     A     C, G    100   rs001
   ctg3    12     C        T    100   rs002

我的实现有问题吗?我认为我可能误解了某些概念,或者 .h 文件或 .cpp 文件中缺少某些内容。

【问题讨论】:

删除qmlRegisterType&lt;TableModel&gt;("TableModel", 1, 0, "TableModel");。同时提供minimal reproducible example。还要在tableModel.setQuery(MySQLQueries::queryBodyOfVCF.arg(1), db.db);之后添加qDebug() &lt;&lt; tableModel.rowCount(); 谢谢。 qDebug() &lt;&lt; tableModel.rowCount(); 返回 1(正如预期的那样,因为 MySQL 工作台也只返回一行)。删除qmlRegisterType&lt;TableModel&gt;("TableModel", 1, 0, "TableModel"); 并不能解决问题,但我明白你为什么要我删除它。 嗯,我已经理解错误了。我认为错误是行数,因为在图像中显示为 1,但在预期的输出中显示为 2。现在我明白错误是因为它出现 TABLEVIEW_QMLTYPE_.... 我的错,我没有说清楚。我已经编辑了这个问题,所以很明显这是一个输出示例。我在数据库中插入了另一个条目,因此查询现在在 MySQL Workbench 中返回 2 行。 qDebug() &lt;&lt; tableModel.rowCount(); 正在打印 2。但是,GUI 中的输出完全相同,只有一行显示 TABLEVIEW_QMLTYPE_46...(),而函数 dataroleNames 没有被执行。 【参考方案1】:

问题是因为你使用了item的名称:TableModel,解决方法是更改​​context-property的名称:

engine.rootContext()->setContextProperty("tableModel", &tableModel);
model: tableModel

另一方面,我建议使用在another post 中实现的模型,我在其中概括了逻辑。

【讨论】:

像魅力一样工作!非常感谢。那么问题是它使用的是类型而不是对象。当然,我会检查您链接的帖子中实现的模型并更改我的实现。事实是,找到这方面的例子有点困难,所以谢谢你的链接。

以上是关于QSqlQueryModel - 覆盖未调用的函数数据的主要内容,如果未能解决你的问题,请参考以下文章

使用情节提要时未调用 UITableViewController 覆盖初始化函数

QSqlQueryModel 配合Qtableview的表格,怎么实现点击头部排序

QT中QTableview表中内容修改?

QT中QTableview表中内容修改?

Django 序列化程序:未调用验证函数

delphi中覆盖override父类的静态方法和虚函数有啥不同?