【问题标题】:QML ListView data retreival from mysql database从 mysql 数据库中检索 QML ListView 数据
【发布时间】:2015-08-11 09:00:27
【问题描述】:

我的测试数据库,我有一个名为 users 的表,它代表可记录的用户。现在,我已经通过 Qt/C++ 成功连接到数据库,向 QML 公开类(也没有问题),设置 QML ListView 以向这些用户展示自定义模型和委托(文件 main.qml)以及当我运行我的应用程序时,ListView 中显示了五个项目。现在,ListView's 委托由 ImageText 部分组成(Image section 用于可记录的用户图像,它驻留在 BLOB 在 mysql 数据库中,Text section 用于用户名,它也作为 VARCHAR 在 mysql 数据库中 - 两个字段都在同一个名为 users 的表中>):

import QtQuick 2.3

Item
{
    id: uePeopleItemDelegate

    property Image uePersonImage
    property string uePersonName

    width: 256
    height: 256
    antialiasing: true

    clip: true

    Rectangle
    {
        id: ueRectangleMain
        color: "#000000"

        radius: 16
        anchors.fill: parent
        antialiasing: true
        border.color: "#ffffff"
        border.width: 4
        clip: true
        //opacity: 0.7

        Grid
        {
            antialiasing: true
            anchors.rightMargin: 12
            anchors.leftMargin: 12
            anchors.bottomMargin: 12
            anchors.topMargin: 12
            anchors.fill: parent
            spacing: 4
            rows: 2
            columns: 1
        }

        Row
        {
            id: ueRowImage
            anchors.rightMargin: 12
            anchors.leftMargin: 12
            anchors.bottom: parent.bottom
            anchors.right: parent.right
            anchors.left: parent.left
            anchors.top: parent.top
            anchors.bottomMargin: 48
            anchors.topMargin: 12
        }

        Image
        {
            id: uePersonleImage
            x: 12
            y: 12
            width: 232
            height: 196
            antialiasing: true
            fillMode: Image.PreserveAspectFit
            source: ""
        }

        Column
        {
            id: ueColumnPeopleInfo
            x: 12
            y: 214
            width: 232
            height: 30
            spacing: 0
        }

        Text
        {
            id: ueTextPersonName
            x: 12
            y: 214
            width: 232
            height: 30
            color: "#ffffff"
            text: uePersonName
            font.bold: true
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
            font.pixelSize: 16
        }
    }
}

这是代表的截图:

如果我在数据库中删除/添加用户,代表的数量会根据表用户记录的数量而变化,这很完美。但是现在我有两个问题:在main.qml,我实例化了这个ListView

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtMultimedia 5.0
import QtQuick.Layouts 1.0
import QtTest 1.1

import "gui/delegates"

ApplicationWindow
{
    id: ueWindowMain

    title: qsTr("TestApp")

    width: Screen.desktopAvailableWidth
    height: Screen.desktopAvailableWidth

    visible: true

    opacity: 1.0

    contentOrientation: Qt.LandscapeOrientation

    color: "black"

    ListView
    {
        id: uePeopleListView
        snapMode: ListView.SnapToItem
        highlightRangeMode: ListView.ApplyRange
        anchors.right: parent.right
        anchors.rightMargin: 0
        anchors.bottom: parent.top
        anchors.bottomMargin: -128
        anchors.left: parent.left
        anchors.leftMargin: 0
        anchors.top: parent.top
        anchors.topMargin: 0
        orientation: ListView.Horizontal
        flickableDirection: Flickable.HorizontalFlick
        antialiasing: true
        spacing: 16
        delegate: UePeopleItemDelegate
        {
            id: uePersonDelegate

            uePersonImage: ""   // Q1: How do I retreive image (user image) from database?
            uePersonName: ""    // Q2: How do I retreive text (user name) from database?
        }
        model: uePeopleModel
    }
}

如何检索数据(图像和文本)以在 4950 行的委托中显示它?这里也是我的模型类的标头和实现:

#ifndef UEPEOPLEMODEL_H
#define UEPEOPLEMODEL_H

#include <QImage>
#include <QVariant>
#include <QStringList>
#include <QDebug>
#include <QHash>
#include <QByteArray>
#include <QtSql/QSqlError>
#include <QtSql/QSqlQueryModel>
#include <QtSql/QSqlRecord>
#include <QModelIndex>

#include "../settings/uedefaults.h"

class UePeopleModel : public QSqlQueryModel
{
    Q_OBJECT

private:
    QHash<int, QByteArray> m_ueRoleNames;

    void ueGenerateRoleNames();

public:
    UePeopleModel(QObject *parent=0);
    ~UePeopleModel();

