0


QT中Model-View-Delegate委托代理机制用法介绍

文章目录

之前的一篇文章中介绍过QT的委托代理机制,那时候由于理解的比较浅就简单的给了一个例子。最近又做了一部分相关的工作,发现之前的理解有点问题。这里就详细的介绍一下QT的委托代理机制的用法,希望对大家有帮助。

Model-View-Delegate机制可以简单的理解为将本地的一些数据以特定的UI形式呈现出来。常见的数据结构包括列表数据(list)、表格数据(table)、树状数据(tree),分别对应着QT中的QListView、QTableView、QTreeView控件。本地数据和视图代理之间的关系如下图所示:
在这里插入图片描述

数据模型中的数据来源可以是本地的XML文件、JSON文件、二进制数据,也可以数据库中的数据表。这些数据源中的数据按照一定的结构加载到对应的数据模型中,我们可以通过操作数据模型中的数据来间接的操作数据源中的数据。

有时候,我们需要对数据模型中的数据进行二次处理,包括数据筛选、数据排序、数据处理等等,这时候我们就得需要引入模型代理,负责对数据模型进行处理。当然模型代理不是必须的。QT中的模型代理有两种都是QAbstractProxyModel的子类。分别是QIdentityProxyModel和QSortFilterProxyModel。
QIdentityProxyModel代理不会修改原有的数据模型,只是重写了data()函数,对返回视图的数据进行了重新组合和修改。
QSortFilterProxyModel代理会对模型的数据进行筛选和排序。
有了这两个代理类,我们就可以对模型中的数据进行处理了。

数据模型加载完毕数据之后,View层就会对数据模型中的数据进行呈现了。由于数据模型中的数据都是以一个个数据单元存在的,我们可以为每个数据单元指定对应的UI。这就用到了委托代理Delegate,委托控件可以给数据模型中的每一个元素指定固定的UI。通过委托代理的机制,我们就可以以个性的图形界面呈现本地数据了。

下面以一个详细的例子,来说明一下委托代理机制的用法。例子主要功能是以缩略图的形式对本地的图片文件进行管理,类似于一个图片管理器。

本地数据加载(Data)

例子中的图片数据主要包含两个字段,一个字段是图片的ID,另一个字段是图片的URL。对应的数据结构如下所示:

//PictureclassPicture{public:Picture(const QString & filePath =""){
         mPictureUrl =QUrl::fromLocalFile(filePath);}Picture(const QUrl& fileUrl){
        mPictureUrl = fileUrl;}intpictureId()const{return mPictureId;}voidsetPictureId(int pictureId){
        mPictureId = pictureId;}

    QUrl pictureUrl()const{return mPictureUrl;}voidsetPictureUrl(const QUrl &pictureUrl){
        mPictureUrl = pictureUrl;}private:int mPictureId;// 图片ID
    QUrl mPictureUrl;//图片的地址};

由于本地的图片数据可能会很多,为了方便对大量的图片数据进行管理,这里我们采用SQLITE数据库对图片信息进行本地持久化。首先,我们新建数据库管理类,管理数据库连接。

//DatabaseManager.h#ifndefDATABASEMANAGER_H#defineDATABASEMANAGER_H#include<memory>#include<QString>#include"PictureDao.h"classQSqlQuery;classQSqlDatabase;const QString DATABASE_FILENAME ="picture.db";classDatabaseManager{public:staticvoiddebugQuery(const QSqlQuery& query);//数据库管理类是单例模式static DatabaseManager&instance();~DatabaseManager();protected://用来构建固定名称的数据库DatabaseManager(const QString& path = DATABASE_FILENAME);
    DatabaseManager&operator=(const DatabaseManager& rhs);private:
    std::unique_ptr<QSqlDatabase> mDatabase;public://图片数据操作类const PictureDao mpictureDao;};#endif// DATABASEMANAGER_H
