最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++數(shù)據(jù)模型應(yīng)用在QML委托代理機制中

 更新時間:2022年08月25日 11:00:40   作者:碼農(nóng)飛飛  
這篇文章主要介紹了在QML委托代理機制中使用C++數(shù)據(jù)模型,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

之前文章中介紹過在Qt-Widget和QML中如何使用委托代理機制(Model-View-Delegate),對應(yīng)的文章鏈接分別如下所示:

QT中Model-View-Delegate委托代理機制

QML基礎(chǔ)

在開發(fā)的過程中發(fā)現(xiàn)在QML中直接定義操作數(shù)據(jù)模型比較繁瑣費力,不如C++的數(shù)據(jù)模型好用。這里就介紹一下如何在QML中調(diào)用C++定義的數(shù)據(jù)模型,實現(xiàn)數(shù)據(jù)模型的混合使用。

定義數(shù)據(jù)模型

定義的C++數(shù)據(jù)模型和Qt-Widget中定義的數(shù)據(jù)模型相同。模型主要用來存儲本地圖片的ID的對應(yīng)的圖片地址。

實現(xiàn)如下:

//picturemodel.h
#ifndef PICTUREMODEL_H
#define PICTUREMODEL_H
#include <memory>
#include <vector>
#include <QAbstractListModel>
#include <QUrl>
class Picture
{
public:
    Picture(const QString & filePath = "")
    {
         mPictureUrl = QUrl::fromLocalFile(filePath);
    }
    Picture(const QUrl& fileUrl)
    {
        mPictureUrl = fileUrl;
    }
    int pictureId() const
    {
        return mPictureId;
    }
    void setPictureId(int pictureId)
    {
        mPictureId = pictureId;
    }
    QUrl pictureUrl() const
    {
        return mPictureUrl;
    }
    void setPictureUrl(const QUrl &pictureUrl)
    {
        mPictureUrl = pictureUrl;
    }
private:
    int mPictureId;   // 圖片ID
    QUrl mPictureUrl; //圖片的地址
};
class PictureModel : public QAbstractListModel
{
    Q_OBJECT
public:
    //自定義每個元素的數(shù)據(jù)類型
    enum Roles {
        UrlRole = Qt::UserRole + 1,
        FilePathRole
    };
    PictureModel(QObject* parent = 0);
    //向數(shù)據(jù)模型中添加單個數(shù)據(jù)
    QModelIndex addPicture(const Picture& picture);
    Q_INVOKABLE void addPictureFromUrl(const QUrl& fileUrl);
    //模型的行數(shù)
    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
    //獲取某個元素的數(shù)據(jù)
    QVariant data(const QModelIndex& index, int role) const override;
    //刪除某幾行數(shù)據(jù)
    Q_INVOKABLE bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
    //每個元素類別的名稱
    QHash<int, QByteArray> roleNames() const override;
    //加載用戶圖片
    Q_INVOKABLE void loadPictures();
    //清空模型的中的數(shù)據(jù),但不移除本地文件數(shù)據(jù)
    void clearPictures();
public slots:
    //清空模型,刪除本地文件中的數(shù)據(jù)
    void deleteAllPictures();
private:
    void resetPictures();
    bool isIndexValid(const QModelIndex& index) const;
private:
    std::unique_ptr<std::vector<std::unique_ptr<Picture>>> mPictures;
};
#endif // PICTUREMODEL_H
//picturemodel.cpp
#include "picturemodel.h"
#include <QUrl>
using namespace std;
PictureModel::PictureModel(QObject* parent) :
    QAbstractListModel(parent),
    mPictures(new vector<unique_ptr<Picture>>())
{
}
QModelIndex PictureModel::addPicture(const Picture& picture)
{
    int rows = rowCount();
    beginInsertRows(QModelIndex(), rows, rows);
    unique_ptr<Picture>newPicture(new Picture(picture));
    mPictures->push_back(move(newPicture));
    endInsertRows();
    return index(rows, 0);
}
void PictureModel::addPictureFromUrl(const QUrl& fileUrl)
{
    addPicture(Picture(fileUrl));
}
int PictureModel::rowCount(const QModelIndex& /*parent*/) const
{
    return mPictures->size();
}
QVariant PictureModel::data(const QModelIndex& index, int role) const
{
    if (!isIndexValid(index))
    {
        return QVariant();
    }
    const Picture& picture = *mPictures->at(index.row());
    switch (role) {
        //展示數(shù)據(jù)為圖片的名稱
        case Qt::DisplayRole:
            return picture.pictureUrl().fileName();
            break;
        //圖片的URL
        case Roles::UrlRole:
            return picture.pictureUrl();
            break;
        //圖片地址
        case Roles::FilePathRole:
            return picture.pictureUrl().toLocalFile();
            break;
        default:
            return QVariant();
    }
}
bool PictureModel::removeRows(int row, int count, const QModelIndex& parent)
{
    if (row < 0
            || row >= rowCount()
            || count < 0
            || (row + count) > rowCount()) {
        return false;
    }
    beginRemoveRows(parent, row, row + count - 1);
    int countLeft = count;
    while(countLeft--) {
        const Picture& picture = *mPictures->at(row + countLeft);
    }
    mPictures->erase(mPictures->begin() + row,
                    mPictures->begin() + row + count);
    endRemoveRows();
    return true;
}
QHash<int, QByteArray> PictureModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[Qt::DisplayRole] = "name";
    roles[Roles::FilePathRole] = "filepath";
    roles[Roles::UrlRole] = "url";
    return roles;
}
void PictureModel::loadPictures()
{
    beginResetModel();
    endResetModel();
}
void PictureModel::clearPictures()
{
    resetPictures();
}
void PictureModel::resetPictures()
{   
    beginResetModel();
    mPictures.reset(new vector<unique_ptr<Picture>>());
    endResetModel();
    return;
}
void PictureModel::deleteAllPictures()
{
    resetPictures();
}
bool PictureModel::isIndexValid(const QModelIndex& index) const
{
    if (index.row() < 0
            || index.row() >= rowCount()
            || !index.isValid()) {
        return false;
    }
    return true;
}

