9.Delegate类

Concepts
     不像MVC模式,Model/View模式并没有单独用来处理事件和用户交互的组件(controller)。通常,视图负责向用户呈现模型中的数据,并处理用户的输入。有时,为了让输入更加灵活,使用Delegate处理交互。Delegate组件提供输入功能,还负责渲染某个Item。Delegate的标准接口在QAbstractItemDelegate中定义。
     Delegate希望实现paint()和sizeHint()函数来呈现自己的内容。但是,简单的基于Widget的Delegate通过QItemDelegate子类化,而不是QAbstractItemDelegate,并且有这些函数的默认实现。
     Delegate的Editors可以用过Widget管理Edit过程或者直接处理事件,这两种方式实现。第一种方法将在 spin box delegate 例子中实现。
     Pixelato例子显示如何专门为TableView创建定制的Delegate。
 
Using an existing delegate
     Qt提供的标准视图都是通过QItemDelegate实例来实现编辑功能。默认的Delegate接口实现,以通常的样式渲染每个标准视图:QListView,QTreeView,QTableView。
     所有的standard roles都由标准视图使用的默认Delegate来处理。视图使用的Delegate由itemDelegate()函数返回。setItemDelegate()函数允许您为标准视图安装自定义Delegate。 
 
Delegate举例: 我们显示一个4x2的表格,表格中每个单元都是spinbox。
 
思考:
1.我们使用QTableView显示这个表格。
2.使用QStandardItemModel,初始化时指定4行2列。
3.渲染每个表格为spinbox,这里就需要QItemDelegate。
4.QItemDeleate实现了paint()和sizeHint()函数。我们不需要重新这2个函数。
5.每个表格变成spinbox,需要实现createEditor()函数。
6.表格中数据改变,需要告诉Model,实现setModelData()函数
7.表格中数据改变,显示也要跟着改变,实现setEditorData()函数。
8.最后数据改变,单元格的空间也可能改变,实现updataEditorGeometry()函数。
 
代码如下:
spinboxdelegate.h
#ifndef SPINBOXDELEGATE_H
#define SPINBOXDELEGATE_H

#include <QItemDelegate>

class SpinBoxDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    explicit SpinBoxDelegate(QObject *parent = 0);
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
signals:
    
public slots:
    
};

#endif // SPINBOXDELEGATE_H

 

sinboxdelegate.cpp

#include "spinboxdelegate.h"

#include <QSpinBox>

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

QWidget* SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QSpinBox *editor = new QSpinBox(parent);
    editor->setMaximum(100);
    editor->setMinimum(0);

    return editor;
}
void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QSpinBox *spinBox = static_cast<QSpinBox *>(editor);

    spinBox->interpretText();
    int num = index.data(Qt::DisplayRole).toInt();
    spinBox->setValue(num);
}

void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QSpinBox *spinBox = static_cast<QSpinBox *>(editor);
    int num = spinBox->value();

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

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

main.cpp

#include <QTableView>
#include <QStandardItemModel>
#include <QModelIndex>
#include <QApplication>

#include <spinboxdelegate.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QStandardItemModel *standardModel = new QStandardItemModel(4,2);
    QTableView *tableView = new QTableView;

    tableView->setModel(standardModel);
    for(int row = 0; row < 4; row++) {
        for(int col = 0; col < 2; col++) {
            QModelIndex index = standardModel->index(row, col, QModelIndex());
            standardModel->setData(index, QVariant((row+1)*(col+1)));
        }
    }

    SpinBoxDelegate *delegate = new SpinBoxDelegate;
    tableView->setItemDelegate(delegate);

    tableView->show();



    return a.exec();
}

 

程序效果如下:

      

 
 
 
 
 
posted @ 2017-05-28 21:25  billxyd  阅读(417)  评论(0编辑  收藏  举报