//DatabaseManager.cpp#include"DatabaseManager.h"#include<QSqlDatabase>#include<QDebug>#include<QSqlError>#include<QSqlQuery>voidDatabaseManager::debugQuery(const QSqlQuery& query){if(query.lastError().type()== QSqlError::ErrorType::NoError){qDebug()<<"Query OK:"<< query.lastQuery();}else{qWarning()<<"Query KO:"<< query.lastError().text();qWarning()<<"Query text:"<< query.lastQuery();}}

DatabaseManager&DatabaseManager::instance(){static DatabaseManager singleton;return singleton;}DatabaseManager::DatabaseManager(const QString& path):mDatabase(newQSqlDatabase(QSqlDatabase::addDatabase("QSQLITE"))),mpictureDao(*mDatabase){
    mDatabase->setDatabaseName(path);bool openStatus = mDatabase->open();qDebug()<<"Database connection: "<<(openStatus ?"OK":"Error");
    mpictureDao.init();}DatabaseManager::~DatabaseManager(){
    mDatabase->close();}

完成数据库管理类的创建之后,我们需要添加图片数据表的数据库访问对象,访问对象负责完成对图片数据表的增删改查等基本操作,对应的实现如下所示:

//PictureDao.h#ifndefPICTUREDAO_H#definePICTUREDAO_H#include<memory>#include<vector>classQSqlDatabase;classPicture;classPictureDao{public:explicitPictureDao(QSqlDatabase& database);voidinit()const;//添加图片voidaddPicture(Picture& picture)const;//删除图片voidremovePicture(int id)const;//加载图片
    std::unique_ptr<std::vector<std::unique_ptr<Picture>>>loadPictures()const;//删除所有的数据voidremoveAllPictures()const;private:
    QSqlDatabase& mDatabase;};#endif// PICTUREDAO_H
//PictureDao.cpp#include"PictureDao.h"#include<QSqlDatabase>#include<QSqlQuery>#include<QVariant>#include"DatabaseManager.h"#include"picturemodel.h"usingnamespace std;PictureDao::PictureDao(QSqlDatabase& database):mDatabase(database){}voidPictureDao::init()const{if(!mDatabase.tables().contains("pictures")){
        QSqlQuery query(mDatabase);
        query.exec(QString("CREATE TABLE pictures")+" (id INTEGER PRIMARY KEY AUTOINCREMENT, "+"url TEXT)");DatabaseManager::debugQuery(query);}}voidPictureDao::addPicture(Picture& picture)const{
    QSqlQuery query(mDatabase);
    query.prepare(QString("INSERT INTO pictures")+" (url)"+" VALUES ("+":url"+")");
    query.bindValue(":url", picture.pictureUrl());
    query.exec();DatabaseManager::debugQuery(query);
    picture.setPictureId(query.lastInsertId().toInt());}voidPictureDao::removePicture(int id)const{
    QSqlQuery query(mDatabase);
    query.prepare("DELETE FROM pictures WHERE id = (:id)");
    query.bindValue(":id", id);
    query.exec();DatabaseManager::debugQuery(query);}

unique_ptr<vector<unique_ptr<Picture>>>PictureDao::loadPictures()const{
    QSqlQuery query(mDatabase);
    query.prepare("SELECT * FROM pictures");
    query.exec();DatabaseManager::debugQuery(query);
    unique_ptr<vector<unique_ptr<Picture>>>list(newvector<unique_ptr<Picture>>());while(query.next()){
        unique_ptr<Picture>picture(newPicture());
        picture->setPictureId(query.value("id").toInt());
        picture->setPictureUrl(query.value("url").toString());
        list->push_back(move(picture));}return list;}voidPictureDao::removeAllPictures()const{
    QSqlQuery query(mDatabase);
    query.prepare("DELETE FROM pictures WHERE 1=1");
    query.exec();DatabaseManager::debugQuery(query);}

