一、前言

传统的模型-视图框架可以让我们实现逻辑个展示相分离,我们只需要关心模型就可以,在模型上做的任何更改都会走动更新到视图上去,其实就是观察者模式。Qt基于传统的模型-视图框架(MVC,model、view、controler),推出了MVD(model、view、delegate)框架。具体有什么用呢?

如果我们使用QTableView来作为表格控件,显示数据,但是突然有需求需要在里面添加一些交互的控件,例如:按钮、进度条之类的,直接使用模型是无法实现的。可以使用QTableWidget控件可以很轻松的实现,但是这个不支持模型-视图框架。代理的作用就来了,代理可以把控件委托给模型来代理,就可以实现在表格中添加控件进行交互了。

通常委托都继承QStyledItemDelegateQItemDelegate这个两个类。两个类的代码基本相同,如下图示。如果需要使用style sheet 时,建议使用QStyledItemDelegate。


二、实际案例

2.1、委托进度条QSpinBox、QComboBox

2.1.1、效果展示


2.1.2、定义代理类

spinBoxDelegate.h

#ifndef SPINBOXDELEGATE_H
#define SPINBOXDELEGATE_H#include <QItemDelegate>
#include <QSpinBox>
#include <QComboBox>class SpinBoxDelegate : public QItemDelegate
{Q_OBJECTpublic:SpinBoxDelegate(QObject* parent = nullptr);QWidget * createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const override;void setEditorData(QWidget *editor,const QModelIndex &index) const override;void setModelData(QWidget *editor,QAbstractItemModel *model, const QModelIndex &index) const override;void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};#endif // SPINBOXDELEGATE_H

spinBoxDelegate.cpp

#include "spinboxdelegate.h"SpinBoxDelegate::SpinBoxDelegate(QObject* parent) : QItemDelegate(parent)
{}QWidget* SpinBoxDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const
{if(index.column() == 0){QSpinBox* spinBox = new QSpinBox(parent);spinBox->setFrame(false);spinBox->setMinimum(0);spinBox->setMaximum(100);return spinBox;}else if(index.column() == 1){QComboBox* comboBox = new QComboBox(parent);comboBox->addItem("Hello");comboBox->addItem("World");return comboBox;}return QItemDelegate::createEditor(parent,option,index);
}
void SpinBoxDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{if(index.column() == 0){int value = index.model()->data(index,Qt::EditRole).toInt();QSpinBox* spinBox = static_cast<QSpinBox*>(editor);spinBox->setValue(value);}else if(index.column() == 1){QString value = index.model()->data(index,Qt::EditRole).toString();QComboBox* comboBox = static_cast<QComboBox*>(editor);int tindex = comboBox->findText(value);comboBox->setCurrentIndex(tindex);}elseQItemDelegate::setEditorData(editor,index);
}
void SpinBoxDelegate::setModelData(QWidget *editor,QAbstractItemModel *model, const QModelIndex &index) const
{if(index.column() == 0){QSpinBox* spinBox = static_cast<QSpinBox*>(editor);spinBox->interpretText();int value = spinBox->value();model->setData(index,value,Qt::EditRole);}else if(index.column() == 1){QComboBox* comboBox = static_cast<QComboBox*>(editor);QString text = comboBox->currentText();model->setData(index,text,Qt::EditRole);}elseQItemDelegate::setModelData(editor,model,index);
}
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const
{editor->setGeometry(option.rect);
}

2.1.3、具体使用

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QTableView>
#include <QStandardItemModel>
#include <QHeaderView>#include "spinboxdelegate.h"QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void init_UI();void init_Model();void init_Delegate();private:Ui::MainWindow *ui;QTableView* tableView;QStandardItemModel* model;SpinBoxDelegate* delegate;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);init_UI();init_Model();init_Delegate();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::init_UI()
{this->setMinimumSize(400,200);tableView = new QTableView;tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);this->setCentralWidget(tableView);
}
void MainWindow::init_Model()
{model = new QStandardItemModel;model->setRowCount(4);model->setColumnCount(4);model->setHeaderData(0,Qt::Horizontal,"第一列");model->setHeaderData(1,Qt::Horizontal,"第一列");model->setHeaderData(2,Qt::Horizontal,"第三列");model->setHeaderData(3,Qt::Horizontal,"第四列");tableView->setModel(model);
}
void MainWindow::init_Delegate()
{delegate = new SpinBoxDelegate;tableView->setItemDelegate(delegate);
}


