QT風格(QStyle):繪製一個自定義QComboBox

友善啊,朋友發表於2020-12-06

繪製QComboBox即把QComboBoxd組成元素繪製出來。

元素如下:

這三個都是子控制元件,可互動的,圖示元素預設是PE_IndicatorArrowDown,一個下箭頭。

繪製設計圖:

過程實在沒啥好說的,繪製套路和前面都一樣,無非是確定好子控制元件/子元素位置,然後在相應位置繪製需要繪製的內容。

完整程式碼:

.h檔案:

#ifndef MYCOMBOBOXSTYLE_H
#define MYCOMBOBOXSTYLE_H

#include <QProxyStyle>

class myComboBoxStyle : public QProxyStyle
{
public:
    myComboBoxStyle();
    void drawComplexControl(ComplexControl which,const QStyleOptionComplex *option,QPainter *painter,const QWidget *widget = nullptr) const override;
    QRect subControlRect(ComplexControl whichControl,const QStyleOptionComplex *option,SubControl whichSubControl,const QWidget *widget = nullptr) const override;
    void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const override;
};

#endif // MYCOMBOBOXSTYLE_H

 .cpp檔案:

#include "mycomboboxstyle.h"
#include <QPainter>
#include <QStyleOptionComplex>
#include <QDebug>

myComboBoxStyle::myComboBoxStyle()
{

}
void myComboBoxStyle::drawComplexControl(ComplexControl which,const QStyleOptionComplex *option,QPainter *painter,const QWidget *widget) const
{
    if (which == CC_ComboBox)
    {
        if(const QStyleOptionComboBox * cbOption = qstyleoption_cast<const QStyleOptionComboBox *>(option))
        {
            painter->save();
            QRect rect = subControlRect(CC_ComboBox, option,SC_ComboBoxFrame).adjusted(+1, +1, -1, -1);
            painter->setBrush(QColor("#128bf1"));
            painter->drawRect(rect);

            rect = subControlRect(CC_ComboBox, option,SC_ComboBoxEditField).adjusted(+2, +2, -2, -2);
            QLinearGradient gradient(rect.topLeft(),rect.bottomRight());
            gradient.setColorAt(0.0, QColor("#fa709a"));
            gradient.setColorAt(1.0, QColor("#fee140"));
            painter->setPen(Qt::NoPen);
            painter->setBrush(gradient);
            painter->drawRect(rect);

            rect = subControlRect(CC_ComboBox, option,SC_ComboBoxArrow).adjusted(+1, +1, -1, -1);
            painter->setPen(Qt::transparent);
            painter->translate(option->rect.x(),option->rect.y());
            QLinearGradient gradient2(rect.topLeft(),rect.bottomRight());
            gradient2.setColorAt(0.0, QColor("#84fab0"));
            gradient2.setColorAt(1.0, QColor("#8fd3f4"));
            painter->setBrush(gradient2);
            painter->drawRect(rect);
            painter->restore();

            QStyleOption arrowOpt(*cbOption);
            arrowOpt.rect = rect.adjusted(+rect.width() * 0.3, +rect.height() * 0.3,
                                          -rect.width() * 0.3, -rect.height() * 0.3);
            drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter);

            if(option->activeSubControls == SC_ComboBoxEditField ||
               option->activeSubControls == SC_ComboBoxArrow)
            {
                painter->save();
                QColor slightlyOpaqueBlack(0, 0, 0, 63);
                painter->setBrush(slightlyOpaqueBlack);
                painter->drawRect(widget->rect());
                painter->restore();
            }
        }
    }
    else
    {
        return QProxyStyle::drawComplexControl(which, option, painter,widget);
    }
}

void myComboBoxStyle::drawPrimitive(PrimitiveElement which, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
{
    switch (which)
    {
        case PE_IndicatorArrowDown:
        {
            painter->save();
            painter->translate(option->rect.x(),option->rect.y());
            QPainterPath drawtriangle;  //畫三角形
            drawtriangle.moveTo(0,0);
            drawtriangle.lineTo(option->rect.width()/2,option->rect.height());
            drawtriangle.lineTo(option->rect.width(),0);
            drawtriangle.lineTo(0,0);
            painter->setPen(QPen(QColor("#128bf1"), 2));
            painter->drawPath(drawtriangle);  //繪製出圖形
            painter->restore();
        }
        break;
        default:
            QProxyStyle::drawPrimitive(which, option, painter, widget);
    }
}

QRect myComboBoxStyle::subControlRect(ComplexControl whichControl,const QStyleOptionComplex *option,SubControl whichSubControl,const QWidget *widget) const
{
    if (whichControl == CC_ComboBox)
    {
        switch (whichSubControl)
        {
            case SC_ComboBoxEditField:
                return QRect(0,0,option->rect.width() * 0.7,option->rect.height()).adjusted(+2, +2, -2, -2);
            case SC_ComboBoxFrame:
                return QRect(0,0,option->rect.width() * 0.7,option->rect.height());
            case SC_ComboBoxArrow:
                return QRect(option->rect.width() * 0.7, 0, option->rect.width() * 0.3, option->rect.height());
            default:
                return QProxyStyle::subControlRect(whichControl, option,whichSubControl, widget);
        }
    }
    else
    {
        return QProxyStyle::subControlRect(whichControl, option,whichSubControl, widget);
    }
}

效果:

 

 

可參考:Qt中QComboBox下拉選單(popup)位置與樣式的控制

相關文章