Qt--自定义Delegate

这是Model/View中的最后一篇了,Qt官方显然弱化了Controller在MVC中的作用,提供了一个简化版的Delegate;甚至在Model/View框架的使用中,提供了默认的委托,让这个控制器愈加淡出开发者的实现。

实际上,Qt Model/View框架中的MVC概念是有误的,显而易见的就是Controller的作用,控制器应该只对交互进行控制,渲染方面的工作应该仅由View完成,但Delegate的接口中却包含了这一块。不过这都不是这篇文章的重点,我们只关注Delegate本身。

1. 实现一个自定义Delegate

这里我们也来实现一个自定义Delegate,怀着了解Delegate的目的,主要实现以下几个功能:

  1. 以不同颜色绘制View。
    
  2. 双击View方格区域弹出行编辑器,默认覆盖这个区域,显示字母。
    
  3. 输入行编辑器内的内容会被保存,下次点开显示。
    
  4. 鼠标停留,显示提示框。
    

2. 继承QAbstractItemDelegate

Qt提供了几个标准的委托:

  1. QItemDelegate:Qt**曾经**默认使用的委托。
    
  2. QStyledItemDelegate。:**现在**默认使用的委托,官方推荐我们使用这个。(自从Qt 4.4)
    

为了熟悉委托借口,我们继承虚基类QAbstractItemDelegate来实现我们的自定义委托。

3. 实现虚函数

出去虚析构函数,QAbstractItemDelegate总共有9个虚函数,下面分别介绍。

paint()函数用来重绘view。我们这里选择用随机颜色填充背景:

void CustomeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (!index.isValid() || option.state == QStyle::State_None || !index.isValid())
        return;

    painter->fillRect(option.rect, QColor(m_randomColor(m_generator)));
}

createEditor()destroyEditor()的用途非常明显,双击View的时候会弹出一个行编辑器:

QWidget* CustomeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    return new QLineEdit(parent);
}

void CustomeDelegate::destroyEditor(QWidget *editor, const QModelIndex &index) const
{
    Q_ASSERT(dynamic_cast<QLineEdit*>(editor) != 0);

    delete dynamic_cast<QLineEdit*>(editor);
}

helpEvent()表示帮助事件,当发生QEvent::ToolTip或者QEvent::WhatsThis事件的时候,就会调用这个函数,我们这里根据事件不同显示不同内容的Tool Tip:

bool CustomeDelegate::helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index)
{
    if (event->type() == QEvent::ToolTip) {
        QToolTip::showText(QCursor::pos(), QString("CustomeDelegate Tooltip"), reinterpret_cast<QWidget*>(view), option.rect, 1000);
    } else if (event->type() == QEvent::WhatsThis) {
        QToolTip::showText(QCursor::pos(), QString("CustomeDelegate Whatsthis"), reinterpret_cast<QWidget*>(view), option.rect, 1000);
    }
    return true;
}

当Editor显示的时候,会调用setEditorData()这个函数来显示默认的文字:

void CustomeDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    dynamic_cast<QLineEdit*>(editor)->setText(index.data(Qt::DisplayRole).toString());
}

setModelData()这个函数用来更新Model中的数据:

void CustomeDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    model->setData(index, dynamic_cast<QLineEdit*>(editor)->text(), Qt::DisplayRole);
}

updateEditorGeometry()这个函数也会在Editor显示的时候被调用,双击不同方格时,我们用它来更新编辑器的位置和大小:

void CustomeDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    dynamic_cast<QLineEdit*>(editor)->setFixedSize(option.rect.width(), option.rect.height());
    dynamic_cast<QLineEdit*>(editor)->move(option.rect.topLeft());
}

4. 运行结果

result-img1 result-img2 result-img3

完整代码见此处

posted @ 2017-10-01 20:13  lgxZJ  阅读(5491)  评论(0编辑  收藏  举报