首页 > 其他分享 >QTreeView代理QStyledItemDelegate实现按钮、图标的绘制

QTreeView代理QStyledItemDelegate实现按钮、图标的绘制

时间:2024-09-14 16:37:55浏览次数:1  
标签:24 QRect QTreeView QStyle buttonOption rectItem QStyledItemDelegate painter 图标

1.需求描述

代理实现按钮图标状态的绘制

实现方法

(1)重写paint函数,根据type类型绘制案件、文件夹、监控点、视频任务;

 

为了实现不同的item的样式,需要继承QStyledItemDelegate类型实现TreeTaskDelegate。重写paint函数,根据不同的类型type去绘制不同的按钮和状态;

void TreeTaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (painter == nullptr || !index.isValid())
    {
        return;
    }
    if (option.state & QStyle::State_Editing)
    {
        return;
    }
    if (index.flags())
    {
    }
    QFont gfont;
    gfont.setFamily("Microsoft YaHei UI");
    gfont.setPixelSize(16);
    painter->setFont(gfont);
    QStyleOptionViewItem viewOption(option);
    initStyleOption(&viewOption, index);
    if (option.state.testFlag(QStyle::State_HasFocus))
        viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
    QStyledItemDelegate::paint(painter, viewOption, index);
    QVariantMap var = index.data(Qt::UserRole).toMap();
    if (var.contains("type"))
    {
        QString strType = var.value("type").toString();
        if (strType == "0")//case
        {
            paintCase(painter, viewOption, index);
        }
        else if (strType == "1")//folder
        {
            paintFolder(painter, viewOption, index);
        }
        else if (strType=="3")//camera
        {
            paintCamera(painter, viewOption, index);
        }
        else if(strType=="2")//video
        {
            paintVideo(painter, viewOption, index);
        }    
    }
}

(2)以绘制案件为例,绘制按钮,状态和名称;

void TreeTaskDelegate::paintCase(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (option.state .testFlag(QStyle::State_Editing))//正在编辑状态,不绘制
    {
        return;
    }
    QVariantMap caseinfo = index.data(Qt::UserRole).toMap();
    //绘制案件的图标
    QRect rectItem = option.rect;
    QIcon icon(":/analysisCenter/Resources/analysisCenter/caseicon.svg"); // 替换为你的图标路径
    QRect iconRect(rectItem.x() + 20, rectItem.y() + 8, 24, 24); // 设置图标大小和位置
    icon.paint(painter, iconRect);
    if (caseinfo.contains("editing"))//编辑状态,不绘制
    {
        return;
    }
    QRect nameRect;
    QStyleOptionButton buttonOption;
    buttonOption.features = QStyleOptionButton::Flat;
    buttonOption.state |= QStyle::State_Enabled;
    if (option.state.testFlag(QStyle::State_MouseOver)) //鼠标hover
    {
        QRect rectTop = QRect(rectItem.x() + 75, rectItem.y() + 8, 24, 24);
        QRect rectEdit = QRect(rectItem.x() + 95, rectItem.y() + 8, 24, 24);
        QRect rectCreateDir = QRect(rectItem.x() + 125, rectItem.y() + 8, 24, 24);
        QRect rectInput = QRect(rectItem.x() + 155, rectItem.y() + 8, 24, 24);
        QRect rectDelete = QRect(rectItem.x() + 185, rectItem.y() + 8, 24, 24);
        nameRect = QRect(rectItem.x() + 44, rectItem.y() + 8, 20, 24);
        if (caseinfo.contains("top")&&caseinfo.value("top").toString()=="1")
        {
            buttonOption.state |= QStyle::State_On; // 设置为选中状态,取消置顶图标
        }
        else
        {
            buttonOption.state |= QStyle::State_Off; // 设置为选中状态,置顶图标
        }
        buttonOption.rect = rectTop;
        m_pbTop.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbTop);//绘制创建文件夹
        buttonOption.state = QStyle::State_Enabled;
        buttonOption.rect = rectEdit;
        m_pbEditName.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbEditName);//绘制创建文件夹
        buttonOption.rect = rectCreateDir;
        m_pbCreateFold.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbCreateFold);//绘制创建文件夹
        buttonOption.rect = rectInput;
        m_pbInput.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbInput);//绘制导入按钮
        buttonOption.rect = rectDelete;
        m_pbDelete.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbDelete);//绘删除按钮
    }
    else
    {
        nameRect = QRect(rectItem.x() + 44, rectItem.y() + 8, 120, 24);
    }
    if (caseinfo.contains("TasksStatistic"))
    {
        TasksStatistic statstic = caseinfo.value("TasksStatistic").value<TasksStatistic>();
        QString strColor = "";
        if ((statstic.unfinished + statstic.finished + statstic.failed) != 0)
        {
            QString strState = "";
            if (statstic.unfinished == 0)
            {
                strColor = "#2080F7";
                strState="已完成";
            }
            else
            {
                strColor = "#09D245";
                strState = "解析中";
            }
            if (strColor!="")
            {
                painter->save();
                painter->setRenderHint(QPainter::Antialiasing, true);
                painter->setPen(QPen(QColor(strColor), 1, Qt::SolidLine, Qt::RoundCap));
                painter->setBrush(QBrush(QColor(strColor), Qt::SolidPattern));
                //绘圆
                painter->drawEllipse(rectItem.x() + 210 + 3, rectItem.y() + 17, 6, 6);
                painter->restore();
            }
            
            QRect rectState = QRect(rectItem.x() + 210, rectItem.y() + 10, 54, 20);
            buttonOption.rect = rectState;
            m_pbState.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbState);//绘制区域按钮
            QFont font;
            font.setPixelSize(12);
            painter->save();
            painter->setFont(font);
            QRect rectText(rectItem.x() + 210+10, rectItem.y() + 10, 54, 20);
            painter->drawText(rectText, Qt::AlignLeft | Qt::AlignVCenter, strState);
            painter->restore();
        }
    }
    paintName(painter, nameRect, caseinfo.value("name").toString());
    //painter->drawText(nameRect, Qt::AlignLeft|Qt::AlignVCenter, caseinfo.value("name").toString());
}