    QVariant data(const QModelIndex &index,
                  int role) const Q_DECL_OVERRIDE;
    void ueRefresh();
    inline QHash<int, QByteArray> ueRoleNames() const
        { return this->m_ueRoleNames; }
};

#endif // UEPEOPLEMODEL_H

和实施:

#include "uepeoplemodel.h"

UePeopleModel::UePeopleModel(QObject* parent)
    : QSqlQueryModel(parent)
{
    QSqlDatabase db;

    if(!QSqlDatabase::connectionNames().contains(UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE,
                                                 Qt::CaseInsensitive))
    {
            db=QSqlDatabase::addDatabase(UePosDatabase::DATABASE_DRIVER,
                                         UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE);
    }   // if

    db.setHostName(/*this->uePosSettings()->ueDbHostname()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_HOSTNAME);
    db.setDatabaseName(/*this->uePosSettings()->ueDbName()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_NAME);
    db.setUserName(/*this->uePosSettings()->ueDbUser()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_USERNAME);
    db.setPassword(/*this->uePosSettings()->ueDbPassword()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_PASSWORD);

    if(db.open())
    {
        this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
                       db);
        this->ueGenerateRoleNames();
    }
    else
    {
        qDebug() << db.lastError().text();
    }
}   // default constructor

UePeopleModel::~UePeopleModel()
{
}   // default destructor

QVariant UePeopleModel::data(const QModelIndex &index,
                             int role) const
{
    QVariant value;

    if(role<Qt::UserRole)
    {
        value=QSqlQueryModel::data(index,
                                   role);
    }
    else
    {
        int iColumnIndex=role-Qt::UserRole-1;
        QModelIndex modelIndex=this->index(index.row(),
                                           iColumnIndex);

        value=QSqlQueryModel::data(modelIndex,
                                   Qt::DisplayRole);
    }   // if

    return value;

//    QVariant value=QSqlQueryModel::data(index,
//                                        role);

//    if(value.isValid()&&role==Qt::DisplayRole)
//    {
//        switch(index.column())
//        {
//            case UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_ID:
//                return value.toInt();

//            case UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_NAME:
//                return value.toString();

//            case UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_APPPASSWORD:
//                return value.toString();

//            case UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_CARD:
//                return value.toString();

//            case UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_IMAGE:
//            {
//                QImage image;

//                image.loadFromData(value.toByteArray());

//                return image;
//            }   // case

//            default:
//                return value;
//        }   // switch
//    }   // if

//    return QVariant();
}   // data

void UePeopleModel::ueRefresh()
{
    this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE);
}   // ueRefresh

void UePeopleModel::ueGenerateRoleNames()
{
    this->ueRoleNames().clear();
    for(int iIndex=0; iIndex<this->record().count(); iIndex++)
    {
        this->ueRoleNames().insert(Qt::UserRole+1+iIndex,
                                   this->record().fieldName(iIndex).toUtf8());
    }   // for
}   // ueGenerateRoleNames

【问题讨论】:

    标签: c++ mysql qt qml


    【解决方案1】:

    默认的 QML 图像提供程序只能使用 URL 或文件路径。如果您想从 C++ 图像类加载 QML 图像,例如 QPixmapQImage,您将不得不着手实现自己的图像提供程序。我已经描述了one possible implementation strategy here

    之后就相当简单了,data() 方法将不会返回包裹在 QVariant 中的图像,而只是针对自定义图像提供程序的自定义图像 URL,这就是您将要使用的内容QML 委托。自然,在数据库中,您仍然会有一个 blob,并且您仍将使用fromData() 方法来构造图像,但是图像提供程序将用于将自定义图像源字符串与实际图像相关联。自然,您必须找到一种方法来控制实际图像的生命周期,以免发生内存泄漏。我的建议是实现上面列出的答案中的 Pixmap 项之类的东西,并使其成为您的代表的一部分 - 这样在不再需要时将删除图像。但是,您还需要为Pixmap 实现setData(),并以文本形式传递QPixmap 指针并将其存储在pix 中。

    不将图像存储在数据库中可能更容易和更明智,但作为常规文件,只需将其相对路径存储在数据库中,它会为您省去一些麻烦。至于“如何检索数据”这个问题——我想说去那里,实际上是read the documentation...

    【讨论】:

    • 会按照你的方式进行,我同意不将图像存储在数据库中,但此时,系统是原样的,不是我开发的,我只是在做眼睛糖果客户端(Qt/ QML),适用于 android 设备。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    • 2013-03-24
    • 1970-01-01
    • 2019-05-30
    • 2013-04-02
    • 2015-12-03
    相关资源
    最近更新 更多