C++ Qt开发:QItemDelegate 自定义代理组件

打印 上一主题 下一主题

主题 874|帖子 874|积分 2622

Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍QStyledItemDelegate自定义代理组件的常用方法及灵活运用。
在Qt中,QStyledItemDelegate 类是用于创建自定义表格视图(如QTableView和QTableWidget)的委托类,允许你自定义表格中每个单元格的外观和交互。QStyledItemDelegate 是QItemDelegate 的子类,提供了更现代、更易用的接口。此处我们将实现对QTableView表格组件的自定义代理功能,例如默认情况下表格中的缺省代理就是一个编辑框,我们只能够在编辑框内输入数据,而有时我们想选择数据而不是输入,此时就需要重写编辑框实现选择的效果,代理组件常用于个性化定制表格中的字段类型。
1.1 概述代理类

代理类的作用是用来实现组件重写的,例如TableView中默认是可编辑的,之所以可编辑是因为Qt默认为我们重写了QLineEdit编辑框实现的,也可理解为将组件嵌入到了表格中,实现了对表格的编辑功能。
在自定义代理中QAbstractItemDelegate是所有代理类的抽象基类,它用于创建自定义的项委托。提供了一个基本的框架,使得可以定制如何在视图中绘制和编辑数据项。
QAbstractItemDelegate 是 QItemDelegate 的基类,而 QItemDelegate 则是 QStyledItemDelegate 的基类。这个继承体系提供了不同层次的定制能力。我们继承任何组件时都必须要包括如下4个函数:

  • CreateEditor() 用于创建编辑模型数据的组件,例如(QSpinBox组件)
  • SetEditorData() 从数据模型获取数据,以供Widget组件进行编辑
  • SetModelData() 将Widget组件上的数据更新到数据模型
  • UpdateEditorGeometry() 给Widget组件设置一个合适的大小
通过继承 QAbstractItemDelegate 并实现这些函数,读者可创建一个定制的项委托,用于控制数据项在视图中的外观和交互行为。此处我们分别重写三个代理接口,其中两个ComBox组件用于选择婚否,而第三个SpinBox组件则用于调节数值范围,先来定义三个重写部件。
1.2 自定义代理组件

这里我们以第一个SpinBox组件为例,要实现代理该组件,首先需要在项目上新建一个SpinDelegate类,并依次实现上述的四个方法,先来开创建流程;

  • 选择addnew选中 C++ Class 输入自定义类名称QWintSpinDelegate,然后基类继承QStyledItemDelegate/QMainWindow,然后下一步结束向导,同理其他功能的创建也如此。

接着就是对该接口的重写了,此处重写代码spindelegate.cpp如下所示,其关键位置的解释可参考注释部分。
  1. #include "spindelegate.h"
  2. #include <QSpinBox>
  3. QWIntSpinDelegate::QWIntSpinDelegate(QObject *parent):QStyledItemDelegate(parent)
  4. {
  5. }
  6. // 创建代理编辑组件
  7. QWidget *QWIntSpinDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const
  8. {
  9.     Q_UNUSED(option);
  10.     Q_UNUSED(index);
  11.     QSpinBox *editor = new QSpinBox(parent);  // 创建一个QSpinBox
  12.     editor->setFrame(false);                  // 设置为无边框
  13.     editor->setMinimum(0);
  14.     editor->setMaximum(10000);
  15.     return editor;                            // 返回此编辑器
  16. }
  17. // 从数据模型获取数据,显示到代理组件中
  18. void QWIntSpinDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
  19. {
  20.     // 获取数据模型的模型索引指向的单元的数据
  21.     int value = index.model()->data(index, Qt::EditRole).toInt();
  22.     QSpinBox *spinBox = static_cast<QSpinBox*>(editor);   // 强制类型转换
  23.     spinBox->setValue(value);                             // 设置编辑器的数值
  24. }
  25. // 将代理组件的数据,保存到数据模型中
  26. void QWIntSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
  27. {
  28.     QSpinBox *spinBox = static_cast<QSpinBox*>(editor); // 强制类型转换
  29.     spinBox->interpretText();                           // 解释数据,如果数据被修改后,就触发信号
  30.     int value = spinBox->value();                       // 获取spinBox的值
  31.     model->setData(index, value, Qt::EditRole);         // 更新到数据模型
  32. }
  33. // 设置组件大小
  34. void QWIntSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
  35. {
  36.     Q_UNUSED(index);
  37.     editor->setGeometry(option.rect);
  38. }