(3)按钮m_pbTop等是代理中定义的QPushButton对象;要设置按钮的图标样式

m_pbTop.setStyleSheet(QLatin1String("QPushButton:checked\n"
        "{\n"
        "background-image: url(:/analysisCenter/Resources/analysisCenter/canceltop-nor.svg) no-repeat center center;\n"
        "background-repeat:no-repeat;\n"
        "background-color: Transparent;\n"
        "}\n"
        "QPushButton:checked:hover\n"
        "{\n"
        "background-image: url(:/analysisCenter/Resources/analysisCenter/canceltop-nor.svg) no-repeat center center;\n"
        "background-repeat:no-repeat;\n"
        "background-color: Transparent;\n"
        "}\n"
        "QPushButton\n"
        "{\n"
        "background-image: url(:/analysisCenter/Resources/analysisCenter/top-nor.svg) no-repeat center center;\n"
        "background-repeat:no-repeat;\n"
        "background-color: Transparent;\n"
        "}\n"
        "QPushButton:hover\n"
        "{\n"
        "background-image: url(:/analysisCenter/Resources/analysisCenter/top-nor.svg) no-repeat center center;\n"
        "background-repeat:no-repeat;\n"
        "border-style: flat;\n"
        "background-color: rgba(0,0,0,0.20);\n"
        "}\n"
        ""));

这样就可以实现按钮的绘制和布局;但是按钮绘制好以后,点击还是无响应的,需要自行实现按钮的点击信号和响应函数;

看下一篇如何实现按钮的鼠标移动点击响应;

 

 

(1)重写paint函数,根据type类型绘制案件、文件夹、监控点、视频任务;

为了实现不同的item的样式,需要继承QStyledItemDelegate类型实现TreeTaskDelegate。重写paint函数,根据不同的类型type去绘制不同的按钮和状态;

voidTreeTaskDelegate::paint(QPainter *painter, constQStyleOptionViewItem &option, constQModelIndex &index) const

{

    if (painter == nullptr || !index.isValid())

    {

        return;

    }

    if (option.state&QStyle::State_Editing)

    {

        return;

    }

    if (index.flags())

    {

    }

    QFontgfont;

    gfont.setFamily("Microsoft YaHei UI");

    gfont.setPixelSize(16);

    painter->setFont(gfont);

    QStyleOptionViewItemviewOption(option);

    initStyleOption(&viewOption, index);

    if (option.state.testFlag(QStyle::State_HasFocus))

        viewOption.state=viewOption.state^QStyle::State_HasFocus;

    QStyledItemDelegate::paint(painter, viewOption, index);

    QVariantMapvar = index.data(Qt::UserRole).toMap();

    if (var.contains("type"))

    {

        QStringstrType = var.value("type").toString();

        if (strType=="0")//case

        {

            paintCase(painter, viewOption, index);

        }

        elseif (strType=="1")//folder

        {

            paintFolder(painter, viewOption, index);

        }

        elseif (strType=="3")//camera

        {

            paintCamera(painter, viewOption, index);

        }

        elseif(strType=="2")//video

        {

            paintVideo(painter, viewOption, index);

        }  

    }

}

(2)以绘制案件为例,绘制按钮,状态和名称;

voidTreeTaskDelegate::paintCase(QPainter *painter, constQStyleOptionViewItem &option, constQModelIndex &index) const

