Qt之模型/视图(委托)

概念
      不同于模型 - 视图 - 控制器模式,模型/视图设计不包括用于管理与用户交互的一个完全独立的组件。一般情况,视图负责将模型数据呈现给用户以及处理用户输入。为了输入更加具有灵活性,则由委托来执行交互。这些组件提供输入功能,且在一些视图中还负责渲染个别项目。控制委托的标准接口在 QAbstractItemDelegate类中定义。
      委托能够通过实现的 paint()sizeHint()函数来展示它们的内容。然而,简单基础部件的委托可以继承 QItemDelegate而不是 QAbstractItemDelegate,并使用这些函数的默认实现。
 
 
      委托编辑器可以通过使用小工具来管理编辑过程或直接处理事件来实现。
使用现有委托
      Qt提供的标准视图中使用 QItemDelegate提供编辑功能。委托接口的默认实现以一贯风格来呈现项目为每个标准视图: QListViewQTableViewQTreeView
      所有标准角色由所使用的标准视图中的默认委托处理。
      视图使用委托是由 itemDelegate()函数返回。 setItemDelegate()函数允许你为标准视图设定一个自定义委托,为自定义视图设定委托时,有必要使用此功能。
一个简单的委托
 
 
      这里实现的委托使用 QSpinBox来提供编辑功能,主要用于模型处理整数。虽然为了这个目的我们设置了一个自定义的基于整数的表模型,我们可以很容易地使用 QStandardItemModel来代替,因为自定义委托控制数据输入。我们构造了一个表视图来显示模型的内容,可以使用自定义的委托来进行编辑。
Qt之模型/视图(委托)
      我们的委托继承于 QItemDelegate,因为我们不想编写自定义显示功能。然而,仍然必须提供管理编辑器窗口小部件的功能:
class SpinBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    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;
};
提供了一个编辑器
在这个例子中,当表视图需要提供一个编辑器时,它将要求委托提供一个编辑器部件适用于修改该项目。createEditor()函数提供一切,委托需要能够建立一个合适的窗口小部件:
 
 
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem &,
    const QModelIndex &) const
{
    QSpinBox *editor = new QSpinBox(parent);
    editor->setFrame(false);
    editor->setMinimum(0);
    editor->setMaximum(100);
 
return editor; }
注意,我们不需要一个指向编辑器的部件,因为当不再需要时,视图负责销毁它。
    在编辑器上安装代理的默认事件过滤器,以确保它提供了用户所期望的标准编辑快捷方式。编辑器中可以添加额外的快捷键,以允许更复杂的行为。
    可以根据视图提供的模型索引创建不同的编辑器。例如,如果有一个整数列和字符串列,我们可以返回一个QSpinBoxQLineEdit,这取决于哪一列正在被编辑。
    委托必须提供一个函数将模型中的数据复制到编辑器中。在这个例子中,我们读出存储在显示角色中的数据,并在QSpinBox中设置的值相应。
 
 
void SpinBoxDelegate::setEditorData(QWidget *editor,
    const QModelIndex &index) const
{
    int value = index.model()->data(index, Qt::EditRole).toInt();
    QSpinBox *spinBox = static_cast<<span style=" color:#800080;">QSpinBox*>(editor);
    spinBox->setValue(value);
}
    在这个例子中,我们知道编辑器部件是一个QSpinBox,但可以为模型中不同类型的数据提供不同的编辑器,在这种情况下,则需要在访问它的成员函数之前设置部件为适当的类型。
 
 
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
    const QModelIndex &index) const
{
    QSpinBox *spinBox = static_cast<<span style=" color:#800080;">QSpinBox*>(editor);
    spinBox->interpretText();
    int value = spinBox->value();
    model->setData(index, value, Qt::EditRole);
}
 
 
    由于视图为委托管理编辑器部件,所以只需要以编辑器提供的内容来更新模型。在这种情况下,我们确QSpinBox是最新更新,并使用指定的索引包含的值来更新模型。
    标准的QItemDelegate类通过发射closeEditor()信号来完成编辑视图。视图可确保编辑器部件被关闭和销毁。在这个例子中,我们只提供简单的编辑功能,所以我们需要永远不会发出这个信号。
    所有的数据操作通过QAbstractItemModel提供的接口执行。这使得委托大多独立于它操纵的数据的类型,但为了使用某些类型的编辑器部件,则必须做出一些假设。在这个例子中,我们假设模型总是包含整数值,但我们仍然在不同类型的模型中使用此委托,因为的QVariant为意想不到的数据提供了合理的默认值。
 
 
 
 
更新编辑器的几何形状
    管理编辑器的几何形状是委托的责任。当编辑器被创建,或者当项目视图的的位置、大小在视图中改变时,几何形状必须被设置。幸运的是,视图提供了视图选项物体内部所有必要的几何信息。
 
 
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
    const QStyleOptionViewItem &option, const QModelIndex &) const
{
    editor->setGeometry(option.rect);
}
    这种情况下,我们仅在项目区域中使用视图选项提供的位置信息。使用一些元素展现项目的委托不会直接使用该项目矩形。根据这个项目中的其他元素来设定编辑器的位置。
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QStandardItemModel model(4, 2);
    QTableView tableView;
    tableView.setModel(&model);
    SpinBoxDelegate delegate;
    tableView.setItemDelegate(&delegate);
    tableView.horizontalHeader()->setStretchLastSection(true);
    for (int row = 0; row <<span style=" color:#c0c0c0;"> 4; ++row) {
    for (int column = 0; column <<span style=" color:#c0c0c0;"> 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();
}
转自:http://blog.sina.com.cn/s/blog_a6fb6cc90101hhon.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值