完成数据访问层的构建之后,我们的应用就具备了对底层原始数据操作的能力。这个是应用的基础能力。

添加数据模型(Model)

完成了数据操作类之后,接下来我们就需要构建对应的数据模型了。由于图片信息之间是没有关联关系的所以这里采用的是基于QAbstractListModel的列表数据模型,对应的实现如下所示:

//picturemodel.h#ifndefPICTUREMODEL_H#definePICTUREMODEL_H#include<memory>#include<vector>#include<QAbstractListModel>#include<QUrl>#include"DatabaseManager.h"classPictureModel:publicQAbstractListModel{
    Q_OBJECT
public://自定义每个元素的数据类型enumRoles{
        UrlRole = Qt::UserRole +1,
        FilePathRole
    };PictureModel(QObject* parent =0);//向数据模型中添加单个数据
    QModelIndex addPicture(const Picture& picture);
    Q_INVOKABLE voidaddPictureFromUrl(const QUrl& fileUrl);//模型的行数introwCount(const QModelIndex& parent =QModelIndex())constoverride;//获取某个元素的数据
    QVariant data(const QModelIndex& index,int role)constoverride;//删除某几行数据
    Q_INVOKABLE boolremoveRows(int row,int count,const QModelIndex& parent =QModelIndex())override;//每个元素类别的名称
    QHash<int, QByteArray>roleNames()constoverride;//加载用户图片
    Q_INVOKABLE voidloadPictures();//清空模型的中的数据,但不移除本地文件数据voidclearPictures();public slots://清空模型,删除本地文件中的数据voiddeleteAllPictures();private:voidresetPictures();boolisIndexValid(const QModelIndex& index)const;private:
    DatabaseManager& mDatabase;
    std::unique_ptr<std::vector<std::unique_ptr<Picture>>> mPictures;};#endif// PICTUREMODEL_H
//picturemodel.cpp#include"picturemodel.h"#include<QUrl>usingnamespace std;PictureModel::PictureModel(QObject* parent):QAbstractListModel(parent),mPictures(newvector<unique_ptr<Picture>>()),mDatabase(DatabaseManager::instance()){}

QModelIndex PictureModel::addPicture(const Picture& picture){int rows =rowCount();beginInsertRows(QModelIndex(), rows, rows);
    unique_ptr<Picture>newPicture(newPicture(picture));
    mDatabase.mpictureDao.addPicture(*newPicture);
    mPictures->push_back(move(newPicture));endInsertRows();returnindex(rows,0);}voidPictureModel::addPictureFromUrl(const QUrl& fileUrl){addPicture(Picture(fileUrl));}intPictureModel::rowCount(const QModelIndex&/*parent*/)const{return mPictures->size();}

QVariant PictureModel::data(const QModelIndex& index,int role)const{if(!isIndexValid(index)){returnQVariant();}const Picture& picture =*mPictures->at(index.row());switch(role){//展示数据为图片的名称case Qt::DisplayRole:return picture.pictureUrl().fileName();break;//图片的URLcase Roles::UrlRole:return picture.pictureUrl();break;//图片地址case Roles::FilePathRole:return picture.pictureUrl().toLocalFile();break;default:returnQVariant();}}boolPictureModel::removeRows(int row,int count,const QModelIndex& parent){if(row <0|| row >=rowCount()|| count <0||(row + count)>rowCount()){returnfalse;}beginRemoveRows(parent, row, row + count -1);int countLeft = count;while(countLeft--){const Picture& picture =*mPictures->at(row + countLeft);
        mDatabase.mpictureDao.removePicture(picture.pictureId());}
    mPictures->erase(mPictures->begin()+ row,
                    mPictures->begin()+ row + count);endRemoveRows();returntrue;}

