主页 > 创业  > 

QT实现简约美观的动画Checkbox

QT实现简约美观的动画Checkbox

*最终效果: * 一共三个文件: main.cpp , FancyCheckbox.h , FancyCheckbox.cpp main.cpp

#include <QApplication> #include "FancyCheckbox.h" #include <QGridLayout> int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget* w = new QWidget; w->setWindowTitle("cool checkbox"); w->resize(600,400); auto* layout = new QGridLayout; layout->addWidget(new CheckboxSimple,0,0); layout->addWidget(new CheckboxLollipop,0,1); layout->addWidget(new CheckboxNike,0,2); layout->addWidget(new CheckboxTransform,1,0); layout->addWidget(new CheckboxBanner,1,1); layout->addWidget(new CheckboxMark,1,2); w->setLayout(layout); w->show(); return a.exec(); }

FancyCheckbox.h

#ifndef CHECKBOXSIMPLE_H #define CHECKBOXSIMPLE_H #include <QPropertyAnimation> #include <QWidget> #include <QPaintEvent> #include <QMouseEvent> class CheckboxBase:public QWidget { Q_OBJECT Q_PROPERTY(qreal angle READ angle WRITE setAngle) public: CheckboxBase(QWidget* parent=nullptr); virtual ~CheckboxBase(); qreal angle()const; void setAngle(qreal an); protected: void enterEvent(QEvent* e); void leaveEvent(QEvent* e); QPropertyAnimation mAnim; qreal mAngle; bool mChecked; }; class CheckboxSimple : public CheckboxBase { Q_OBJECT public: explicit CheckboxSimple(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent* e); void mouseReleaseEvent(QMouseEvent* e); }; class CheckboxLollipop : public CheckboxBase { Q_OBJECT public: explicit CheckboxLollipop(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent* e); void mouseReleaseEvent(QMouseEvent* e); }; class CheckboxNike: public CheckboxBase{ Q_OBJECT public: explicit CheckboxNike(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent* e); void mouseReleaseEvent(QMouseEvent* e); }; class CheckboxTransform: public CheckboxBase{ Q_OBJECT public: explicit CheckboxTransform(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent* e); void mouseReleaseEvent(QMouseEvent* e); }; class CheckboxBanner: public CheckboxBase{ Q_OBJECT public: explicit CheckboxBanner(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent* e); void mouseReleaseEvent(QMouseEvent* e); }; class CheckboxMark: public CheckboxBase{ Q_OBJECT public: explicit CheckboxMark(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent* e); void mouseReleaseEvent(QMouseEvent* e); }; #endif // CHECKBOXSIMPLE_H

FancyCheckbox.cpp

