当前位置: 首页 > news >正文

重写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设置进去

相关文章:

  • jvm中各个参数的理解
  • Ubuntu编译ZLMediaKit
  • react实例与总结(二)
  • ollama修改监听ip: 0.0.0.0
  • deepseek清华大学第二版 如何获取 DeepSeek如何赋能职场应用 PDF文档 电子档(附下载)
  • 计算机网络基础杂谈(局域网、ip、子网掩码、网关、DNS)
  • 分布式 IO 模块:水力发电设备高效控制的关键
  • 正则表达式特殊字符
  • Nginx 常用命令和部署详解及案例示范
  • arthas教程(还没有全部写完,有空更新)
  • QT事件循环
  • 【Spring详解五】bean的加载
  • Debian软件包重构
  • 第三章:Transformer模型探索
  • ECMAScript6----var、let、const
  • 【Pandas】pandas Series rename_axis
  • vue3面试题进阶版
  • 【设计模式精讲】创建型模式之原型模式(深克隆、浅克隆)
  • [特殊字符]边缘计算课程资料整理|从零到实战全攻略[特殊字符]
  • Rust配置笔记
  • 海南高院通报去年知产领域司法保护状况:审结民事一审案件4847起
  • 中信证券:“国家队”未曾减持ETF,应充分相信国家维稳决心
  • 《2025职场人阅读报告》:超半数会因AI改变阅读方向
  • 拖车10公里收1900元?货车司机质疑收费过高,潮州饶平县市监局已介入
  • 限制再放宽!新版市场准入负面清单缩减到106项
  • 法治日报:强制统一店铺广告牌匾事件何以频发?