QHash<int, QByteArray>PictureModel::roleNames()const{
    QHash<int, QByteArray> roles;
    roles[Qt::DisplayRole]="name";
    roles[Roles::FilePathRole]="filepath";
    roles[Roles::UrlRole]="url";return roles;}voidPictureModel::loadPictures(){beginResetModel();
    mPictures = mDatabase.mpictureDao.loadPictures();endResetModel();}voidPictureModel::clearPictures(){resetPictures();}voidPictureModel::resetPictures(){beginResetModel();
    mPictures.reset(newvector<unique_ptr<Picture>>());endResetModel();return;}voidPictureModel::deleteAllPictures(){
    mDatabase.mpictureDao.removeAllPictures();resetPictures();}boolPictureModel::isIndexValid(const QModelIndex& index)const{if(index.row()<0|| index.row()>=rowCount()||!index.isValid()){returnfalse;}returntrue;}

QT允许开发者针对数据模型中的每个数据单元ModelIndex定义不同的数据角色。简单来说,就是每个数据单元可以提供各种类型的供外部使用的数据。这里我们定义了UrlRole和FilePathRole分别代表着图片的URL和图片的地址。

添加代理模型(Proxy)

模型代理就是对原始模型中的数据进行二次处理,包括排序筛选等等操作。模型代理不能直接修改模型中的数据,只是负责对数据模型中的数据进行二次处理操作。同时模型代理也不是必须的,我们也可以直接用原始的数据模型和视图进行交互。模型代理对应的实现如下所示:

//picproxymodel.h#ifndefPICTURE_PROXY_MODEL_H#definePICTURE_PROXY_MODEL_H#include<QIdentityProxyModel>#include<QHash>#include<QPixmap>classPictureModel;classPictureProxyModel:publicQIdentityProxyModel{public:PictureProxyModel(QObject* parent =0);//通过重写data接口对数据进行二次处理
    QVariant data(const QModelIndex& index,int role)constoverride;//设置获取源数据模型voidsetSourceModel(QAbstractItemModel* sourceModel)override;
    PictureModel*pictureModel()const;private://重新加载缩略图voidreloadPictures();//生成缩略图voidgeneratePictures(const QModelIndex& startIndex,int count);private:
   QHash<QString, QPixmap*>mPictureHashMaps;};#endif
//picproxymodel.cpp#include"picproxymodel.h"#include"PictureModel.h"constunsignedint PICTURE_SIZE =350;PictureProxyModel::PictureProxyModel(QObject* parent):QIdentityProxyModel(parent),mPictureHashMaps(){}

QVariant PictureProxyModel::data(const QModelIndex& index,int role)const{//对原始数据模型中的数据进行二次加工处理//供前端调用if(role != Qt::DecorationRole){returnQIdentityProxyModel::data(index, role);}

    QString filepath =sourceModel()->data(index, PictureModel::Roles::FilePathRole).toString();return*mPictureHashMaps[filepath];}voidPictureProxyModel::setSourceModel(QAbstractItemModel* sourceModel){QIdentityProxyModel::setSourceModel(sourceModel);if(!sourceModel){return;}connect(sourceModel,&QAbstractItemModel::modelReset,[this]{reloadPictures();});connect(sourceModel,&QAbstractItemModel::rowsInserted,[this](const QModelIndex&/*parent*/,int first,int last){generatePictures(index(first,0), last - first +1);});}

PictureModel*PictureProxyModel::pictureModel()const{returnstatic_cast<PictureModel*>(sourceModel());}voidPictureProxyModel::reloadPictures(){qDeleteAll(mPictureHashMaps);
    mPictureHashMaps.clear();generatePictures(index(0,0),rowCount());}voidPictureProxyModel::generatePictures(const QModelIndex& startIndex,int count){if(!startIndex.isValid()){return;}const QAbstractItemModel* model = startIndex.model();int lastIndex = startIndex.row()+ count;for(int row = startIndex.row(); row < lastIndex; row++){
        QString filepath = model->data(model->index(row,0), PictureModel::Roles::FilePathRole).toString();
        QPixmap pixmap(filepath);auto thumbnail =newQPixmap(pixmap.scaled(PICTURE_SIZE, PICTURE_SIZE,Qt::KeepAspectRatio,
                                             Qt::SmoothTransformation));
        mPictureHashMaps.insert(filepath, thumbnail);}}

