Qt Model/View 架构

一、核心架构基础

1.1 Model(模型)介绍

  • Qt Model 是 Qt 的一个重要组件,用于管理和展示数据。它是 Qt 的 Model/View 架构的核心部分,用于将数据模型与其视图相分离,实现数据的高效处理和可视化呈现
  • Qt Model 可以理解成一组数据结构,其中包含了待展示的数据,以及有关这些数据的元数据信息,如列名、列类型、数据行数等。Qt Model 还提供了一系列接口,用于访问和操作这些数据,使得开发人员可以轻松地实现数据的增删改查等操作
  • Qt Model 支持多种数据模型,包括基于内存、文件、数据库等不同类型的数据源,开发人员可以根据实际需求选择合适的数据模型。此外,Qt Model 也提供了多种视图组件,如 QListView、QTableView、QTreeView 等,用于将数据以不同的方式展示出来,同时也支持自定义视图组件。

QStandardItemModel  现成表格模型,不用重写任何函数
QAbstractTableModel 自定义表格模型,要重写函数
QAbstractListModel 列表模型,要重写函数
QFileSystemModel 文件浏览器,读取本地磁盘/文件夹

1.2 View(视图)介绍

  • Qt View 是一个跨平台的应用程序,用于在多个设备上查看 RTSP 和 HTTP 播放器。它使用Qt框架的嵌入式Web服务器和界面库,为用户提供了一个简单、易用的图形用户界面,支持实时视频流的播放、录像回放、抓拍等功能。Qt View 可以运行在多个操作系统,包括 Windows,Linux,Android 和 iOS 等。它广泛应用于监控系统、视频会议、视频门禁、家庭安防等领域。Qt View 被广泛应用于开源软件中,例如 ZoneMinder、iSpy、Bluecherry 和 Zoneminder-Moonlight。
                                                                                  
QTableView 表格展示
QListView 列表展示
QTreeView 树形展示
  • 视图与模型的绑定:view->setModel(&model) (核心函数:绑定后view自动从model上获取数据

1.3 Delegate(代理)介绍

  • Qt Delegate是一种Qt框架中的重要组件,用于在数据模型和视图之间提供交互性。它可以用于自定义Qt控件的外观和行为,以满足特定的应用程序需求。
  • Qt Delegate通常用于实现以下功能:

    1. 为视图中的项目创建自定义外观,并定制数据的显示方式。

    2. 在编辑模式下,为单元格提供自定义编辑器以编辑数据。

    3. 实现特定的用户交互行为,如拖放、复制和粘贴等。

1.4 三者关系

image

总之,先通过建立模型,在通过视图绑定模型才能展示数据。


二、模型详细介绍

2.1 QFileSystemModel

  • QFileSystemModel是 Qt Model/View 架构中封装操作系统文件系统的专属模型,无需你手动读取文件、解析目录,就能自动同步本地文件 / 文件夹的所有信息(名称、路径、大小、类型、修改时间等),并完美适配QTreeView(树形目录)、QListView(文件列表)、QTableView(文件详情表格),是实现 “文件浏览器” 类功能的核心组件。
#include "mainwindow.h"
#include "modelextend.h"

#include<QObject>
#include <QApplication>
#include <QAbstractItemView>
#include <QAbstractItemModel>
#include <QSplitter>
#include <QFileSystemModel>
#include <QTreeView>
#include <QTableView>
#include <QListView>
#include <QModelIndex>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QFileSystemModel model;//获取磁盘文件目录的模型
    model.setRootPath("");//设置数据根目录
    QTreeView tree;//树形视图
    QListView list;//列表视图
    QTableView table;//表视图

    //设置视图模型(视图绑定模型)
    tree.setModel(&model);
    list.setModel(&model);
    table.setModel(&model);

    //详细说
    tree.setSelectionMode(QAbstractItemView::SingleSelection);
    list.setSelectionModel(tree.selectionModel());
    table.setSelectionModel(tree.selectionModel());


    //信号与槽
    //双击事件(lambda表达式)
    QObject::connect(&tree, &QTreeView::doubleClicked, [&](const QModelIndex index){
        list.setRootIndex(index);
    });

    QObject::connect(&tree, &QTableView::doubleClicked, [&](const QModelIndex index){
        table.setRootIndex(index);
    });

    //初始化一个分割窗口
    QSplitter *qsp = new QSplitter();
    qsp->addWidget(&tree);
    qsp->addWidget(&list);
    qsp->addWidget(&table);
    qsp->setWindowTitle("模型(Model)测试");
    qsp->show();
    return a.exec();
}
setSelectionMode 定义单个视图的选中规则(能选多少、以什么方式选) 仅当前视图
NoSelection  不可选中,纯展示
SingleSelection  仅单选,选新取消旧
MultiSelection  点击即多选(无需 Ctrl)
ExtendedSelection Ctrl + 点击多选、Shift + 点击选连续项
setSelectionModel 多个视图共享同一个选择模型(QItemSelectionModel 多视图联动  

 

2.2 QAbstractTableModel

  • QAbstractTableModel是 Qt Model/View 架构中专门用于定制表格数据展示的抽象类(继承自QAbstractItemModel),它本身无法直接实例化,必须通过继承并重写核心函数,才能将你自定义的数据源(如结构体、数组、数据库结果)绑定到QTableView等视图控件。相比开箱即用的QStandardItemModel,它更轻量、定制化更强,是实现复杂表格逻辑(如动态数据、条件样式、自定义编辑)的核心。

2.2.1 必重写函数

rowCount()   返回行数 int rowCount(const QModelIndex &parent) const override;
columnCount()   返回列数 int columnCount(const QModelIndex &parent) const override;
data()   返回单元格数据 QVariant data(const QModelIndex &index, int role) const override;

2.2.2 可扩展的重写函数

headerData()  设置表头文本 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
setData() 单元格编辑 virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override;
flags()  设置单元格属性 virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
insertRow()s/removeRows()/insertColumns()/removeColumns() 增删行列 virtual bool insertRows(int row, int count, const QModelIndex &parent) override;
    virtual bool insertColumns(int column, int count, const QModelIndex &parent) override;
    virtual bool removeRows(int row, int count, const QModelIndex &parent) override;
    virtual bool removeColumns(int column, int count, const QModelIndex &parent) override;
//------------------------------modelextend.h-------------------------------
#ifndef MODELEXTEND_H
#define MODELEXTEND_H

#include <QAbstractTableModel>
#include <QVector>
#include <QMap>


class ModelExtend : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit ModelExtend(QObject *parent = nullptr);


public:
    QVector<int> emphindex;
    QVector<int> empnameidex;

    QMap<int, QString> empno;
    QMap<int, QString> empname;
    QMap<int, QString> empdepartment;

    //创建字符串列表
    QStringList viewtabletitle;//标题名称

    void modelFunc();

    // QAbstractItemModel interface
public:
    int rowCount(const QModelIndex &parent) const override;//返回行
    int columnCount(const QModelIndex &parent) const override;//返回列
    QVariant data(const QModelIndex &index, int role) const override;//显示数据
    QVariant headerData(int section, Qt::Orientation orientation, int role) const override;//表头数据/标题
};