复制代码
接着重写接口floatspindelegate.cpp实现代码如上述部分一致,唯一的变化是组件变了,代码如下;
  1. #include "floatspindelegate.h"
  2. #include <QDoubleSpinBox>
  3. QWFloatSpinDelegate::QWFloatSpinDelegate(QObject *parent):QStyledItemDelegate(parent)
  4. {
  5. }
  6. QWidget *QWFloatSpinDelegate::createEditor(QWidget *parent,
  7.    const QStyleOptionViewItem &option, const QModelIndex &index) const
  8. {
  9.     Q_UNUSED(option);
  10.     Q_UNUSED(index);
  11.     QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
  12.     editor->setFrame(false);
  13.     editor->setMinimum(0);
  14.     editor->setDecimals(2);
  15.     editor->setMaximum(10000);
  16.     return editor;
  17. }
  18. void QWFloatSpinDelegate::setEditorData(QWidget *editor,
  19.                       const QModelIndex &index) const
  20. {
  21.     float value = index.model()->data(index, Qt::EditRole).toFloat();
  22.     QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
  23.     spinBox->setValue(value);
  24. }
  25. void QWFloatSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
  26. {
  27.     QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
  28.     spinBox->interpretText();
  29.     float value = spinBox->value();
  30.     QString str=QString::asprintf("%.2f",value);
  31.     model->setData(index, str, Qt::EditRole);
  32. }
  33. void QWFloatSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
  34. {
  35.     editor->setGeometry(option.rect);
  36. }
复制代码
最后重写接口comboxdelegate.cpp其代码如下所示;
  1. #include "comboxdelegate.h"
  2. #include <QComboBox>
  3. QWComboBoxDelegate::QWComboBoxDelegate(QObject *parent):QItemDelegate(parent)
  4. {
  5. }
  6. QWidget *QWComboBoxDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const
  7. {
  8.     QComboBox *editor = new QComboBox(parent);
  9.     editor->addItem("已婚");
  10.     editor->addItem("未婚");
  11.     editor->addItem("单身");
  12.     return editor;
  13. }
  14. void QWComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
  15. {
  16.     QString str = index.model()->data(index, Qt::EditRole).toString();
  17.     QComboBox *comboBox = static_cast<QComboBox*>(editor);
  18.     comboBox->setCurrentText(str);
  19. }
  20. void QWComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
  21. {
  22.     QComboBox *comboBox = static_cast<QComboBox*>(editor);
  23.     QString str = comboBox->currentText();
  24.     model->setData(index, str, Qt::EditRole);
  25. }
  26. void QWComboBoxDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const
  27. {
  28.     editor->setGeometry(option.rect);
  29. }
复制代码
将部件导入到mainwindow.cpp主程序中,并将其通过ui->tableView->setItemDelegateForColumn(0,&intSpinDelegate);关联部件到指定的table下标索引上面。
[code]#include "mainwindow.h"#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow){    ui->setupUi(this);    // 初始化模型数据    model = new QStandardItemModel(4,6,this);      // 初始化4行,每行六列    selection = new QItemSelectionModel(model);    // 关联模型    ui->tableView->setModel(model);    ui->tableView->setSelectionModel(selection);    // 添加表头    QStringList HeaderList;    HeaderList

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

渣渣兔

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表