1、QT分为:Mode层,View层,数据存放在Mode里面,显示在View层,当我们修改了View层的同时,需要修改Mode层。
2、Delegate工作原理:当我们点击支持编辑的列,创建自定义的编辑控件(可为button、spinbox、combobox等等),然后从Mode层,取值,设置给控件,当自定义控件,编辑完成,再设置给Mode层
3、自定义Delegate
class ItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
ItemDelegate (QObject *parent = nullptr);
~ItemDelegate ();
public:
virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const;
virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
virtual void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
#include "stdafx.h"
#include "ItemDelegate.h"
#include <QSpinBox>
#include <QDoubleSpinBox>
ItemDelegate::ItemDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
// 如果继承的是QItemDelegate,那么在paint中,是不能支持parent的QSS的
}
ItemDelegate::~ItemDelegate()
{
}
QWidget * ItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
// step:1 根据不同的列,创建需要的控件,不支持的直接返回空
if (index.column() == 1|| index.column() == 2)
{
QSpinBox *spinBox = new QSpinBox(parent);
spinBox->setRange(0, 255);
return spinBox;
}
else if(index.column() == 3|| index.column() == 4)
{
QDoubleSpinBox *dSpinBox = new QDoubleSpinBox(parent);
dSpinBox->setRange(0, 100);
dSpinBox->setSingleStep(1.00);
return dSpinBox;
}
return nullptr;
}
void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem viewOption(option);
initStyleOption(&viewOption, index);
QStyledItemDelegate::paint(painter, viewOption, index);
}
void ItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
// step:2 给控件设置值
if (index.column() == 1|| index.column() == 2)
{
QSpinBox *spinBox = dynamic_cast<QSpinBox *>(editor);
if (spinBox)
{
int value = index.data().toString().toInt();
spinBox->setValue(value);
}
}
else if (index.column() == 3|| index.column() == 4)
{
QDoubleSpinBox *dSpinBox = dynamic_cast<QDoubleSpinBox *>(editor);
if (dSpinBox)
{
double value = index.data().toString().toDouble();
dSpinBox->setValue(value);
}
}
}
void ItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
// step:3编辑完成,设置值给Mode层
if (index.column() == 1|| index.column() == 2)
{
QSpinBox *spinBox = dynamic_cast<QSpinBox *>(editor);
if (spinBox)
{
int value = spinBox->value();
model->setData(index, value, Qt::DisplayRole);
}
}
else if (index.column() == 3|| index.column() == 4)
{
QDoubleSpinBox *dSpinBox = dynamic_cast<QDoubleSpinBox *>(editor);
if (dSpinBox)
{
double value = dSpinBox->value();
model->setData(index, QString::number(value, 'f', 2), Qt::DisplayRole);
}
}
}
void ItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
4、启用Delegate
ui->treeWidget->setItemDelegate(new ItemDelegate(ui->treeWidget));
// 当鼠标点击时候,开启编辑
connect(ui->treeWidget, &QTreeWidget::clicked, this, [this](const QModelIndex &index)
{
if (index.column() == 1|| index.column() == 2|| index.column() == 3
|| index.column() == 4)
{
ui->treeWidget->edit(index);
}
});
// 检测Item变化是为了给底层设值
connect(ui->treeWidget, &QTreeWidget::itemChanged, this, [this]{onItemChanged();});
// mEditing 是为了监测是否在编辑状态,在创建QTreeWidgetItem时候 设置为tree,添加完成设置为False
void MainWindow::onItemChanged(QTreeWidgetItem *item, int column)
{
if (mEditing || nullptr == item)
{
return;
}
// 然后给底层设值值
// do something
}
// Item 支持编辑
QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
item->setFlags(item->flags() | Qt::ItemIsEditable);