#endif // MODELEXTEND_H


///-------------------------modelextend.cpp--------------------------------------------------------
#include "modelextend.h"

ModelExtend::ModelExtend(QObject *parent)
    : QAbstractTableModel{parent}
{
    empno[1] = "2022001";
    empno[2] = "2022002";
    empno[3] = "2022003";
    empno[4] = "2022004";
    empno[5] = "2022005";

    empname[1] = "张三";
    empname[2] = "李四";
    empname[3] = "王五";
    empname[4] = "周发";
    empname[5] = "王平";

    empdepartment[1] = "营销部";
    empdepartment[2] = "财务部";
    empdepartment[3] = "研发部";
    empdepartment[4] = "董事会";
    empdepartment[5] = "后勤部";


    //视图标题
    viewtabletitle<<"员工编号" << "员工姓名" << "所在部门";
    emphindex<< 1 << 2 << 3 << 4 << 5;
    empnameidex << 1 << 2 << 3 << 4 << 5;


    modelFunc();
}

void ModelExtend::modelFunc()
{

}

int ModelExtend::rowCount(const QModelIndex &parent) const
{
    return 5;
}

int ModelExtend::columnCount(const QModelIndex &parent) const
{
    return 3;
}

//index存储(行,列)data函数用于显示数据
QVariant ModelExtend::data(const QModelIndex &index, int role) const
{
    if(!index.isValid()){//判断是否合法
        return QVariant();//不合法返回空的值
    }

    if(role == Qt::DisplayRole){//显示文本
        switch (index.column()) {
        case 0:
            return empno[emphindex[index.row()]];
            break;
        case 1:
            return empname[empnameidex[index.row()]];
            break;
        case 2:
            return empdepartment[index.row() + 1];
            break;
        default:
            return QVariant();
            break;
        }
    }

    return QVariant();
}

//设置行列表头
QVariant ModelExtend::headerData(int section, Qt::Orientation orientation, int role) const
{
    //if(section > 3 || section < 0) return QVariant();
    //显示表头(水平标题)
    if(role == Qt::DisplayRole && orientation == Qt::Horizontal){
        return viewtabletitle[section];
    }else if(role == Qt::DisplayRole && orientation == Qt::Vertical){//垂直方向的表头
        return section + 1;
    }
    return QVariant();
}


//--------------------------------------main.cpp----------------------------------------------
#include "mainwindow.h"
#include "modelextend.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // MainWindow w;
    // w.show();

    ModelExtend *model = new ModelExtend();
    QTableView view;
    view.setGeometry(220, 220, 400, 200);
    view.setModel(model);//创建视图后绑定模型,自动获取模型中的数据
    view.show();
    return a.exec();
}

运行效果:

image 

posted @ 2026-01-31 16:13  菜鸡の编程日常  阅读(5)  评论(0)    收藏  举报