C++ and Qt TableDelegate custom proxy component

The main function of the TableDelegate custom proxy component is to adjust the original table. For example, the default proxy in the Table is an edit box by default. We can only enter data in the edit box, and sometimes we want to select data instead of input , at this time, it is necessary to rewrite the edit box to achieve the selection effect, and the proxy component is often used to personalize the field type in the Table form.

In the custom agent, QAbstractItemDelegate is the abstract base class of all agent classes. When we inherit any component, we must include the following four functions:

  • CreateEditor() is used to create components for editing model data, for example (QSpinBox component)
  • SetEditorData() Gets data from the data model for editing by the Widget component
  • SetModelData() updates the data on the Widget component to the data model
  • UpdateEditorGeometry() Set an appropriate size for the Widget component

Here we rewrite three agent interfaces respectively, among which two ComBox components are used to select whether to marry, and the SpinBox component is used to adjust the value range. Let’s define three rewritten components first.

Rewrite the interface spindelegate.cpp code as follows.

#include "spindelegate.h"
#include <QSpinBox>

QWIntSpinDelegate::QWIntSpinDelegate(QObject *parent):QStyledItemDelegate(parent)
{
}

// https://www.cnblogs.com/lyshark
QWidget *QWIntSpinDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//创建代理编辑组件
    Q_UNUSED(option);
    Q_UNUSED(index);

    QSpinBox *editor = new QSpinBox(parent); //创建一个QSpinBox
    editor->setFrame(false); //设置为无边框
    editor->setMinimum(0);
    editor->setMaximum(10000);
    return editor;  //返回此编辑器
}

void QWIntSpinDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
//从数据模型获取数据,显示到代理组件中
//获取数据模型的模型索引指向的单元的数据
    int value = index.model()->data(index, Qt::EditRole).toInt();

    QSpinBox *spinBox = static_cast<QSpinBox*>(editor);  //强制类型转换
    spinBox->setValue(value); //设置编辑器的数值
}

void QWIntSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
//将代理组件的数据,保存到数据模型中
    QSpinBox *spinBox = static_cast<QSpinBox*>(editor); //强制类型转换
    spinBox->interpretText(); //解释数据,如果数据被修改后,就触发信号
    int value = spinBox->value(); //获取spinBox的值

    model->setData(index, value, Qt::EditRole); //更新到数据模型
}

void QWIntSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//设置组件大小
    Q_UNUSED(index);
    editor->setGeometry(option.rect);
}

Rewrite the interface floatspindelegate.cpp code as follows.

#include "floatspindelegate.h"
#include <QDoubleSpinBox>

QWFloatSpinDelegate::QWFloatSpinDelegate(QObject *parent):QStyledItemDelegate(parent)
{
}

QWidget *QWFloatSpinDelegate::createEditor(QWidget *parent,
   const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_UNUSED(option);
    Q_UNUSED(index);

    QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
    editor->setFrame(false);
    editor->setMinimum(0);
    editor->setDecimals(2);
    editor->setMaximum(10000);

    return editor;
}

void QWFloatSpinDelegate::setEditorData(QWidget *editor,
                      const QModelIndex &index) const
{
    float value = index.model()->data(index, Qt::EditRole).toFloat();
    QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
    spinBox->setValue(value);
}

// https://www.cnblogs.com/lyshark
void QWFloatSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);
    spinBox->interpretText();
    float value = spinBox->value();
    QString str=QString::asprintf("%.2f",value);

    model->setData(index, str, Qt::EditRole);
}

void QWFloatSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

The rewrite interface comboxdelegate.cpp code is as follows.

#include "comboxdelegate.h"
#include <QComboBox>

QWComboBoxDelegate::QWComboBoxDelegate(QObject *parent):QItemDelegate(parent)
{
}

QWidget *QWComboBoxDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QComboBox *editor = new QComboBox(parent);

    editor->addItem("已婚");
    editor->addItem("未婚");
    editor->addItem("单身");

    return editor;
}

// https://www.cnblogs.com/lyshark
void QWComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QString str = index.model()->data(index, Qt::EditRole).toString();

    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    comboBox->setCurrentText(str);
}

void QWComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    QString str = comboBox->currentText();
    model->setData(index, str, Qt::EditRole);
}

void QWComboBoxDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

Import the component into mainwindow.cpp, and associate it with the specified table subscript index through ui->tableView->setItemDelegateForColumn(0,&intSpinDelegate);

#include "mainwindow.h"
#include "ui_mainwindow.h"

// https://www.cnblogs.com/lyshark
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 << "序号" << "姓名" << "年龄" << "性别" << "婚否" << "薪资";
    model->setHorizontalHeaderLabels(HeaderList);

    // 批量添加数据
    QStringList DataList[3];
    QStandardItem *Item;

    DataList[0] << "1001" << "admin" << "24" << "男" << "已婚" << "4235.43";
    DataList[1] << "1002" << "lyshark" << "23" << "男" << "未婚" << "10000.21";
    DataList[2] << "1003" << "lucy" << "37" << "女" << "单身" << "8900.23";

    int Array_Length = DataList->length();                          // 获取每个数组中元素数
    int Array_Count = sizeof(DataList) / sizeof(DataList[0]);       // 获取数组个数

    for(int x=0; x<Array_Count; x++)
    {
        for(int y=0; y<Array_Length; y++)
        {
            // std::cout << DataList[x][y].toStdString().data() << std::endl;
            Item = new QStandardItem(DataList[x][y]);
            model->setItem(x,y,Item);
        }
    }

    // 为各列设置自定义代理组件
    // 0,4,5 代表第几列 后面的函数则是使用哪个代理类的意思
    ui->tableView->setItemDelegateForColumn(0,&intSpinDelegate);
    ui->tableView->setItemDelegateForColumn(4,&comboBoxDelegate);
    ui->tableView->setItemDelegateForColumn(5,&floatSpinDelegate);

}

MainWindow::~MainWindow()
{
    delete ui;
}

After the proxy components are associated, run the program again, and you will find that the edit box in the original TableWidget component has been replaced with a selection box and other components:


 The benefits of this article, free to receive Qt development learning materials package, technical video, including (C++ language foundation, C++ design pattern, introduction to Qt programming, QT signal and slot mechanism, QT interface development-image drawing, QT network, QT database programming, QT project actual combat, QSS, OpenCV, Quick module, interview questions, etc.) ↓↓↓↓↓↓See below↓↓Click on the bottom of the article to receive the fee↓↓

Guess you like

Origin blog.csdn.net/m0_73443478/article/details/130606001