添加元素的代理(Delegate)

元素代理就是数据表中每个元素对应的UI,我们通过自定义的控件来呈现对应的数据。这里我们采用的是QStyledItemDelegate而不是QItemDelegate,是因为QStyledItemDelegate支持样式表的操作,而QItemDelegate不支持,对应的实现如下所示:

//picturedelegate.h#ifndefPICTUREDELEGATE_H#definePICTUREDELEGATE_H#include<QStyledItemDelegate>#include<QMouseEvent>classPictureDelegate:publicQStyledItemDelegate{
    Q_OBJECT
public:PictureDelegate(QObject* parent =0);//代理的绘制事件voidpaint(QPainter* painter,const QStyleOptionViewItem& option,const QModelIndex& index)constoverride;//代理的尺寸
    QSize sizeHint(const QStyleOptionViewItem& option,const QModelIndex& index)constoverride;protected:};#endif// PICTUREDELEGATE_H
//picturedelegate.cpp#include"picturedelegate.h"#include<QPainter>//标题栏的尺寸样式constunsignedint LABEL_HEIGHT =20;constunsignedint LABEL_COLOR =0x303030;constunsignedint LABEL_ALPHA =200;constunsignedint LABEL_TEXT_COLOR =0xffffff;constunsignedint HIGHLIGHT_ALPHA =100;//图片的尺寸样式constunsignedint PIXMAP_WIDTH =200;constunsignedint PIXMAP_HEIGHT =200;PictureDelegate::PictureDelegate(QObject* parent):QStyledItemDelegate(parent){}voidPictureDelegate::paint(QPainter* painter,const QStyleOptionViewItem& option,const QModelIndex& index)const{
    painter->save();//绘制对应的图片
    QPixmap pixmap = index.model()->data(index, Qt::DecorationRole).value<QPixmap>();
    painter->drawPixmap(option.rect.x(), option.rect.y(),PIXMAP_WIDTH,PIXMAP_HEIGHT,pixmap);//绘制图片的标题栏显示图片名称
    QRect bannerRect =QRect(option.rect.x(), option.rect.y(), PIXMAP_WIDTH, LABEL_HEIGHT);
    QColor bannerColor =QColor(LABEL_COLOR);
    bannerColor.setAlpha(LABEL_ALPHA);
    painter->fillRect(bannerRect, bannerColor);//绘制标题文字
    QString filename = index.model()->data(index, Qt::DisplayRole).toString();
    painter->setPen(LABEL_TEXT_COLOR);
    painter->drawText(bannerRect, Qt::AlignCenter, filename);//设置元素被选中之后的颜色if(option.state.testFlag(QStyle::State_Selected)){
        QColor selectedColor = option.palette.highlight().color();
        selectedColor.setAlpha(HIGHLIGHT_ALPHA);
        painter->fillRect(option.rect, selectedColor);}

    painter->restore();}

QSize PictureDelegate::sizeHint(const QStyleOptionViewItem&/*option*/,const QModelIndex& index)const{const QPixmap& pixmap = index.model()->data(index, Qt::DecorationRole).value<QPixmap>();returnQSize(PIXMAP_WIDTH,PIXMAP_HEIGHT);}

我们也可以通过实现QStyledItemDelegate::createEditor()接口,来对每一个元素代理中的数据进行编辑,这里就不详细介绍了,之前的文章中写过。

添加视图层(View)

完善了数据模型和元素代理之后,对应的视图层操作就比较简单了。视图层我们添加了和用户交互的接口,用户可以通过对应的UI操作,对数据模型中的数据进行增删改查。同时视图中我们为元素添加了菜单,我们可以通过右键菜单来删除某个特定的元素。

