我有连接到数据库的 Qt/QML 应用程序,现在我想通过子类 QSqlQueryModel
获取数据:
#ifndef UEPEOPLEMODEL_H
#define UEPEOPLEMODEL_H
#include <QImage>
#include <QVariant>
#include <QStringList>
#include <QDebug>
#include <QHash>
#include <QByteArray>
#include <QSqlError>
#include <QSqlQueryModel>
#include <QSqlRecord>
#include <QModelIndex>
#include <QQuickImageProvider>
#include <QByteArray>
#include <QSqlRecord>
#include <QDebug>
#include <QSqlQuery>
#include "../settings/uedefaults.h"
#include "../settings/uetypes.h"
class UePeopleModel : public QSqlQueryModel,
public QQuickImageProvider
{
Q_OBJECT
private:
QSqlDatabase m_ueDb;
private:
QSqlDatabase ueDatabase() const
{ return this->m_ueDb; }
void ueSetDatabase(const QSqlDatabase& database)
{ this->m_ueDb=database; }
public:
UePeopleModel(QObject *parent=0);
~UePeopleModel();
QVariant data(const QModelIndex &index,
int role) const Q_DECL_OVERRIDE;
QImage ueImage(const QString &id) const;
QImage requestImage(const QString &id,
QSize *size,
const QSize &requestedSize);
UeTypeRoles roleNames() const;
public:
static const int ueRoleName=Qt::UserRole+1;
static const int ueRoleImage=Qt::UserRole+2;
};
#endif // UEPEOPLEMODEL_H
这里是实现:
#include "uepeoplemodel.h"
UePeopleModel::UePeopleModel(QObject* parent)
: QSqlQueryModel(parent),
QQuickImageProvider(QQmlImageProviderBase::Image,
QQmlImageProviderBase::ForceAsynchronousImageLoading)
{
//QSqlDatabase db;
if(!QSqlDatabase::connectionNames().contains(UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE,
Qt::CaseInsensitive))
{
this->ueSetDatabase(QSqlDatabase::addDatabase(UePosDatabase::DATABASE_DRIVER,
UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE));
} // if
this->ueDatabase().setHostName(/*this->uePosSettings()->ueDbHostname()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_HOSTNAME);
this->ueDatabase().setDatabaseName(/*this->uePosSettings()->ueDbName()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_NAME);
this->ueDatabase().setUserName(/*this->uePosSettings()->ueDbUser()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_USERNAME);
this->ueDatabase().setPassword(/*this->uePosSettings()->ueDbPassword()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_PASSWORD);
if(this->ueDatabase().open())
{
this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
this->ueDatabase());
//qDebug() << this->ueDatabase().lastError().text();
}
else
{
qDebug() << this->ueDatabase().lastError().text();
}
} // default constructor
UePeopleModel::~UePeopleModel()
{
} // default destructor
QVariant UePeopleModel::data(const QModelIndex &index,
int role) const
{
QVariant value=QVariant();
switch(role)
{
case ueRoleImage:
{
value=this->record(index.row()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_IMAGE).toByteArray();
break;
} // case
case ueRoleName:
{
value=this->record(index.row()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_NAME).toString();
break;
} // case
default:
return value;
} // switch
return QSqlQueryModel::data(index,
role);//value;
} // data
QImage UePeopleModel::ueImage(const QString &id) const
{
return QImage::fromData(this->record(id.toInt()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_IMAGE).toByteArray(),
"PNG");
} // image
QImage UePeopleModel::requestImage(const QString &id,
QSize *size,
const QSize &requestedSize)
{
Q_UNUSED(requestedSize);
QImage image=this->ueImage(id);
*size = image.size();
return image;
} // requestImage
UeTypeRoles UePeopleModel::roleNames() const
{
UeTypeRoles roles;
const int iRoleName=UePeopleModel::ueRoleName;
const int iRoleImage=UePeopleModel::ueRoleImage;
roles.insert(iRoleName,
"ueRoleName");
roles.insert(iRoleImage,
"ueRoleImage");
return roles;
} // roleNames
现在,问题是我从数据库中获取空值,因此 qml 输出错误:
> qrc:/gui/windows/UeKeypad.qml:140:43: Unable to assign [undefined] to
> QString qrc:/gui/windows/UeKeypad.qml:140:43: Unable to assign
> [undefined] to QString qrc:/gui/windows/UeKeypad.qml:118:33: QML
> Image: Failed to get image from provider:
> image://uepeoplemodel/undefined qrc:/gui/windows/UeKeypad.qml:118:33:
> QML Image: Failed to get image from provider:
> image://uepeoplemodel/undefined qrc:/gui/windows/UeKeypad.qml:140:43:
> Unable to assign [undefined] to QString
> qrc:/gui/windows/UeKeypad.qml:140:43: Unable to assign [undefined] to
> QString qrc:/gui/windows/UeKeypad.qml:140:43: Unable to assign
> [undefined] to QString qrc:/gui/windows/UeKeypad.qml:140:43: Unable to
> assign [undefined] to QString qrc:/gui/windows/UeKeypad.qml:118:33:
> QML Image: Failed to get image from provider:
> image://uepeoplemodel/undefined qrc:/gui/windows/UeKeypad.qml:118:33:
> QML Image: Failed to get image from provider:
> image://uepeoplemodel/undefined qrc:/gui/windows/UeKeypad.qml:118:33:
> QML Image: Failed to get image from provider:
> image://uepeoplemodel/undefined qrc:/gui/windows/UeKeypad.qml:118:33:
> QML Image: Failed to get image from provider:
> image://uepeoplemodel/undefined
为什么我从表中得到空值?! 嗯,我一直在研究问题,在 Qt 文档中它指出:
If the model is not initialized, an empty record will be returned.
文档链接:QSqlQueryModel::record .这可能是问题所在,但是,我在 main.cpp
中初始化了 UePeopleModel:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
UePeopleModel* uePeopleModel=new UePeopleModel(qApp);
engine.rootContext()->setContextProperty("uePeopleModel",
uePeopleModel);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
我还缺少什么?我检查了很多次数据库连接,没问题,我也从表中获取了字段名,但没有数据。
嗯,我已经将调试代码添加到 QVariant UePeopleModel::data(const QModelIndex &index, int role)
const 方法:
QVariant UePeopleModel::data(const QModelIndex &index,
int role) const
{
switch(role)
{
case ueRoleImage:
{
return this->record(index.row()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_IMAGE).toByteArray();
break;
} // case
case ueRoleName:
{
int nrrecords=this->rowCount(QModelIndex());
QString name=this->record(index.row()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_NAME).toString();;
return this->record(index.row()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_NAME).toString();
} break; // case
case ueRolePassword:
{
QString password=this->record(index.row()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_APPPASSWORD).toString();
return this->record(index.row()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_APPPASSWORD).toString();
} break; // case
default:
return QVariant();
} // switch
return QSqlQueryModel::data(index,
role);//value;
} // data
在 int nrrecords=this->rowCount(QModelIndex());
行之后我设置了一个断点,临时变量 nrrecord
保持值 5 -是数据库中的记录数!为什么 then 方法的参数 index
为空? data()
方法是通过 QML 项目 model
属性从 QML 文件中调用的。
最佳答案
至少存在以下问题:
你的 switch cases 都失败了(你必须在每个 switch cases 之后
break
)。您不需要私有(private)成员的任何访问器,您应该直接使用它们。这就是为什么他们是私有(private)的。当您希望将实现细节与公共(public)(或 protected )接口(interface)隔离时,访问器用作封装。删除
m_ueDb
的访问器并直接使用成员(member)。您对
data
的实现只会为图像角色提供值。您必须将默认角色访问权限转发给基类的data()
:QVariant UePeopleModel::data(const QModelIndex &index, int role) const { switch(role) { case ueRoleImage: for(int iIndex=0; iIndex<this->record().count(); iIndex++) { qDebug() << this->record().fieldName(iIndex) << << this->record().value(iIndex) << << index.row(); } return record(index.row()).value( UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_IMAGE).toByteArray(); case ueRoleName: return record(index.row()).value( UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_NAME).toString(); } return QSqlQueryModel::data(index, role); }
你不应该使用
<QtModule/QtHeader>
包括样式。你这样做表明你的.pro
文件未声明使用sql
模块和/或您在将模块添加到项目后没有在项目上重新运行 qmake(您应该在QT += sql
文件中的某处有.pro
)。修复如下:// CORRECT #include <QSqlError> // WRONG #include <QtSql/QSqlError>
关于mysql - Qt取数据库记录字段值为空,数据库中数据EXISTS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32178173/