定義C++數(shù)據(jù)模型的時候有幾點需要注意:

1.如果想在QML中訪問模型的某個方法的話需要在方法聲明的時候添加Q_INVOKABLE宏

Q_INVOKABLE void addPictureFromUrl(const QUrl& fileUrl);

2.在QML中通過每個元素類別的名稱來進行訪問,對應(yīng)的類別名稱的定義如下:

QHash<int, QByteArray> PictureModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[Qt::DisplayRole] = "name";
    roles[Roles::FilePathRole] = "filepath";
    roles[Roles::UrlRole] = "url";
    return roles;
}

定義圖片緩存器

由于數(shù)據(jù)模型中包含圖片數(shù)據(jù),為了便于在QML中訪問圖片資源,添加圖片緩存器。緩存器繼承自QQuickImageProvider。對應(yīng)的實現(xiàn)如下所示:

//PictureImageProvider.h
#ifndef PICTUREIMAGEPROVIDER_H
#define PICTUREIMAGEPROVIDER_H
#include <QQuickImageProvider>
#include <QCache>
class PictureModel;
class PictureImageProvider : public QQuickImageProvider
{
public:
    static const QSize THUMBNAIL_SIZE;
    PictureImageProvider(PictureModel* pictureModel);
    //請求圖片
    QPixmap requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) override;
    //獲取緩存
    QPixmap* pictureFromCache(const QString& filepath, const QString& pictureSize);
private:
    //數(shù)據(jù)模型
    PictureModel* mPictureModel;
    //圖片緩存容器
    QCache<QString, QPixmap> mPicturesCache;
};
#endif // PICTUREIMAGEPROVIDER_H
//PictureImageProvider.cpp
#include "PictureImageProvider.h"
#include "PictureModel.h"
//全屏顯示
const QString PICTURE_SIZE_FULL = "full";
//縮略顯示
const QString PICTURE_SIZE_THUMBNAIL = "thumbnail";
//縮略顯示的尺寸
const QSize PictureImageProvider::THUMBNAIL_SIZE = QSize(350, 350);
PictureImageProvider::PictureImageProvider(PictureModel* pictureModel) :
    QQuickImageProvider(QQuickImageProvider::Pixmap),
    mPictureModel(pictureModel),
    mPicturesCache()
{
}
QPixmap PictureImageProvider::requestPixmap(const QString& id, QSize* /*size*/, const QSize& /*requestedSize*/)
{
    QStringList query = id.split('/');
    if (!mPictureModel || query.size() < 2) {
        return QPixmap();
    }
    //第幾個圖片數(shù)據(jù)
    int rowId = query[0].toInt();
    //顯示模式是縮略顯示還是全屏顯示
    QString pictureSize = query[1];
    QUrl fileUrl = mPictureModel->data(mPictureModel->index(rowId, 0), PictureModel::Roles::UrlRole).toUrl();
    return *pictureFromCache(fileUrl.toLocalFile(), pictureSize);
}
QPixmap* PictureImageProvider::pictureFromCache(const QString& filepath, const QString& pictureSize)
{
    QString key = QStringList{ pictureSize, filepath }
                    .join("-");
    //不包含圖片的時候創(chuàng)建新的緩存
    QPixmap* cachePicture = nullptr;
    if (!mPicturesCache.contains(key))
    {
        QPixmap originalPicture(filepath);
        if (pictureSize == PICTURE_SIZE_THUMBNAIL)
        {
            cachePicture = new QPixmap(originalPicture
                                  .scaled(THUMBNAIL_SIZE,
                                          Qt::KeepAspectRatio,
                                          Qt::SmoothTransformation));
        }
        else if (pictureSize == PICTURE_SIZE_FULL)
        {
            cachePicture = new QPixmap(originalPicture);
        }
        mPicturesCache.insert(key, cachePicture);
    }
    //包含的時候直接訪問緩存
    else
    {
        cachePicture = mPicturesCache[key];
    }
    return cachePicture;
}