//mylistview.h#ifndefMYLISTVIEW_H#defineMYLISTVIEW_H#include<QWidget>#include<QItemSelectionModel>#include<QMouseEvent>#include<QMenu>namespace Ui {classMyListView;}classPictureProxyModel;classMyListView:publicQWidget{
    Q_OBJECT

public:explicitMyListView(QWidget *parent =0);~MyListView();//设置数据模型voidsetPictureModel(PictureProxyModel *pictureModel);//设置选中的数据模型voidsetPictureSelectionModel(QItemSelectionModel *selectionModel);private slots:voidaddPictures();voiddelPictures();voidclearPictures();voiddelAllPicture();voiddelCurrentPicture();voidshowCustomMenu(const QPoint& pos);private:
    Ui::MyListView *ui;//图片数据模型
    PictureProxyModel* mPictureModel;//选中元素的数据模型
    QItemSelectionModel* mPictureSelectionModel;
    QModelIndex mCurrentIndex;
    QMenu* m_func_menu =nullptr;
    QAction* m_del_current_pic =nullptr;};#endif// MYLISTVIEW_H
//mylistview.cpp#pragmaexecution_character_set("utf-8")#include"mylistview.h"#include"picturedelegate.h"#include"picproxymodel.h"#include"ui_mylistview.h"#include"picturemodel.h"#include<QFileDialog>#include<QInputDialog>#include<QStandardPaths>MyListView::MyListView(QWidget *parent):QWidget(parent),ui(new Ui::MyListView){
    ui->setupUi(this);//设置元素之间的间隔
    ui->pic_list_view->setSpacing(5);//设置尺寸变化策略
    ui->pic_list_view->setResizeMode(QListView::Adjust);//设置元素增减的时候的变化模式
    ui->pic_list_view->setFlow(QListView::LeftToRight);//设置伸缩的时候是否自动换行
    ui->pic_list_view->setWrapping(true);//设置每个元素的代理
    ui->pic_list_view->setItemDelegate(newPictureDelegate(this));//开启自定义的菜单
    ui->pic_list_view->setContextMenuPolicy(Qt::CustomContextMenu);//初始化功能菜单
    m_func_menu =newQMenu(this);
    m_del_current_pic =newQAction("删除当前图片",this);
    m_func_menu->addAction(m_del_current_pic);connect(m_del_current_pic,&QAction::triggered,this,&MyListView::delCurrentPicture);//对图片数据进行增删改查connect(ui->add_pic_btn,&QPushButton::clicked,this,&MyListView::addPictures);connect(ui->clear_btn,&QPushButton::clicked,this,&MyListView::clearPictures);connect(ui->del_pic_btn,&QPushButton::clicked,this,&MyListView::delPictures);connect(ui->del_all_pic_btn,&QPushButton::clicked,this,&MyListView::delAllPicture);connect(ui->pic_list_view,&QListView::customContextMenuRequested,this,&MyListView::showCustomMenu);}MyListView::~MyListView(){delete ui;}voidMyListView::setPictureModel(PictureProxyModel* pictureModel){
    mPictureModel = pictureModel;
    ui->pic_list_view->setModel(pictureModel);}voidMyListView::setPictureSelectionModel(QItemSelectionModel* selectionModel){
    mPictureSelectionModel = selectionModel;
    ui->pic_list_view->setSelectionModel(selectionModel);}voidMyListView::addPictures(){
    QStringList filenames =QFileDialog::getOpenFileNames(this,"添加图片",QStandardPaths::writableLocation(QStandardPaths::DesktopLocation),"Picture files (*.jpg *.png)");if(!filenames.isEmpty()){
        QModelIndex lastModelIndex;for(auto filename : filenames){
            Picture picture(filename);
            lastModelIndex = mPictureModel->pictureModel()->addPicture(picture);
            lastModelIndex = mPictureModel->index(lastModelIndex.row(),lastModelIndex.column());}if(lastModelIndex.isValid()){
            ui->pic_list_view->setCurrentIndex(lastModelIndex);}}}voidMyListView::delPictures(){if(mPictureSelectionModel->selectedIndexes().isEmpty()){return;}int row = mPictureSelectionModel->currentIndex().row();
    mPictureModel->sourceModel()->removeRow(row);//选中前一个图片
    QModelIndex previousModelIndex = mPictureModel->sourceModel()->index(row -1,0);if(previousModelIndex.isValid()){
        previousModelIndex = mPictureModel->index(previousModelIndex.row(),previousModelIndex.column());
        mPictureSelectionModel->setCurrentIndex(previousModelIndex, QItemSelectionModel::SelectCurrent);return;}//选中后一个图片
    QModelIndex nextModelIndex = mPictureModel->sourceModel()->index(row,0);if(nextModelIndex.isValid()){
        nextModelIndex = mPictureModel->index(nextModelIndex.row(),nextModelIndex.column());
        mPictureSelectionModel->setCurrentIndex(nextModelIndex, QItemSelectionModel::SelectCurrent);return;}}voidMyListView::clearPictures(){
    PictureModel* pic_model =(PictureModel*)mPictureModel->sourceModel();
    pic_model->clearPictures();}voidMyListView::delAllPicture(){
    PictureModel* pic_model =(PictureModel*)mPictureModel->sourceModel();
    pic_model->deleteAllPictures();}voidMyListView::delCurrentPicture(){if(mCurrentIndex.isValid()){
        PictureModel* pic_model =(PictureModel*)mPictureModel->sourceModel();
        pic_model->removeRow(mCurrentIndex.row());}}voidMyListView::showCustomMenu(const QPoint &pos){
    QPoint point = pos;
    mCurrentIndex = ui->pic_list_view->indexAt(pos);if(mCurrentIndex.isValid()&& mCurrentIndex.row()>=0){
        m_func_menu->exec(ui->pic_list_view->mapToGlobal(point));}}

