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类型的。这个例子非常有代表性,要在模型视图框架里面处理自定义的数据类型可以参考之。