3、委托类
Qt中的模型、视图结构中没有包含一个完全分离的组件来处理与用户的交互。
一般地、视图用来将模型中的数据展示给用户,也用来处理用户的输入。为了获得更高的灵活性,交互可以交给委托来执行。
控制委托的标准接口在QAbstractItemDelegate类中定义。
委托通过实现paint()和sizeHint()来使它们可以渲染自身的内容。
基于部件的委托可以通过子类化QItemDelegate来实现。
委托的编辑器可以通过两种方式来实现,
一、使用部件来管理编辑过程。
二、直接处理事件。
可以参考Qt提供的Spin Box Delegate的示例程序,如下:
委托:顾明思议,使用标准Qt 的编辑器编辑(standard QT editor widget),然后再将数据返回到视图中。
先看下SpinBoxDelegate Class Definition:
class SpinBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
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;
};
上述类的定义中做了如下几项事情:
1、创建 一个编辑部件,并在视图中的确定位置显示。
2、与数据模型通信。
另外,自定义模型可以通过paintEvent来提供自定义的painting code
当然,还可以通过重载destroyEditor()函数来实现可编辑部件的重复使用。
SpinBoxDelegate 类成员的实现:
委托常常代码量是非常少的。构造韩式也仅仅需要调用类默认的构造函数即可。
1、构造函数:
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
2、createEditor():该函数返回一个可编辑部件,并且将从数据模型中获得的数据的值限定在0到100之间。
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/* option */,
const QModelIndex &/* index */) const
{
QSpinBox *editor = new QSpinBox(parent);
editor->setFrame(false);
editor->setMinimum(0);
editor->setMaximum(100);
return editor;
}
3、setEditorData(): 从模型中读到数据,并将它转化为整形,然后写到这个可编辑的部件中。
void SpinBoxDelegate::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);
}
4、setModelData(): 从spin box 中读到数据,并将数据写入到数据模型中。
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->interpretText();
int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}
这里的interpretText()函数,是为了让我们获得到的是spin box 中最新的的数据。
5、updateEditorGeometry():更新可编辑部件的几何形状,这是委托机制中必不可少的。
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
主函数的实现
主函数实现以下几方面内容:
1、通过标准数据模型来创建数据项;
2、建立表格视图来显示这些数据项;
3、创建一个委托来编辑数据;
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QStandardItemModel model(4, 2);
QTableView tableView;
tableView.setModel(&model);
SpinBoxDelegate delegate;
tableView.setItemDelegate(&delegate);
for (int row = 0; row < 4; ++row) {
for (int column = 0; column < 2; ++column) {
QModelIndex index = model.index(row, column, QModelIndex());
model.setData(index, QVariant((row + 1) * (column + 1)));
}
}
tableView.setWindowTitle(QObject::tr("Spin Box Delegate"));
tableView.show();
return app.exec();
}
由于委托继承自QStyledItemDelegate,每一个单元格会通过标准绘图操作绘制。(这句话的理解就是,当单元格被操作的时候,会建立委托,而这个委托的视图是通过标准的绘图操作来实现)
到这里,这个spin box delegate的介绍就结束了。想必多操作,多练习自然就明白了。