初始化QML引擎

在QML引擎初始化的時候添加對應(yīng)的數(shù)據(jù)模型和圖片緩存器,對應(yīng)的實現(xiàn)如下:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "picturemodel.h"
#include "PictureImageProvider.h"
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    PictureModel pictureModel;
    QQmlApplicationEngine engine;
    QQmlContext* context = engine.rootContext();
    //添加數(shù)據(jù)模型和圖片緩存器
    context->setContextProperty("pictureModel", &pictureModel);
    //圖片Provider的ID是"pictures"
    engine.addImageProvider("pictures", new PictureImageProvider(&pictureModel));
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    return app.exec();
}

QML中訪問C++數(shù)據(jù)模型

在QML中通過數(shù)據(jù)模型訪問數(shù)據(jù),通過圖片緩存器訪問對應(yīng)的圖片資源,對應(yīng)的實現(xiàn)如下:

//main.qml
import QtQuick 2.8
import QtQuick.Dialogs 1.2
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import QtQuick.Window 2.2
Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("QML-MVC")
    RowLayout {
        id:tool_layout
        //添加圖片的按鈕
        ToolButton {
            background: Image {
                source: "qrc:/image/photo-add.svg"
            }
            onClicked: {
                dialog.open()
            }
        }
        //刪除圖片的按鈕
        ToolButton {
            background: Image {
                source: "qrc:/image/photo-delete.svg"
            }
            onClicked: {
                pictureModel.removeRows(pictureListView.currentIndex,1)
            }
        }
    }
    //網(wǎng)格視圖
    GridView {
        id: pictureListView
        model: pictureModel
        anchors.top:tool_layout.bottom
        width: parent.width;
        height: parent.height - tool_layout.height
        anchors.leftMargin: 10
        anchors.rightMargin: 10
        cellWidth : 300
        cellHeight: 230
        //對應(yīng)的每個元素的代理
        delegate: Rectangle {
            width: 290
            height: 200
            color: GridView.isCurrentItem?"#4d9cf8":"#ffffff" //選中顏色設(shè)置
            Image {
                id: thumbnail
                anchors.fill: parent
                fillMode: Image.PreserveAspectFit
                cache: false
                //通過緩存器訪問圖片
                //image://pictures/訪問器的ID
                //index + "/thumbnail" 圖片索引和顯示模式
                source: "image://pictures/" + index + "/thumbnail"
            }
            //訪問圖片的名稱
            Text {
                height: 30
                anchors.top: thumbnail.bottom
                text: name
                font.pointSize: 16
                anchors.horizontalCenter: parent.horizontalCenter
            }
            //鼠標(biāo)點擊設(shè)置當(dāng)前索引
            MouseArea{
                anchors.fill: parent
                onClicked: {
                    pictureListView.currentIndex = index;
                }
            }
        }
    }
    //圖片選擇窗口
    FileDialog {
        id: dialog
        title: "Select Pictures"
        folder: shortcuts.pictures
        onAccepted: {
            var pictureUrl = dialog.fileUrl
            pictureModel.addPictureFromUrl(pictureUrl)
            dialog.close()
        }
    }
}

顯示效果如下圖所示:

