feat: Repaint the skin of a custom control, and the painting is complete

MyStyle has completed, QStylePainter's inheritance rewrite has not yet started
This commit is contained in:
muli 2020-02-20 00:47:18 +08:00
parent 158deb7c80
commit 77115da29d
6 changed files with 303 additions and 11 deletions

View File

@ -24,7 +24,8 @@
#
#-------------------------------------------------
QT += core gui
#xxxPrivate 继承 Q-xxxx-Private的话,是需要的添加 core-private有一些核心方法? 可能不开放)
QT += core gui core-private # 若是需要继承 widgets相关需要添加 widgets-private
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
@ -47,11 +48,14 @@ CONFIG += c++11
SOURCES += \
main.cpp \
widget.cpp \
mystyle.cpp
mystyle.cpp \
myswitchbutton.cpp
HEADERS += \
widget.h \
mystyle.h
mystyle.h \
myswitchbutton.h \
myswitchbutton_p.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin

View File

@ -30,6 +30,46 @@ MyStyle::MyStyle()
}
void MyStyle::drawPrimitive(MyStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const
{
proxy()->drawPrimitive(static_cast<QStyle::PrimitiveElement>(pe), opt, p, w);
}
void MyStyle::drawControl(MyStyle::ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w) const
{
proxy()->drawControl(static_cast<QStyle::ControlElement>(element), opt, p, w);
}
QRect MyStyle::subElementRect(MyStyle::SubElement subElement, const QStyleOption *option, const QWidget *widget) const
{
return proxy()->subElementRect(static_cast<QStyle::SubElement>(subElement), option, widget);
}
//void MyStyle::drawComplexControl(MyStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const
//{
//}
//QRect MyStyle::subControlRect(MyStyle::ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const
//{
// return QRect();
//}
int MyStyle::pixelMetric(MyStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
{
return proxy()->pixelMetric(static_cast<QStyle::PixelMetric>(metric), option, widget);
}
//QSize MyStyle::sizeFromContents(MyStyle::ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w) const
//{
// return QSize();
//}
//int MyStyle::styleHint(MyStyle::StyleHint stylehint, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *returnData) const
//{
// return 0;
//}
void MyStyle::polish(QWidget *widget)
{
QCommonStyle::polish(widget);
@ -40,8 +80,24 @@ void MyStyle::unpolish(QWidget *widget)
QCommonStyle::unpolish(widget);
}
void MyStyle::drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const
{
switch (pe) {
case PE_SwitchButtonGroove: {
if (const QStyleOptionButton* swtchBtn = qstyleoption_cast<const QStyleOptionButton*>(opt)) {
p->setBrush(Qt::red);
p->drawRoundedRect(swtchBtn->rect, 8, 8);
}
}
break;
case PE_SwitchButtonHandle: {
}
break;
default:
break;
}
QCommonStyle::drawPrimitive(pe, opt, p, w);
}
@ -70,6 +126,19 @@ void MyStyle::drawControl(QStyle::ControlElement element, const QStyleOption *op
p->fillRect(opt->rect, QColor("#de6161"));
return;
}
case CE_SwitchButton: {
if (const QStyleOptionButton *switchBtn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
QStyleOptionButton option = *switchBtn;
option.palette = switchBtn->palette;
option.rect = subElementRect(SE_SwitchButtonGroove, opt, w);
drawPrimitive(PE_SwitchButtonGroove, &option, p, w);
option.rect = subElementRect(SE_SwitchButtonHandle, opt, w);
drawPrimitive(PE_SwitchButtonHandle, &option, p, w);
}
break;
}
default:
break;
}
@ -79,6 +148,37 @@ void MyStyle::drawControl(QStyle::ControlElement element, const QStyleOption *op
QRect MyStyle::subElementRect(QStyle::SubElement subElement, const QStyleOption *option, const QWidget *widget) const
{
switch (subElement) {
case SE_SwitchButtonGroove: {
if (const QStyleOptionButton* switchBtn = qstyleoption_cast<const QStyleOptionButton*>(option))
return switchBtn->rect;
}
break;
case SE_SwitchButtonHandle: {
if (const QStyleOptionButton* switchBtn = qstyleoption_cast<const QStyleOptionButton*>(option)) {
int handleWidth = pixelMetric(PM_SwitchButtonHandleWidth, option, widget);
//pixelMetric(PM_SwitchButtonHandleWidth, option, widget);
QRect rectHandle(0, 0, 0, 0);
rectHandle.setHeight(switchBtn->rect.height());
if (switchBtn->rect.width() / 2.0 <= handleWidth)
rectHandle.setWidth(switchBtn->rect.width() / 2.0);
else
rectHandle.setWidth(handleWidth);
if (switchBtn->state & QStyle::State_On)
rectHandle.moveRight(switchBtn->rect.right());
else
rectHandle.moveLeft(switchBtn->rect.left());
return rectHandle;
}
}
break;
default:
break;
}
return QCommonStyle::subElementRect(subElement, option, widget);
}
@ -94,6 +194,15 @@ QRect MyStyle::subControlRect(QStyle::ComplexControl cc, const QStyleOptionCompl
int MyStyle::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
{
switch (metric) {
case PM_SwitchButtonHandleWidth:
return 30;
case PM_SwithcButtonHandleHeight:
return 12;
default:
break;
}
return QCommonStyle::pixelMetric(metric, option, widget);
}

View File

@ -26,21 +26,73 @@
class MyStyle : public QCommonStyle
{
// Q_OBJECT
public:
//这里新增加的枚举,是属于 MyStyle:: , 而非 QStyle:: 范围
enum ControlElement {
CE_SwitchButton = QStyle::CE_CustomBase + 1, //switchButton 控件
CE_CustomBase = QStyle::CE_CustomBase + 0xf00000
};
enum SubElement {
SE_SwitchButtonGroove = QStyle::SE_CustomBase + 1, //滑槽矩形大小
SE_SwitchButtonHandle, //滑块矩形大小
SE_CustomBase = QStyle::SE_CustomBase + 0xf00000
};
enum PixelMetric {
PM_SwitchButtonHandleWidth = QStyle::PM_CustomBase + 1, //switch Handle width
PM_SwithcButtonHandleHeight, //switch Handle height
PM_CustomBase = QStyle::PM_CustomBase + 0xf00000
};
enum PrimitiveElement {
PE_SwitchButtonGroove = QStyle::PE_CustomBase + 1, //滑槽
PE_SwitchButtonHandle, //滑块
PE_CustomBase = QStyle::PE_CustomBase + 0xf00000
};
public:
MyStyle();
// QStyle interface
public:
//新增加的枚举属 MyStyle:: , 之能够在此内敛函数里面调用
inline void drawPrimitive(MyStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w = nullptr) const;
inline void drawControl(MyStyle::ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w) const;
inline QRect subElementRect(MyStyle::SubElement subElement, const QStyleOption *option, const QWidget *widget) const;
// inline void drawComplexControl(MyStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const;
// inline QRect subControlRect(MyStyle::ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const;
inline int pixelMetric(MyStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const;
// inline QSize sizeFromContents(MyStyle::ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w) const;
// inline int styleHint(MyStyle::StyleHint stylehint, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *returnData) const;
//这里的快捷方式创建的枚举,都是不带QStyle:: ; 但是快捷方式的定义是带是QStyle:: , 此处声明的地方必须加上 QStyle:: /*后面改写更复杂的得写上MyStyle:: 因添加自定义的枚举*/
//这里 override 的虚函数,只能够调用旧有的 QStyle:: 的函数
virtual void drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const override;
virtual void drawControl(QStyle::ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w) const override;
virtual QRect subElementRect(QStyle::SubElement subElement, const QStyleOption *option, const QWidget *widget) const override;
virtual void drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const override;
virtual QRect subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const override;
virtual int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const override;
virtual QSize sizeFromContents(QStyle::ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w) const override;
virtual int styleHint(QStyle::StyleHint stylehint, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *returnData) const override;
virtual void polish(QWidget *widget) override;
virtual void unpolish(QWidget *widget) override;
virtual void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const override;
virtual void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w) const override;
virtual QRect subElementRect(SubElement subElement, const QStyleOption *option, const QWidget *widget) const override;
virtual void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const override;
virtual QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const override;
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const override;
virtual QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w) const override;
virtual int styleHint(StyleHint stylehint, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *returnData) const override;
//重实现,使得父类的多个同名 函数 (不同参数) 任然可以在本类里面使用
using QCommonStyle::polish;
using QCommonStyle::unpolish;
using QCommonStyle::drawPrimitive;
using QCommonStyle::drawControl;
using QCommonStyle::subElementRect;
using QCommonStyle::drawComplexControl;
using QCommonStyle::subControlRect;
using QCommonStyle::pixelMetric;
using QCommonStyle::sizeFromContents;
using QCommonStyle::styleHint;
};

View File

@ -0,0 +1,69 @@
#include "myswitchbutton.h"
#include "myswitchbutton_p.h"
#include "mystyle.h"
#include <QStylePainter>
#include <QStyleOptionButton>
MySwitchButton::MySwitchButton(QWidget *parent)
: QAbstractButton(parent)
{
Q_D(MySwitchButton);
d->init();
}
MySwitchButton::~MySwitchButton()
{
}
QSize MySwitchButton::sizeHint() const
{
return QSize(100, 40);
}
void MySwitchButton::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QStyleOptionButton opt;
initStyleOption(&opt);
QStylePainter pa(this);
// pa.drawControl(MyStyle::CE_SwitchButton, opt);
}
void MySwitchButton::initStyleOption(QStyleOptionButton *opt) const
{
if (!opt)
return;
opt->init(this);
opt->initFrom(this);
if (isChecked())
opt->state |= QStyle::State_On;
else
opt->state |= QStyle::State_Off;
}
MySwitchButtonPrivate::MySwitchButtonPrivate()
{
}
MySwitchButtonPrivate::~MySwitchButtonPrivate()
{
}
void MySwitchButtonPrivate::init()
{
Q_Q(MySwitchButton);
checked = false;
animationStart = 0;
animationEnd = 1;
q->setObjectName("MySwitchButton");
// q->connect(q, &MySwitchButton::toggled, q, &MySwitchButton::checkedChanged);
}

View File

@ -0,0 +1,29 @@
#ifndef MYSWITCHBUTTON_H
#define MYSWITCHBUTTON_H
#include <QAbstractButton>
class QStyleOptionButton;
class MySwitchButtonPrivate;
class MySwitchButton : public QAbstractButton//bianxinagjicengle QObject
{
Q_OBJECT
public:
explicit MySwitchButton(QWidget* parent = nullptr);
~MySwitchButton();
// QWidget interface
public:
virtual QSize sizeHint() const override;
protected:
virtual void paintEvent(QPaintEvent *event) override;
private:
void initStyleOption(QStyleOptionButton *opt) const;
private:
Q_DECLARE_PRIVATE(MySwitchButton)
};
#endif // MYSWITCHBUTTON_H

View File

@ -0,0 +1,29 @@
#ifndef MYSWITCHBUTTON_P_H
#define MYSWITCHBUTTON_P_H
#include <private/qobject_p.h>
/*!
* \~chinese \class MySwitchButtonPrivate
* \~chinese \brief MySwitchButton 便/, _Private
* , QObjectPrivate , 使 Q_Q Q_D q_fun()
* \~chinese \sa Qt QPushButtonPrivate QPushButton
*/
class MySwitchButtonPrivate : public QObjectPrivate
{
public:
explicit MySwitchButtonPrivate();
~MySwitchButtonPrivate();
void init();
public:
bool checked;
double animationStart;
double animationEnd;
public:
Q_DECLARE_PUBLIC(MySwitchButton) //要加上宏
};
#endif // MYSWITCHBUTTON_P_H