QT风格(QStyle):绘制一个自定义QProgressBar

参考:[Qt]自定义QStyle——实现QProgressBar自定义样式

参考:QStyle Progress Bar 样式设计(十七)

前面已经知道了绘制控件只需要把控件的子元素/子控件绘制出来即可。

一个默认的QProgressBar子元素如下:

 QProgressBar只有子元素没有子控件(可以与之交互的是子控件,只能展示不能交互的叫子元素)

设计图:

根据这个设计图,各个子元素的位置:

QRect myProgressBarStyle::subElementRect(SubElement element,
                                         const QStyleOption *option,
                                         const QWidget *widget) const
{
    switch (element)
    {
    case CE_ProgressBarContents:
        return widget->rect();
    case SE_ProgressBarContents:
        return widget->rect();
    case SE_ProgressBarLabel:
    {
        if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option))
        {
            if(pb->orientation == Qt::Vertical)
            {
                return QRect(0,widget->height() * 0.4,widget->width(),widget->height() * 0.2);
            }
            else
            {
                return QRect(widget->width()*0.4,0,widget->width()*0.2,widget->height());
            }
        }
    }
    break;
    default:
        return QProxyStyle::subElementRect(element,option,widget);
    }
}

完整代码:

.h文件:

#ifndef MYPROGRESSBARSTYLE_H
#define MYPROGRESSBARSTYLE_H

#include <QProxyStyle>

class myProgressBarStyle : public QProxyStyle
{
public:
    myProgressBarStyle();
protected:
    void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const override;
    void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const override;
    QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const override;
};

#endif // MYPROGRESSBARSTYLE_H

.cpp文件:

#include "myprogressbarstyle.h"
#include <QPainter>
#include <QStyleOption>
#include <QDebug>
#include <qdrawutil.h>
myProgressBarStyle::myProgressBarStyle()
{

}

void myProgressBarStyle::drawControl(ControlElement element,
                                     const QStyleOption *option,
                                     QPainter *painter,
                                     const QWidget *widget)const
{
    switch (element)
    {
    case CE_ProgressBar://整个进度条部分,整个绘制QProgressBar的开始
    {
        if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option))
        {
            QStyleOptionProgressBar subopt = *pb;
            painter->save();
            painter->setBrush(QColor(88, 88, 88, 63));
            painter->setPen(Qt::transparent);

            QRect rect = subElementRect(SE_ProgressBarContents,pb,widget);
            int diameter = 12;
            int cx = 100 * diameter / rect.width();
            int cy = 100 * diameter / rect.height();
            painter->drawRoundRect(rect, cx, cy);//绘制圆角矩形
            painter->restore();

            drawControl(CE_ProgressBarContents, &subopt, painter, widget);
            if (pb->textVisible)
            {
                subopt.rect = subElementRect(SE_ProgressBarLabel, pb, widget);
                drawControl(CE_ProgressBarLabel, &subopt, painter, widget);
            }
        }
    }
    break;
    case CE_ProgressBarContents://进度条内容部分,区别于文本部分,只包含进度区域
    {
        if (const QStyleOptionProgressBarV2 *pb = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option))
        {
            QRect rect = pb->rect;
            QStyleOptionProgressBarV2 drawPb = *pb;
            if(pb->orientation == Qt::Horizontal)
            {
                drawPb.rect.setWidth((pb->progress * rect.width()) / pb->maximum);
            }
            else
            {
                drawPb.rect.setHeight((pb->progress * rect.height()) / pb->maximum);
            }
            drawPrimitive(PE_IndicatorProgressChunk, &drawPb, painter, widget);
        }
    }
    break;
    case CE_ProgressBarGroove://这个元素查看Qt源码发现这个部分宽度为固定值1,而且从效果上看是介于内容和文本之间的部分
    {
        if (option->rect.isValid())
            qDrawShadePanel(painter, option->rect, option->palette, true, 1,
                            &option->palette.brush(QPalette::Window));
    }
    break;
    case CE_ProgressBarLabel://进度条文本部分
    {
        if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option))
        {
            QPalette::ColorRole textRole = QPalette::Text;
            QRect rect = subElementRect(SE_ProgressBarLabel,option,widget);
            QPalette shadowPalette = pb->palette;
            shadowPalette.setColor(textRole, QColor("#ffffff"));
            QString text = "完成度:" + pb->text;
            proxy()->drawItemText(painter, rect, Qt::AlignCenter | Qt::TextSingleLine,
                                  shadowPalette, pb->state & State_Enabled, text, textRole);
        }
    }
    break;
    default:
        return QProxyStyle::drawControl(element,option,painter,widget);
    }
}

QRect myProgressBarStyle::subElementRect(SubElement element,
                                         const QStyleOption *option,
                                         const QWidget *widget) const
{
    switch (element)
    {
    case CE_ProgressBarContents:
        return widget->rect();
    case SE_ProgressBarContents:
        return widget->rect();
    case SE_ProgressBarLabel:
    {
        if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option))
        {
            if(pb->orientation == Qt::Vertical)
            {
                return QRect(0,widget->height() * 0.4,widget->width(),widget->height() * 0.2);
            }
            else
            {
                return QRect(widget->width()*0.4,0,widget->width()*0.2,widget->height());
            }
        }
    }
    break;
    default:
        return QProxyStyle::subElementRect(element,option,widget);
    }
}

void myProgressBarStyle::drawPrimitive(PrimitiveElement which,
                                       const QStyleOption *option,
                                       QPainter *painter,
                                       const QWidget *widget) const
{
    switch (which)
    {
        case PE_IndicatorProgressChunk://此元素表示进度覆盖区域的元素,windows样式是一小节一小节设定的
        {
            painter->save();
            QLinearGradient linear;
            linear.setStart(0,0);
            linear.setFinalStop(widget->width(), widget->height());
            linear.setColorAt(0, QColor(255,182,193));
            linear.setColorAt(0.5, QColor(100,149,237));
            linear.setColorAt(1, QColor(255,222,173));
            painter->setPen(Qt::NoPen);
            painter->setBrush(linear);
            painter->drawRect(option->rect);
            painter->restore();
        }
        break;
        default:
            QProxyStyle::drawPrimitive(which, option, painter, widget);
    }
}

效果:

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值