到此這篇關(guān)于C++數(shù)據(jù)模型應(yīng)用在QML委托代理機制中的文章就介紹到這了,更多相關(guān)C++數(shù)據(jù)模型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言編程時常犯十八個錯誤小結(jié)

    C語言編程時常犯十八個錯誤小結(jié)

    C語言的最大特點是:功能強、使用方便靈活。C編譯的程序?qū)φZ法檢查并不象其它高級語言那么嚴(yán)格,這就給編程人員留下“靈活的余地”,但還是由于這個靈活給程序的調(diào)試帶來了許多不便,尤其對初學(xué)C語言的人來說,經(jīng)常會出一些連自己都不知道錯在哪里的錯誤
    2013-07-07
  • C++ XML庫用法詳解

    C++ XML庫用法詳解

    TinyXML-2是C++中一個輕量級、易于使用的XML解析庫,支持XML的讀取和寫入,內(nèi)存占用小,適合嵌入式系統(tǒng),本文給大家介紹C++ XML庫用法,感興趣的朋友一起看看吧
    2025-03-03
  • Qt5.14.2使用虛擬鍵盤的關(guān)鍵代碼

    Qt5.14.2使用虛擬鍵盤的關(guān)鍵代碼

    對于Qwidget程序,使用qtvirtualkeyboard彈出鍵盤之后,鍵盤會浮于表面。使用VirtualkeyboardPushView模塊,自動根據(jù)情況把輸入視圖往上面推移,這篇文章主要介紹了Qt5.14.2使用虛擬鍵盤的關(guān)鍵代碼,需要的朋友可以參考下
    2022-09-09
  • C語言的數(shù)據(jù)結(jié)構(gòu)之樹、森連、二叉樹之間的轉(zhuǎn)換圖解

    C語言的數(shù)據(jù)結(jié)構(gòu)之樹、森連、二叉樹之間的轉(zhuǎn)換圖解

    這篇文章主要介紹了C語言的數(shù)據(jù)結(jié)構(gòu)之樹、森連、二叉樹之間的轉(zhuǎn)換詳解,數(shù)據(jù)是信息的載體,是描述客觀事物屬性的數(shù)、字符以及所有能輸入到計算機中并被程序識別和處理的符號的集合,需要的朋友可以參考下
    2023-07-07
  • C++中Lambda表達式的語法與實例

    C++中Lambda表達式的語法與實例

    C++ 11 中的 Lambda 表達式用于定義并創(chuàng)建匿名的函數(shù)對象,以簡化編程工作,下面這篇文章主要給大家介紹了關(guān)于C++中Lambda表達式的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-10-10
  • 深入了解C語言棧的創(chuàng)建

    深入了解C語言棧的創(chuàng)建

    棧只允許在一端進行插入或刪除操作的線性表。首先棧是一種線性表,但是限定這種線性表只能在某一端進行插入和刪除操作,這篇文章主要介紹了C語言對棧的實現(xiàn)基本操作
    2021-07-07
  • 一文詳解C++17中的結(jié)構(gòu)化綁定

    一文詳解C++17中的結(jié)構(gòu)化綁定

    C++17中的結(jié)構(gòu)化綁定(structured binding)是指將指定名稱綁定到初始化程序的子對象或元素,本文主要來和大家聊聊C++17中結(jié)構(gòu)化綁定的實現(xiàn),感興趣的小伙伴可以了解下
    2023-12-12
  • opengl繪制五星紅旗

    opengl繪制五星紅旗

    這篇文章主要為大家詳細(xì)介紹了opengl繪制五星紅旗的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • c++分離講解模板的概念與使用

    c++分離講解模板的概念與使用

    人們需要編寫多個形式和功能都相似的函數(shù),因此有了函數(shù)模板來減少重復(fù)勞動;人們也需要編寫多個形式和功能都相似的類,于是 C++ 引人了類模板的概念,編譯器從類模板可以自動生成多個類,避免了程序員的重復(fù)勞動
    2022-04-04
  • C++關(guān)鍵字const使用方法詳解

    C++關(guān)鍵字const使用方法詳解

    C語言中的const與C++有很大的不同,在C語言中用const修飾的變量仍是一個變量,表示這個變量是只讀的,不可顯示地更改,C++中的const關(guān)鍵字的用法非常靈活,而使用const將大大改善程序的健壯性,const關(guān)鍵字是一種修飾符
    2022-12-12

最新評論

河曲县| 容城县| 施甸县| 齐齐哈尔市| 大理市| 弥勒县| 水富县| 安岳县| 玛多县| 孟州市| 大港区| 桂阳县| 正定县| 榕江县| 黄山市| 图木舒克市| 长乐市| 和林格尔县| 温宿县| 汨罗市| 沙田区| 阿鲁科尔沁旗| 郯城县| 临洮县| 大田县| 钟山县| 三河市| 彰武县| 鄂伦春自治旗| 湛江市| 那曲县| 巴马| 开化县| 镇江市| 丰台区| 余姚市| 伊金霍洛旗| 广宗县| 巩留县| 宝丰县| 广德县|