主页 > 其他  > 

重写QListWidget/QListView的代理,以网格的形式展示Item

重写QListWidget/QListView的代理,以网格的形式展示Item

效果如下:

1、首先我们要设置QListWidget的ViewMode为图片模式IconMode

2、然后确定每个item的大小,重写代理的sizeHint函数

QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override { //假如整个QListWidget每行显示4个item,那么每个item的宽度就是整个QListWidget的宽度减去右边的间距(这里还多减了10px,一行才显示了4个,Qt Bug) //然后除以4,得到每个item的宽度 //然后每个item以正方形为区域 //返回每个item的尺寸 //但是绘制的时候为了显示间距,在每个item的区域绘制时不绘制满,而是将矩形的左上角往内缩spacing的距离 int width = (option.widget->width()-spacing-10) / 4; qDebug()<<"widget with:"<<option.widget->width(); qDebug()<<"item with:"<<width; return QSize(width, width); }

3、然后重写代理的paint函数

void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override { painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing); //每行4个 正方形 //绘制区域:将item实际矩形区域的左上角往内缩spacing的距离 QRect rect = option.rect.adjusted(spacing, spacing, 0, 0); //绘制图像 painter->save(); QPixmap pixmap = index.data(Qt::UserRole+1).value<QPixmap>();//得到item的图片数据 QSize pixmapSize = pixmap.size(); pixmapSize.scale(rect.size(), Qt::KeepAspectRatio); QRect scaledRect(QPoint(0, 0), pixmapSize);//得到图片等比例缩放的矩形 scaledRect.moveTopLeft(rect.topLeft());//将图片缩放后的矩形移动到和绘制局域的左上角重合 painter->drawPixmap(scaledRect.adjusted(2,2,-2,-2), pixmap);//整体往内缩2px,给边框留空间 painter->restore(); painter->save(); if (option.state.testFlag(QStyle::State_Selected)) { //选中,绘制轮廓线 painter->setBrush(Qt::NoBrush); QPen pen; pen.setStyle(Qt::SolidLine); pen.setColor(QColor("#ff0000")); pen.setWidth(2); painter->setPen(pen); painter->drawRect(scaledRect); } painter->restore(); }

 

 完整代码如下:

#ifndef CUSTOMDELETEGATEFORLISTVIEW_H #define CUSTOMDELETEGATEFORLISTVIEW_H #include <QStyledItemDelegate> #include <QPainter> #include<QDebug> class CustomDeletegateForListView :public QStyledItemDelegate { Q_OBJECT public: CustomDeletegateForListView(QObject* parent = nullptr):QStyledItemDelegate(parent){} ~CustomDeletegateForListView() = default; protected: //重写sizeHint函数,这个函数返回的尺寸决定了每个Item的矩形局域的大小 QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override { //假如整个QListWidget每行显示4个item,那么每个item的宽度就是整个QListWidget的宽度减去右边的间距(这里还多减了10px,一行才显示了4个,Qt Bug) //然后除以4,得到每个item的宽度 //然后每个item以正方形为区域 //返回每个item的尺寸 //但是绘制的时候为了显示间距,在每个item的区域绘制时不绘制满,而是将矩形的左上角往内缩spacing的距离 int width = (option.widget->width()-spacing-10) / 4; qDebug()<<"widget with:"<<option.widget->width(); qDebug()<<"item with:"<<width; return QSize(width, width); } void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override { painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing); //每行4个 正方形 //绘制区域:将item实际矩形区域的左上角往内缩spacing的距离 QRect rect = option.rect.adjusted(spacing, spacing, 0, 0); //绘制图像 painter->save(); QPixmap pixmap = index.data(Qt::UserRole+1).value<QPixmap>();//得到item的图片数据 QSize pixmapSize = pixmap.size(); pixmapSize.scale(rect.size(), Qt::KeepAspectRatio); QRect scaledRect(QPoint(0, 0), pixmapSize);//得到图片等比例缩放的矩形 scaledRect.moveTopLeft(rect.topLeft());//将图片缩放后的矩形移动到和绘制局域的左上角重合 painter->drawPixmap(scaledRect.adjusted(2,2,-2,-2), pixmap);//整体往内缩2px,给边框留空间 painter->restore(); painter->save(); if (option.state.testFlag(QStyle::State_Selected)) { //选中,绘制轮廓线 painter->setBrush(Qt::NoBrush); QPen pen; pen.setStyle(Qt::SolidLine); pen.setColor(QColor("#ff0000")); pen.setWidth(2); painter->setPen(pen); painter->drawRect(scaledRect); } painter->restore(); } private: int spacing = 10;//每个网格之间的间距,这个值可以更改 }; #endif // CUSTOMDELETEGATEFORLISTVIEW_H

不支持随着QListWidget的缩放,显示的item也跟着缩放

只能在resizeEvent中将原来的delegate删除,new一个新的delegate设置进去

标签:

重写QListWidget/QListView的代理,以网格的形式展示Item由讯客互联其他栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“重写QListWidget/QListView的代理,以网格的形式展示Item