#include "FancyCheckbox.h" #include <QPainter> #include <QPainterPath> #include <QPalette> #include <math.h> CheckboxBase::CheckboxBase(QWidget* parent): QWidget(parent),mAngle(0),mChecked(false) { mAnim.setPropertyName("angle"); mAnim.setTargetObject(this); mAnim.setDuration(2000); mAnim.setLoopCount(1); mAnim.setEasingCurve(QEasingCurve::Linear); setMouseTracking(true); } CheckboxBase::~CheckboxBase(){} qreal CheckboxBase::angle()const{ return mAngle;} void CheckboxBase::setAngle(qreal an){ mAngle = an; update(); } void CheckboxBase::enterEvent(QEvent* e){ setCursor(Qt::PointingHandCursor); } void CheckboxBase::leaveEvent(QEvent* e){ setCursor(Qt::ArrowCursor); } CheckboxSimple::CheckboxSimple(QWidget *parent) : CheckboxBase(parent) { setFixedSize(40,24); mAnim.setDuration(100); mAngle = 360; } void CheckboxSimple::paintEvent(QPaintEvent* e){ QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); int w = width(); int h = height(); painter.setPen(Qt::NoPen); if(mChecked){ painter.setBrush(QBrush(QColor("lightgreen"))); } else{ painter.setBrush(QBrush(QColor("lightgray"))); } painter.drawRoundedRect(rect(),h/2,h/2); painter.setBrush(QBrush(QColor("white"))); const int gap = 3; if(mChecked){ painter.translate((w-h)*mAngle/360+h/2,h/2); } else{ painter.translate(w-h/2-(w-h)*mAngle/360 , h/2); } painter.drawEllipse(QPoint(0,0),h/2-gap,h/2-gap); } void CheckboxSimple::mouseReleaseEvent(QMouseEvent* e){ if(mAnim.state() == QAbstractAnimation::Running) return; mChecked = !mChecked; mAnim.setStartValue(0); mAnim.setEndValue(360); mAnim.start(); } CheckboxLollipop::CheckboxLollipop(QWidget *parent) : CheckboxBase(parent) { setFixedSize(80,72); mAnim.setDuration(160); mAngle = 360; } void CheckboxLollipop::paintEvent(QPaintEvent* e){ QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); int w = width(); int h = height(); painter.setPen(Qt::NoPen); if(mChecked){ painter.setBrush(QBrush(QColor("cornflowerblue"))); } else{ painter.setBrush(QBrush(QColor("gray"))); } const auto r = 0.16 * h; const auto R = r + 0.25*w; painter.translate(0.25*w,0.4*h); if(mChecked){ if(mAngle <= 180){//move to rightside painter.drawRoundedRect(QRectF(0,0,0.5*w,0.2*h),0.1*h,0.1*h); painter.setBrush(QBrush(QColor("blueviolet"))); painter.translate((0.5*w - 2*r) * mAngle / 180 + r , 0.1*h); painter.drawEllipse(QPointF(0,0),r,r); } else{//boom! painter.translate(0.5*w - r,0.1*h); QRadialGradient rad(QPointF(0,0),R,QPointF(0,0)); QColor base("blueviolet"); base.setAlphaF(0.3); rad.setColorAt(0,base); rad.setColorAt(1,"transparent"); QColor eraseColor("white"); QWidget * pa = dynamic_cast<QWidget*>( parent() ); if(pa){ eraseColor = pa->palette().color(QPalette::Window); } painter.setBrush(rad); painter.drawEllipse(QPointF(0,0) , R , R);//画一个固定的渐变圈 painter.setBrush(QBrush(eraseColor)); auto out = r + (R -r) * ( mAngle - 180) / 180; painter.drawEllipse(QPointF(0,0), out,out);//画一个逐渐变大的圈把渐变圈覆盖掉 painter.resetTransform(); painter.translate(0.25*w,0.4*h); painter.setBrush(QBrush(QColor("cornflowerblue"))); painter.drawRoundedRect(QRectF(0,0,0.5*w,0.2*h),0.1*h,0.1*h); painter.setBrush(QBrush(QColor("blueviolet"))); painter.translate((0.5*w - r) , 0.1*h); painter.drawEllipse(QPointF(0,0),r,r); } } else{ painter.drawRoundedRect(QRectF(0,0,0.5*w,0.2*h),0.1*h,0.1*h); painter.setBrush(QBrush(QColor("white"))); painter.translate(0.5*w-r-((0.5*w-2*r) * mAngle/360),0.1*h); painter.drawEllipse(QPointF(0,0),r,r); } } void CheckboxLollipop::mouseReleaseEvent(QMouseEvent* e){ if(mAnim.state() == QAbstractAnimation::Running) return; mChecked = !mChecked; mAnim.setStartValue(0); mAnim.setEndValue(360); mAnim.start(); } CheckboxNike::CheckboxNike(QWidget *parent){ setFixedSize(32,32); mAngle = 360; } void CheckboxNike::paintEvent(QPaintEvent* e){ QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::NoPen); const int w = width(); const int h = height(); const int r = 8; if(mChecked){ painter.setBrush(QBrush(QColor("lightblue"))); painter.drawRoundedRect(rect() , r,r); QPainterPath cover; cover.addRect(QRectF(0,0,w*mAngle/360,h)); painter.setClipPath(cover); painter.setPen(Qt::white); painter.setFont(QFont("Microsoft YaHei",12)); painter.drawText(rect() , Qt::AlignCenter , "✔"); } else{ QColor baseBack("lightblue"); QColor baseFront("white"); baseBack.setAlphaF(1 - mAngle / 360); baseFront.setAlphaF(1 - mAngle / 360); painter.setBrush(baseBack); painter.drawRoundedRect(rect() , r,r); painter.setPen(baseFront); painter.setFont(QFont("Microsoft YaHei",12)); painter.drawText(rect() , Qt::AlignCenter , "✔"); QPen pen(QBrush("lightblue"),4); painter.setPen(pen); painter.setBrush(Qt::NoBrush); painter.drawRoundedRect(rect().adjusted(2,2,-2,-2) , r,r); } } void CheckboxNike::mouseReleaseEvent(QMouseEvent* e){ if(mAnim.state() == QAbstractAnimation::Running) return; mChecked = !mChecked; mAnim.setStartValue(0); mAnim.setEndValue(360); if(mChecked){ mAnim.setDuration(200); } else{ mAnim.setDuration(100); } mAnim.start(); } CheckboxTransform::CheckboxTransform(QWidget *parent){ setFixedSize(40,40); mAngle = 360; mAnim.setDuration(200); } void CheckboxTransform::paintEvent(QPaintEvent* e){ QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); QPen pen("black"); pen.setWidth(2); painter.setPen(pen); painter.setBrush(Qt::NoBrush); const double w = width(); const double h = height(); painter.translate(0.25*w,0.75*h); static constexpr int N = 20; if(mChecked){ double theta = -M_PI_4 * mAngle / 360;//在数学中,逆时针角度是正,在计算机中,y轴朝下,逆时针的角度为负数 double scale = 1 - (2-sqrt(2)/2)/2 / 360 * mAngle; for(int i = 0 ;i <= N;++i){ double x = 0; double y = -h/2/N * i; auto x2 = scale * ( cos(theta) * x - sin(theta) * y); auto y2 = scale * ( sin(theta) * x + cos(theta) * y); painter.drawPoint(QPointF(x2,y2)); } theta *= -1; for(int i = 0;i <= N;++i){ double x = w/2/N*i; double y = 0; auto x2 = scale * ( cos(theta) * x - sin(theta) * y); auto y2 = scale * ( sin(theta) * x + cos(theta) * y); painter.drawPoint(QPointF(x2,y2)); } painter.resetTransform(); painter.translate(0.75*w, 0.25*h); theta = atan(2.0/3) * mAngle / 360; scale = 1- (2-sqrt(3.25))/2 * mAngle / 360; double dx = -0.125*w * mAngle / 360; double dy = 0.25*h * mAngle / 360; for(int i = 0;i <= N;i++){ double x = 0; double y = 0.5*h/N * i; auto x2 = scale * ( cos(theta) * x - sin(theta) * y) + dx; auto y2 = scale * ( sin(theta) * x + cos(theta) * y) + dy; painter.drawPoint(QPointF(x2,y2)); } theta = -atan(1.5) * mAngle / 360; dx *= -1; dy = -0.125*h * mAngle / 360; for(int i = 0;i <= N;i++){ double x = -0.5*w * i / N; double y = 0; auto x2 = scale * ( cos(theta) * x - sin(theta) * y) + dx; auto y2 = scale * ( sin(theta) * x + cos(theta) * y) + dy; painter.drawPoint(QPointF(x2,y2)); } } else{ double theta = M_PI_4 * mAngle / 360; double scale = 1+ (2*sqrt(2) - 1) * mAngle / 360; for(int i = 0 ;i <= N;++i){ double x = -0.125*w/N * i; double y = -0.125*h/N * i; auto x2 = scale * ( cos(theta) * x - sin(theta) * y); auto y2 = scale * ( sin(theta) * x + cos(theta) * y); painter.drawPoint(QPointF(x2,y2)); } theta *= -1; for(int i = 0 ;i <= N;++i){ double x = 0.125*w/N * i; double y = 0.125*h/N * i; auto x2 = scale * ( cos(theta) * x - sin(theta) * y); auto y2 = scale * ( sin(theta) * x + cos(theta) * y); painter.drawPoint(QPointF(x2,y2)); } painter.resetTransform(); painter.translate(0.625*w, 0.5*h); theta = -atan(2.0/3) * mAngle / 360; scale = 1 + (2.0/sqrt(3.25) - 1) * mAngle / 360; double dx = 0.125*w * mAngle / 360; double dy = -0.25*h * mAngle / 360; for(int i = 0;i <= N;i++){ double x = -0.25*w * i/N; double y = 0.375*h * i / N; auto x2 = scale * ( cos(theta) * x - sin(theta) * y) + dx; auto y2 = scale * ( sin(theta) * x + cos(theta) * y) + dy; painter.drawPoint(QPointF(x2,y2)); } theta = atan(1.5) * mAngle / 360; dx= -0.375*w * mAngle / 360; dy = -0.25*h * mAngle / 360; for(int i = 0;i <= N;i++){ double x = 0.25*w * i / N; double y = -0.375*h * i / N; auto x2 = scale * ( cos(theta) * x - sin(theta) * y) + dx; auto y2 = scale * ( sin(theta) * x + cos(theta) * y) + dy; painter.drawPoint(QPointF(x2,y2)); } } } void CheckboxTransform::mouseReleaseEvent(QMouseEvent* e){ if(mAnim.state() == QAbstractAnimation::Running) return; mChecked = !mChecked; mAnim.setStartValue(0); mAnim.setEndValue(360); mAnim.start(); } CheckboxBanner::CheckboxBanner(QWidget *parent){ setFixedSize(75,30); mAnim.setDuration(300); mAngle = 360; } void CheckboxBanner::paintEvent(QPaintEvent* e){ QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::NoPen); const int w = width(); const int h = height(); if(mChecked){ painter.setBrush(QBrush("lightgreen")); } else{ painter.setBrush(QBrush("gray")); } QPainterPath pp; pp.moveTo(w/6,0); pp.lineTo(w,0); pp.lineTo(5.0/6*w,h); pp.lineTo(0,h); pp.lineTo(w/6,0); pp.closeSubpath(); painter.drawPath(pp); QPen pen("white"); pen.setWidth(4); painter.setPen(pen); painter.setFont(QFont("Microsoft YaHei",12)); if(mChecked){//move to left painter.translate(w*(1 - sin(M_PI_2 * mAngle/360)),0); painter.drawText(QRect(0,0,w,h),Qt::AlignCenter, "ON"); } else{ painter.translate(w*(sin(M_PI_2 * mAngle/360) -1),0); painter.drawText(QRect(0,0,w,h),Qt::AlignCenter, "OFF"); } } void CheckboxBanner::mouseReleaseEvent(QMouseEvent* e){ if(mAnim.state() == QAbstractAnimation::Running) return; mChecked = !mChecked; mAnim.setStartValue(0); mAnim.setEndValue(360); mAnim.start(); } CheckboxMark::CheckboxMark(QWidget *parent){ setFixedSize(40,40); mAnim.setDuration(300); mAngle = 360; } void CheckboxMark::paintEvent(QPaintEvent* e){ QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.setBrush(Qt::NoBrush); const int w = width(); const int h = height(); QPen pen; pen.setWidth(2); if(mChecked){ pen.setColor("lightgreen"); } else{ pen.setColor("gray"); } painter.setPen(pen); painter.translate(0,0.2*h); painter.drawRoundedRect(QRectF(0,0,0.8*w,0.8*h).adjusted(2,2,-2,-2),4,4); painter.resetTransform(); painter.translate(0.125*w,0.5*h); if(mChecked){ QPen pen("lightgreen"); pen.setWidth(6); pen.setCapStyle(Qt::RoundCap); pen.setJoinStyle(Qt::RoundJoin); painter.setPen(pen); if(mAngle <= 120){ int dw = 0.25*w * mAngle / 120; int dh = 0.25*h * mAngle / 120; painter.drawLine(0,0,dw,dh); } else{ painter.drawLine(0,0,0.25*w,0.25*h); auto rat = (mAngle - 120) / 240.0; painter.resetTransform(); painter.translate(0.375*w,0.75*h); int dw = 0.5*w * rat; int dh = 0.5*h * rat; painter.drawLine(0,0,dw,-dh); } } else{ } } void CheckboxMark::mouseReleaseEvent(QMouseEvent* e){ if(mAnim.state() == QAbstractAnimation::Running) return; mChecked = !mChecked; mAnim.setStartValue(0); mAnim.setEndValue(360); mAnim.start(); }
标签:

QT实现简约美观的动画Checkbox由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“QT实现简约美观的动画Checkbox