完善了列表视图之后,我们就可以在主界面中,添加视图控件了,这也是UI层的最后一步操作了,对应的实现如下:

//mainwwindow.h#ifndefMAINWWINDOW_H#defineMAINWWINDOW_H#include<QWidget>#include"mylistview.h"namespace Ui {classMainwWindow;}classMainwWindow:publicQWidget{
    Q_OBJECT

public:explicitMainwWindow(QWidget *parent =0);~MainwWindow();private:
    MyListView* mListView=nullptr;};#endif// MAINWWINDOW_H
//mainwwindow.cpp#include"mainwwindow.h"#include"ui_mainwwindow.h"#include"picturemodel.h"#include"picproxymodel.h"#include<QHBoxLayout>MainwWindow::MainwWindow(QWidget *parent):QWidget(parent){
    mListView =newMyListView(this);

    PictureModel* pic_model =newPictureModel(this);
    PictureProxyModel* pic_proxy_model =newPictureProxyModel(this);
    pic_proxy_model->setSourceModel(pic_model);

    QItemSelectionModel* pictureSelectionModel =newQItemSelectionModel(pic_proxy_model,this);

    mListView->setPictureModel(pic_proxy_model);
    mListView->setPictureSelectionModel(pictureSelectionModel);

    pic_model->loadPictures();

    QHBoxLayout* main_layout =newQHBoxLayout(this);
    main_layout->addWidget(mListView);this->setLayout(main_layout);this->setFixedSize(910,600);}MainwWindow::~MainwWindow(){}

使用效果

在这里插入图片描述

标签: qt ui 开发语言

本文转载自: https://blog.csdn.net/yang1fei2/article/details/125625567
版权归原作者 码农飞飞 所有, 如有侵权,请联系我们删除。

“QT中Model-View-Delegate委托代理机制用法介绍”的评论:

还没有评论