{

    if (option.state .testFlag(QStyle::State_Editing))//正在编辑状态,不绘制

    {

        return;

    }

    QVariantMapcaseinfo = index.data(Qt::UserRole).toMap();

    //绘制案件的图标

    QRectrectItem = option.rect;

    QIconicon(":/analysisCenter/Resources/analysisCenter/caseicon.svg"); // 替换为你的图标路径

    QRecticonRect(rectItem.x() + 20, rectItem.y() + 8, 24, 24); // 设置图标大小和位置

    icon.paint(painter, iconRect);

    if (caseinfo.contains("editing"))//编辑状态,不绘制

    {

        return;

    }

    QRectnameRect;

    QStyleOptionButtonbuttonOption;

    buttonOption.features=QStyleOptionButton::Flat;

    buttonOption.state|=QStyle::State_Enabled;

    if (option.state.testFlag(QStyle::State_MouseOver)) //鼠标hover

    {

        QRectrectTop = QRect(rectItem.x() + 75, rectItem.y() + 8, 24, 24);

        QRectrectEdit = QRect(rectItem.x() + 95, rectItem.y() + 8, 24, 24);

        QRectrectCreateDir = QRect(rectItem.x() + 125, rectItem.y() + 8, 24, 24);

        QRectrectInput = QRect(rectItem.x() + 155, rectItem.y() + 8, 24, 24);

        QRectrectDelete = QRect(rectItem.x() + 185, rectItem.y() + 8, 24, 24);

        nameRect=QRect(rectItem.x() + 44, rectItem.y() + 8, 20, 24);

        if (caseinfo.contains("top")&&caseinfo.value("top").toString()=="1")

        {

            buttonOption.state|=QStyle::State_On; // 设置为选中状态,取消置顶图标

        }

        else

        {

            buttonOption.state|=QStyle::State_Off; // 设置为选中状态,置顶图标

        }

        buttonOption.rect=rectTop;

        m_pbTop.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbTop);//绘制创建文件夹

        buttonOption.state=QStyle::State_Enabled;

        buttonOption.rect=rectEdit;

        m_pbEditName.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbEditName);//绘制创建文件夹

        buttonOption.rect=rectCreateDir;

        m_pbCreateFold.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbCreateFold);//绘制创建文件夹

        buttonOption.rect=rectInput;

        m_pbInput.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbInput);//绘制导入按钮

        buttonOption.rect=rectDelete;

        m_pbDelete.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbDelete);//绘删除按钮

    }

    else

    {

        nameRect=QRect(rectItem.x() + 44, rectItem.y() + 8, 120, 24);

    }

    if (caseinfo.contains("TasksStatistic"))

    {

        TasksStatisticstatstic = caseinfo.value("TasksStatistic").value<TasksStatistic>();

        QStringstrColor = "";

        if ((statstic.unfinished + statstic.finished + statstic.failed) != 0)

        {

            QStringstrState = "";

            if (statstic.unfinished == 0)

            {

                strColor="#2080F7";

                strState="已完成";

            }

            else

            {

                strColor="#09D245";

                strState="解析中";

            }

            if (strColor!="")

            {

                painter->save();

                painter->setRenderHint(QPainter::Antialiasing, true);

                painter->setPen(QPen(QColor(strColor), 1, Qt::SolidLine, Qt::RoundCap));

                painter->setBrush(QBrush(QColor(strColor), Qt::SolidPattern));

                //绘圆

                painter->drawEllipse(rectItem.x() + 210 + 3, rectItem.y() + 17, 6, 6);

                painter->restore();

            }

           

            QRectrectState = QRect(rectItem.x() + 210, rectItem.y() + 10, 54, 20);

            buttonOption.rect=rectState;

            m_pbState.style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, &m_pbState);//绘制区域按钮

            QFontfont;

            font.setPixelSize(12);

            painter->save();

            painter->setFont(font);

            QRectrectText(rectItem.x() + 210+10, rectItem.y() + 10, 54, 20);

            painter->drawText(rectText, Qt::AlignLeft|Qt::AlignVCenter, strState);

            painter->restore();

        }

    }

    paintName(painter, nameRect, caseinfo.value("name").toString());

    //painter->drawText(nameRect, Qt::AlignLeft|Qt::AlignVCenter, caseinfo.value("name").toString());

}

按钮m_pbTop是QPushButton对象;要设置按钮的图标样式