2.2、委托进度条QProgressBar

2.2.1、效果展示


2.2.2、定义代理类

自定义一个代理类,继承自QStyledItemDelegate(如下所示),然后依据个人需求实现基类中的接口,一般实现paint()就行了。

progressbardelegate.h

#ifndef PROGRESSBARDELEGATE_H
#define PROGRESSBARDELEGATE_H#include <QObject>
#include <QProgressBar>
#include <QModelIndex>
#include <QPainter>
#include <QStyledItemDelegate>
#include <QApplication>class ProgressBarDelegate : public QStyledItemDelegate
{Q_OBJECT
public:ProgressBarDelegate();protected:void paint(QPainter* painter,const QStyleOptionViewItem &option, const QModelIndex &index) const;
};#endif // PROGRESSBARDELEGATE_H

progressbardelegate.cpp

#include "progressbardelegate.h"ProgressBarDelegate::ProgressBarDelegate()
{}void ProgressBarDelegate::paint(QPainter* painter,const QStyleOptionViewItem &option, const QModelIndex &index) const
{if(index.isValid() && index.column() == 1) //代理第二列{QStyleOptionProgressBar bar;bar.rect = option.rect;bar.progress = index.data().toInt();bar.maximum = 100;bar.minimum = 0;bar.text = QString::number(bar.progress)+"%";bar.textVisible = true;QApplication::style()->drawControl(QStyle::CE_ProgressBar,&bar,painter);}else{QStyledItemDelegate::paint(painter,option,index);}
}

2.2.3、具体使用

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QTableView>
#include <QStandardItemModel>
#include <QTimer>
#include <QHeaderView>#include "progressbardelegate.h"QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void init_UI();void init_Model();void init_Delegate();public slots:void slot_download();private:Ui::MainWindow *ui;QTableView* tableView;QStandardItemModel* model;ProgressBarDelegate* delegate;QTimer* timer;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);init_UI();init_Model();init_Delegate();timer = new QTimer;connect(timer,SIGNAL(timeout()),this,SLOT(slot_download()));timer->setInterval(1000);timer->start();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::init_UI()
{this->setMinimumSize(400,200);tableView = new QTableView;tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);this->setCentralWidget(tableView);
}
void MainWindow::init_Model()
{model = new QStandardItemModel;model->setColumnCount(2);model->setHeaderData(0,Qt::Horizontal,"影片名字");model->setHeaderData(1,Qt::Horizontal,"下载进度");model->setItem(0,0,new QStandardItem("阿甘正传.mp4"));model->setItem(0,1,new QStandardItem("18"));model->setItem(1,0,new QStandardItem("霸王别姬.mp4"));model->setItem(1,1,new QStandardItem("3"));model->setItem(2,0,new QStandardItem("这个杀手不太冷.mp4"));model->setItem(2,1,new QStandardItem("69"));tableView->setModel(model);
}
void MainWindow::init_Delegate()
{delegate = new ProgressBarDelegate;tableView->setItemDelegate(delegate);
}void MainWindow::slot_download()
{for(inti=0; i<model->rowCount(); i++){int value = model->index(i,1).data().toInt();value++;model->setData(model->index(i,1),value);}
}

