Qt模型视图框架:自定义委托(星形委托)

1、来自官方demo:Books

星形是图片:

    QPixmap star;

绘制:

模型中存在的数据是int类型的,绘制的时候数字是几就绘制几个星号图片。

设置星号个数:

根据计算鼠标按下的位置确定值。

2、来自官方demo:Star Delegate Example

 自定义一个表示星级的类:

 添加数据时:

和上一个例子里面显示是星号但实际上在模型里面是int类型不同,这里在模型里面的数据类型是定义的StarRating类型。

定义一个小部件用来显示和编辑星级,鼠标事件改变星星个数:

#include <QtWidgets>
#include "stareditor.h"
#include "starrating.h"
#include <QDebug>

//自定义的星号编辑器,用于委托
StarEditor::StarEditor(QWidget *parent)
    : QWidget(parent)
{
    setMouseTracking(true);//设置鼠标跟踪生效,如即使没有按键被按下,部件也会接收鼠标移动事件
    setAutoFillBackground(true);
}

QSize StarEditor::sizeHint() const
{
    return myStarRating.sizeHint();
}

void StarEditor::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    myStarRating.paint(&painter, rect(), this->palette(), StarRating::Editable);
}

void StarEditor::mouseMoveEvent(QMouseEvent *event)
{
    int star = starAtPosition(event->x());

    if (star != myStarRating.starCount() && star != -1)
    {
        myStarRating.setStarCount(star);//设置星号个数
        update();//重绘星号
    }
}

void StarEditor::mouseReleaseEvent(QMouseEvent * /* event */)
{
    qDebug()<<"编辑完成";
    emit editingFinished();
}

//根据鼠标位置确定星号个数
int StarEditor::starAtPosition(int x)
{
    int star = (x / (myStarRating.sizeHint().width() / myStarRating.maxStarCount())) + 1;
    if (star <= 0 || star > myStarRating.maxStarCount())
    {
        return -1;
    }

    return star;
}

委托:

#include <QtWidgets>
#include "stardelegate.h"
#include "stareditor.h"
#include "starrating.h"

//自定义委托
void StarDelegate::paint(QPainter *painter,
                         const QStyleOptionViewItem &option,//QStyleOptionViewItem用于描述用于在视图小部件中绘制项的参数
                         const QModelIndex &index) const
{
    if (index.data().canConvert<StarRating>())//如果模型项中的数据能转换成星号
    {
        StarRating starRating = qvariant_cast<StarRating>(index.data());

        if (option.state & QStyle::State_Selected)//选中了此项
        {
            painter->fillRect(option.rect, option.palette.highlight());
        }

        //重绘星号
        starRating.paint(painter, option.rect, option.palette, StarRating::ReadOnly);
    }
    else
    {
        QStyledItemDelegate::paint(painter, option, index);
    }
}

QSize StarDelegate::sizeHint(const QStyleOptionViewItem &option,
                             const QModelIndex &index) const
{
    if (index.data().canConvert<StarRating>())//如果模型项中的数据能转换成星号
    {
        StarRating starRating = qvariant_cast<StarRating>(index.data());
        return starRating.sizeHint();
    }
    else
    {
        return QStyledItemDelegate::sizeHint(option, index);
    }
}

QWidget *StarDelegate::createEditor(QWidget *parent,
                                    const QStyleOptionViewItem &option,
                                    const QModelIndex &index) const

{
    if (index.data().canConvert<StarRating>())//星号列 星号编辑框
    {
        StarEditor *editor = new StarEditor(parent);
        connect(editor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor()));
        return editor;
    }
    else//其他列 默认的编辑框
    {
        return QStyledItemDelegate::createEditor(parent, option, index);
    }
}

//设置开始编辑时显示的数据
void StarDelegate::setEditorData(QWidget *editor,
                                 const QModelIndex &index) const
{
    if (index.data().canConvert<StarRating>())
    {
        StarRating starRating = qvariant_cast<StarRating>(index.data());//单元格中的星号
        StarEditor *starEditor = qobject_cast<StarEditor *>(editor);//星号编辑框
        starEditor->setStarRating(starRating);
    }
    else
    {
        QStyledItemDelegate::setEditorData(editor, index);
    }
}

//将委托中的数据更新到模型
void StarDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                const QModelIndex &index) const
{
    if (index.data().canConvert<StarRating>())
    {
        StarEditor *starEditor = qobject_cast<StarEditor *>(editor);
        model->setData(index, QVariant::fromValue(starEditor->starRating()));
    }
    else
    {
        QStyledItemDelegate::setModelData(editor, model, index);
    }
}

void StarDelegate::commitAndCloseEditor()
{
    StarEditor *editor = qobject_cast<StarEditor *>(sender());
    emit commitData(editor);
    emit closeEditor(editor);
}

在委托里面处理的数据都是StarRating类型的。这个例子非常有代表性,要在模型视图框架里面处理自定义的数据类型可以参考之。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值