//案件的按钮

    m_pbTop.setStyleSheet(QLatin1String("QPushButton:checked\n"

        "{\n"

        "background-image: url(:/analysisCenter/Resources/analysisCenter/canceltop-nor.svg) no-repeat center center;\n"

        "background-repeat:no-repeat;\n"

        "background-color: Transparent;\n"

        "}\n"

        "QPushButton:checked:hover\n"

        "{\n"

        "background-image: url(:/analysisCenter/Resources/analysisCenter/canceltop-nor.svg) no-repeat center center;\n"

        "background-repeat:no-repeat;\n"

        "background-color: Transparent;\n"

        "}\n"

        "QPushButton\n"

        "{\n"

        "background-image: url(:/analysisCenter/Resources/analysisCenter/top-nor.svg) no-repeat center center;\n"

        "background-repeat:no-repeat;\n"

        "background-color: Transparent;\n"

        "}\n"

        "QPushButton:hover\n"

        "{\n"

        "background-image: url(:/analysisCenter/Resources/analysisCenter/top-nor.svg) no-repeat center center;\n"

        "background-repeat:no-repeat;\n"

        "border-style: flat;\n"

        "background-color: rgba(0,0,0,0.20);\n"

        "}\n"

        ""));

这样就可以实现按钮的绘制和布局;但是按钮绘制好以后,点击还是无响应的,需要自行实现按钮的点击信号和响应函数;

标签:24,QRect,QTreeView,QStyle,buttonOption,rectItem,QStyledItemDelegate,painter,图标
From: https://www.cnblogs.com/bclshuai/p/18414275

相关文章

  • vue3 + vite 使用 vite-plugin-svg-icons 插件显示本地 svg 图标的方法
    1.安装vite-plugin-svg-icons插件yarnaddvite-plugin-svg-icons-D//或者npminstallvite-plugin-svg-icons-D//或者pnpminstallvite-plugin-svg-icons-D2.使用vite-plugin-svg-icons插件2.1在项目根目录查找vite.config.js,进行配置import{createS......
  • QT QSystemTrayIcon创建系统托盘区图标失败
    前言在开发个人项目时,需要在Windows系统托盘区创建一个图标,在代码中,我使用的是QT的QSystemTrayIcon类进行图标创建,但是在加上图片资源后,一直没有图标显现。我使用的是Qt6,Windows11系统。示例代码QSystemTrayIcon*trayIcon=newQSystemTrayIcon(this);trayIco......
  • C#中设置自定义控件工具箱图标
    在设计自定义控件时,系统默认生成的图标比较单一且难看,如何为控件设计自己的图标呢,这里给出了一种基于ToolBoxBitmap 属性设置自定义控件工具箱图标的方法。1、首先将图标文件名改为自定义控件名,如自定义控件类为: public partial class UserDefindControl: UserControl {......
  • vue3 中使用 icon 图标的 3 种方案
    1.element-iconElementPlus提供了一套常用的图标集合。1.1.安装#选择一个你喜欢的包管理器#NPM$npminstall@element-plus/icons-vue#Yarn$yarnadd@element-plus/icons-vue#pnpm$pnpminstall@element-plus/icons-vue#选择一个你喜欢的包管理器1.2.......
  • 组策略统一在桌面显示计算机图标
    可以通过注册表修改实现桌面默认显示相应图标。域环境下,桌面统一显示计算机,文档,网络图标:新建GPO,用户配置--注册表---更新,建立以下内容。显示用户的文件REGADDHKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel {59031a47-3f72-44a7......
  • 实战项目01-icon图标修改
    修改项目图标引入图片资源,放入指定目录,覆盖掉之前图片即可目录:entry>src>main>resources>base>media图片:startIcon.png foreground.pngbackground.png  修改项目标题需要修改EntryAbility_label字段的值。同时因为项目没有做国际化语言配置,所以直接使用......
  • Go语言编译时为exe添加图标和属性信息的方法
    在使用Go语言开发应用程序时,有个非常方便的地方就是编译得到的可执行文件可以不依赖任何动态链接库、并且不需要任何运行环境即可运行,这一点Java就没那么方便了。不过在Windows上编译得到的exe文件,默认是不带图标和任何属性信息的,那么怎么才能让我们编译得到的可执行文件带上图标......
  • echart map图标切换多选,单选,默认选中
    需求是echart默认地图选中之前的去过的城市,一开始多选,后面点击为单选constoption={tooltip:{trigger:'item',formatter:'{b}'},series:[{type:'map',roam:true,//是否开启缩放和平移zoom:1,//当前视角缩放比例......
  • 关于Keil uVision5软件下的界面图标错乱问题
    偶然在进行程序书写的时候,发现Keil界面下的原有的DownLoad图标变成了粘贴图标,其他图标也错乱,如下:        关于这个问题,解决方法很简单,窗口界面出现了问题就找窗口界面设置:        点击“Window-> Reset View to Default”将视图重置为默认值    ......
  • 办公软件:管理和组织菜单栏图标Bartender 4 for Mac
    Bartender是一款专为macOS用户设计的强大软件,主要用于管理和组织菜单栏图标。软件下载地址主要特点:一、菜单栏图标管理菜单栏图标隐藏:用户可隐藏菜单栏图标,仅在需要时显示,减少视觉干扰,使界面更整洁专注。可自定义的菜单栏排序:提供直观拖放界面,用户能自定义图标的顺序和......