qt-渲染原理( 三 )


are GUIthat areand often used by.
主元素代表那些公共的GUI元素 , 主要用于GUI控件复用 。例如这个主元素就进场被多种控件用来绘制输入焦点 。包含两个主元素n、 。
是一套抽象接口 , 它定义了实现界面控件外观的一系列api并且不能用来被实例化:
这个自定义的样式分为两部分 , 箭头区域和非箭头区域 。非箭头区域包含和up 。由于不负责绘制下拉框(由绘制) , 我们只能更改下拉框的位置和大小(这里我们不做改变) 。箭头区域包含背景区和n 。
箭头区域我们用一个辐射渐变来绘制背景 , 并且在鼠标Hover或者按下的时候更改渐变的颜色来重绘 , 中间的下拉箭头我们复用的实现来完成 。
.h
#ifndef CUSTOMESTYLE_H#define CUSTOMESTYLE_H#include class CustomeStyle : public QProxyStyle{public:virtual void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const;virtual void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const;virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const;//not used in our demovirtual QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const;virtual QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const;virtual QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const;private:void drawArrowArea(const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const;private:static bool m_arrowAreaHovered;};#endif // CUSTOMESTYLE_H
#include "CustomeStyle.h"#include #include #include #include #include bool CustomeStyle::m_arrowAreaHovered = false;void CustomeStyle::drawComplexControl(QStyle::ComplexControl control,const QStyleOptionComplex *option,QPainter *painter,const QWidget *widget) const{switch (control) {case CC_ComboBox:{drawArrowArea(option, painter, widget);drawControl(CE_ComboBoxLabel, option, painter, widget);break;}default:QProxyStyle::drawComplexControl(control, option, painter, widget);}}void CustomeStyle::drawArrowArea(const QStyleOptionComplex *option,QPainter *painter,const QWidget *widget) const{QRect arrowBoxRect = option->rect;arrowBoxRect.adjust(option->rect.width() * 0.8, 0, 0, 0);auto arrowAreaColor = Qt::darkCyan;m_arrowAreaHovered = arrowBoxRect.contains(widget->mapFromGlobal(QCursor::pos()));if (option->state & State_MouseOver && m_arrowAreaHovered)arrowAreaColor = Qt::cyan;else if (option->state & State_On && m_arrowAreaHovered)arrowAreaColor = Qt::darkMagenta;QRadialGradient gradient(arrowBoxRect.center(),arrowBoxRect.width());gradient.setColorAt(0.0, Qt::gray);gradient.setColorAt(1.0, arrowAreaColor);painter->fillRect(arrowBoxRect, QBrush(gradient));auto arrowDownOption = *option;auto adjustPixel = arrowBoxRect.width() * 0.2;arrowDownOption.rect = arrowBoxRect.adjusted(adjustPixel,adjustPixel,-adjustPixel,-adjustPixel);drawPrimitive(PE_IndicatorArrowDown, &arrowDownOption, painter, widget);}void CustomeStyle::drawControl(QStyle::ControlElement element,const QStyleOption *option,QPainter *painter,const QWidget *widget) const{switch (element) {case CE_ComboBoxLabel:{auto comboBoxOption = qstyleoption_cast(option);if (comboBoxOption == nullptr)return;QColor gradientColors[] = {Qt::yellow,Qt::green,Qt::blue,Qt::red};QColor penColor = Qt::white;if (option->state & State_MouseOver && !m_arrowAreaHovered) {for (auto& color : gradientColors)color.setAlpha(80);penColor.setAlpha(80);} else if (option->state & State_On && !m_arrowAreaHovered) {for (auto& color : gradientColors)color = color.darker(300);penColor = penColor.darker(300);}QRect labelRect = comboBoxOption->rect;labelRect.adjust(0, 0, -(labelRect.width() * 0.2), 0);QLinearGradient linearGradient(labelRect.topLeft(), labelRect.bottomRight());for (int i = 0; i