QT--自定义代理(MVD)相关推荐

  1. Qt 自定义信号与槽

    注 对象与槽理解 //第一个参数lineEdit是激发事件对象,信号中的方法必须在对象中存在,并在对象类头文件signals下定义,//第二个参数信号,//第三个参数this是槽方法所属类的对象,且必 ...

  2. QT自定义饼图的外观

    QT自定义饼图的外观 项目简介 项目技术 项目展示 主要源码片段解析 获取完整项目源码传送门 项目简介 自定义饼图的外观. 项目技术 qt5.12,qt charts模块,C++ 项目展示

  3. QT自定义图表上不同元素的外观

    QT自定义图表上不同元素的外观 项目简介 项目技术 项目展示 主要源码片段解析 获取完整项目源码传送门 项目简介 自定义图表上不同元素的外观. 项目技术 qt5.12,qt charts模块,C++ ...

  4. Qt 自定义标题栏,最小化、最大化、关闭窗口,双击最大化,鼠标拖动等效果实现

    文章目录 前言 效果 代码 .pro文件 widget.h widget.cpp widget.ui title.h title.cpp title.ui 前言 本次实验内容为Qt自定义标题栏,最小化 ...

  5. QT 自定义加载等待(Loading)提示框

    QT自定义加载等待提示框 一.效果展示 二.源代码 #ifndef LOADINGDIALOG_H #define LOADINGDIALOG_H #include <QMovie> #i ...

  6. QT自定义Widget控件及其使用

    今天来给大家分享一下QT自定义widget控件及其使用,当ui设计器提供的界面不满足实际需求时,可以从QWidget继承自定义的界面组件.有两种方法一种是提升法,另一种是ui设计器自定义界面组件wid ...

  7. QT 自定义分页控件

    Qt 自定义页码控件 一.效果展示 二.头文件 #ifndef PAGECONTROL_H #define PAGECONTROL_H #include <QList> #include ...

  8. QT自定义精美换肤界面

    QT自定义精美换肤界面 陆陆续续用QT开发过很多项目,也用QT写过不少私活项目,也写过N个工具,一直梦寐以求能像VC一样可以很方便的有个自定义的界面,QSS的强大让我看到了很好的希望,辗转百度谷歌无数 ...

  9. Qt自定义QPushButton

    目录 Qt自定义QPushButton 设置图标按钮 Qt自定义QPushButton 设置图标按钮 代码: m_pMinimizeButton = new QPushButton(this);m_p ...

  10. QT自定义进度条-画圆盘

    目录 QT自定义进度条-画圆盘 六等分圆盘 QT自定义进度条-画圆盘 六等分圆盘 void PaintWidget::paintEvent(QPaintEvent *e) {QPainter pain ...

最新文章

  1. 6月27日任务 配置Tomcat监听80端口、配置Tomcat虚拟主机、Tomcat日志
  2. iOS跳转到各种系统设置界面
  3. 一步步编写操作系统(1)
  4. Redis-04Redis数据结构--哈希hash
  5. ceph-deploy mod add_GTA5 1.50NPC自杀 MOD [支持1.411.50版本] 覆盖版【5.19MB】
  6. linux开启telnet服务
  7. vue路由query和params的区别
  8. 函数signal、sigaction
  9. mysql57数据库命令_MySQL 5.7 mysql command line client 使用命令详解
  10. 解决ros::TimeNotInitializedExcep
  11. 转:jdk动态代理实现
  12. 计算机软件进费用什么科目,购买软件费用如何记账?
  13. 考研二战日记-第11天——高数2.1 导数概念
  14. tenacity 报错_Python Tenacity 实现重试机制
  15. 软件测试工程师该如何规划自己的职业发展道路?
  16. 【正点原子FPGA连载】第六章Petalinux设计流程实战摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南
  17. 忌:以不专业去瞎指挥专业,以一知半解去瞎指挥一线实践
  18. 高德地图API实现区域立体效果
  19. 上半年净利同比降46%,依赖大客户的天润云能靠IPO翻身吗?
  20. 2007年8月22日Internet应用讲义以及作业

热门文章

  1. 海思3518EV300 liteos sdk编译
  2. 1.01的365次方与0.99的365次方
  3. 【嵌入式开发板】迅为iTOP-4412开发板板及资料介绍
  4. 计算机窗口移动不了怎么办,电脑鼠标拖不动文件怎么办 电脑鼠标拖动不灵敏如何解决...
  5. QT 版puremvc框架
  6. 金融量化之Tushare模块
  7. 麦克风阵列之声源定位
  8. Lotus Notes中文档查询(转)
  9. 免费ddns f3322.net使用脚本更新公网ip小记
  10. mysql 表 rowid_SQLite数据表的rowid