1. QPaintEvent绘图事件
• QPaintEvent是Qt框架中一个重要的事件类,专门用于处理绘图事件。当Qt视图组件需要重绘自己的一部分时,就会产生QPaintEvent事件。这通常发生在以下几种情况:
**1. 窗口第一次显示时:**当窗口或控件第一次出现在屏幕上时,系统会生成一个QPaintEvent事件,通知窗口进行自身的绘制。
2. **窗口大小改变时:**当用户改变窗口的大小时,窗口的内容通常需要重新绘制以适应新的尺寸。
3. **窗口部分被遮挡后又重新显示时:**如果窗口被其他窗口遮挡,然后又重新露出来,被遮挡的部分通常需要重新绘制。
4. **手动请求重绘:**通过调用QWidget的update()或repaint() 方法,可以手动触发重绘事件。
2. QPainter画家
2.1 概述
• QPainter是QT库中用于在控件上进行绘画的类。它提供了各种绘制功能,比如画线、画图形、画文本等。
以下是一些基本的用法示例:
- 初始化****QPainter:
cpp
QPainter painter(this); //在当前控件上进行绘画
**2. 设置画笔和画刷:**您可以设置画笔(用于描边)和画刷(用于填充)的颜色、样式等。
cpp
painter.setPen(Qt::blue); // 设置画笔颜色为蓝色
painter.setBrush(Qt::yellow); // 设置画刷颜色为黄色
- **绘制图形:**使用QPainter的方法来绘制线条、矩形、圆形、文本等。
cpp
painter.drawLine(10, 10, 100, 100); // 画线
painter.drawRect(10, 10, 100, 100); // 画矩形
painter.drawText(10, 10, "Hello, Qt!"); // 画文本
**4. 结束绘制:**完成绘制后,QPainter对象会在其析构函数中自动结束绘制。
• 请注意, QPainter的使用依赖于Qt的事件循环,因此通常在QWidget的paintEvent或者类似的事
件处理函数中使用它。如果您在 Qt 应用程序中使用QPainter,请确保您遵循Qt的事件驱动机制。
5. 示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
//painter.setPen(Qt::blue);
QPen pen(Qt::red,7);
painter.setPen(pen);
painter.setFont(QFont("Arial", 30));
painter.setRenderHint(QPainter::Antialiasing,true);
//画文字
// painter.drawText(rect(), Qt::AlignCenter, "Qt的案例");
// painter.drawText(100,200,100,100,Qt::AlignCenter,"QT");
// painter.drawText(30,50,"BZY");
// qDebug() << rect().width() << "," << rect().height();
//画线
//painter.drawLine(10,200,300,20);
// painter.drawLine(QLine(10,200,300,20));
painter.drawLine(QPoint(10,200),QPoint(300,20));
//画矩形
QRect rectangle(20,100,220,200);
//painter.drawRect(rectangle);
// painter.drawRect(20,100,220,200);
//画椭圆(画圆形)
// painter.drawEllipse(rectangle);
// painter.drawEllipse(rect().center(),100,200);
// painter.drawEllipse(QPoint(80,500),80,80);
//画弧
//painter.drawArc(rectangle,30 * 16,120 * 16);
//painter.drawArc(rectangle,-30 * 16,120 * 16);
//painter.drawArc(rectangle,30 * 16,-120 * 16);
//painter.drawArc(rectangle,-30 * 16,-120 * 16);
painter.drawRect(30,100,100,180);
painter.drawArc(30,100,100,180,45 * 16,120 * 16);
//画扇形
painter.drawPie(30,100,100,180,45 * 16,90 * 16);
}
2.2 渐变色
2.2.1 线性渐变
• QLinearGradient是Qt框架中用于创建线性渐变的类。线性渐变是一种从一个颜色平滑过渡到另一个颜色的效果,其变化沿着两个点之间的直线进行。这种渐变在图形用户界面设计中非常常见,用于添加深度、立体感或动态效果。
• 基本用法:
• 要使用 QLinearGradient ,你需要执行以下几个基本步骤:
- 创建QLinearGradient **对象:**指定渐变的起点和终点坐标。
- **设置颜色停靠点:**在渐变线上定义颜色和相应的位置。
- 使用渐变创建QBrush:用QLinearGradient对象来创建一个QBrush,然后用它在QPainter中进行绘制。
• 示例代码
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
void Widget::paintEvent(QPaintEvent *event){
QPainter painter(this);
//创建线性渐变
//QLinearGradient linearGradient(0,height() / 2,width(),height() / 2);
QLinearGradient linearGradient(0,0,width(),height());
//设置停靠色
// linearGradient.setColorAt(0.1,Qt::black);
// linearGradient.setColorAt(0.3,Qt::black);
// linearGradient.setColorAt(0.5,Qt::black);
//换一种方式设置颜色
linearGradient.setColorAt(0.1,QColor(0,0,0,255));
linearGradient.setColorAt(0.3,QColor(0,0,0,180));
linearGradient.setColorAt(0.5,QColor(0,0,0,100));
linearGradient.setColorAt(1,Qt::white);
//设置画刷
QBrush brush(linearGradient);
painter.setBrush(brush);
//在矩形画图
painter.drawRect(rect());
}
Widget::~Widget()
{
delete ui;
}
• 注意事项:
• QLinearGradient的颜色变化是沿着两个指定点之间的直线进行的。通过改变这些点的位置,你
可以控制渐变的方向和长度。
• setColorAt() 方法的第一个参数是一个介于 0.0 和 1.0 之间的浮点数,表示颜色在渐变线上的位
置。0.0 通常对应于起点,1.0 对应于终点。
• 你可以设置多个颜色停靠点来创建更复杂的渐变效果。例如,你可以在 0.0 处设置一种颜色,在 0.5处设置另一种颜色,在 1.0 处再设置一种颜色。
• 使用 QLinearGradient创建的QBrush可以用于填充任何形状,包括矩形、椭圆、多边形等。
• 为了获取更好的视觉效果,可以启用 QPainter 的抗锯齿选项( QPainter::Antialiasing )。
• 请注意,当窗口小部件的大小发生变化时,渐变的效果可能也会随之改变,除非你相应地调整渐变的起点和终点坐标或使用其他方法来适应大小变化。
2.2.2 径向渐变
• QRadialGradient是Qt框架中用于创建径向渐变的类。径向渐变是一种从中心点向外部辐射的颜色渐变,通常在中心点有一种颜色,而向外围渐渐变化为另一种颜色。这种渐变非常适合用于模拟光源、阴影或创建圆形的立体感。
• 基本用法
• 要使用QRadialGradient,你需要执行以下几个基本步骤:
- 创建QRadialGradient**对象:**指定渐变的中心点,半径以及焦点(可选)。
- **设置颜色停靠点:**在径向渐变中定义颜色和对应的位置。
- 使用渐变创建QBrush:利用QRadialGradient对象创建一个QBrush ,然后用
它在QPainter中进行绘制。
• 注意事项:
• setColorAt()方法的第一个参数是一个介于 0.0 和1.0 之间的浮点数,表示颜色在径向渐变中的
位置。0.0 通常对应于中心点,1.0 对应于边缘。
• 通过添加多个颜色停靠点,你可以创建更复杂的径向渐变效果。
• setFocalPoint() 方法允许你设置焦点位置,这是渐变颜色开始变化的点,可以与中心点不同。
• 使用QRadialGradient创建的QBrush可以用于填充任何形状,如矩形、椭圆、多边形等。
• 为了获得更好的视觉效果,可以启用 QPainter 的抗锯齿选项( QPainter::Antialiasing )。
• 当绘制较大区域时,可以通过调整渐变的半径和中心点来控制渐变效果的扩展。
• QRadialGradient 非常适用于创建像按钮、指示灯或其他需要有深度感和立体感的界面元素。
• 示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
void Widget::paintEvent(QPaintEvent *event){
QPainter painter(this);
//QRadialGradient radialGradient(0,0,800);//创建QRadialGradient对象
QRadialGradient radialGradient(400,400,200);
// 设置颜色停靠点
radialGradient.setColorAt(0.1,Qt::white);
radialGradient.setColorAt(1,Qt::black);
//使用渐变创建QBrush
QBrush brush(radialGradient);
painter.setBrush(brush);
painter.drawRect(200,300,400,200);
}
Widget::~Widget()
{
delete ui;
}
2.2.3 圆锥形渐变
• QConicalGradient 是 Qt 框架中用于创建圆锥形渐变的类。圆锥渐变是一种渐变效果,其中颜色沿着圆锥的轮廓变化,类似于旋转颜色轮 。这种渐变以其中心点为基点,颜色沿圆周分布,可以创建出富有动感的视觉效果。
• 基本用法:
• 要使用QConicalGradient ,你通常需要做以下几个步骤:
- 创建QConicalGradient**对象:**指定渐变的中心点和起始角度。
- **设置颜色停靠点:**为渐变添加不同的颜色和对应的位置(角度)。
- 使用渐变创建QBrush:使用这个渐变对象来创建一个QBrush,然后应用到QPainter中进行绘图。
• 注意事项:
• QConicalGradient的颜色是沿着圆周分布的,其中0.0和1.0在圆周上是相同的位置。
• 你可以通过添加多个颜色停靠点来创建更复杂的渐变效果。
• QConicalGradient:
• 在使用时,角度是按照顺时针方向测量的,起始点(0度)通常在三点钟方向。
• 为了达到最佳的渲染效果,可以启用QPainter的抗锯齿渲染提示(QPainter::Antialiasing)。
• QConicalGradient非常适合用于创建旋转或动态效果的图形,例如加载指示器、进度条或任何需要圆周颜色变化的场景。
• 示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
void Widget::paintEvent(QPaintEvent *event){
//创建一个 QConicalGradient 对象
QConicalGradient conicalGradient(400, 400, 0); //中心点(400, 400),起始角度 0
//添加颜色停靠点
conicalGradient.setColorAt(0.0, Qt::red);
conicalGradient.setColorAt(0.5, Qt::blue);
conicalGradient.setColorAt(1.0, Qt::red);
// 使用这个渐变创建 QBrush
QBrush brush(conicalGradient);
// 使用 QBrush 进行绘图
QPainter painter(this);
//QRadialGradient radialGradient(0,0,800);//创建QRadialGradient对象
// QRadialGradient radialGradient(400,400,200);
// 设置颜色停靠点
// radialGradient.setColorAt(0.1,Qt::white);
// radialGradient.setColorAt(1,Qt::black);
//使用渐变创建QBrush
// QBrush brush(radialGradient);
painter.setBrush(brush);
painter.drawRect(200,300,400,200);
}
Widget::~Widget()
{
delete ui;
}
2.3 坐标平移
• 在QT框架中,painter.translate(rect().center())这行代码的作用是移动QPainter的坐标系统原点到当前绘制区域(即由rect()返回的矩形)的中心。
• 解释一下各个部分:
- painter:这是一个QPainter对象实例,用于在Qt窗口或者图像上进行绘制。
- translate():这是QPainter类中的一个方法,用于改变坐标系统的原点。它接受一个 QPoint 或QPointF作为参数,这个点指定了新的原点位置。
- rect():这通常是指一个控件(如QWidget)的矩形区域,返回一个QRect或QRectF 对象,表示该控件的大小和位置。
- rect().center():这个方法返回当前矩形(即控件的区域)的中心点,是一个 QPoint或QPointF 对象。
• 总之, painter.translate(rect().center()) 这行代码将QPainter的绘图原点移动到控件的中心。这在进行中心对称绘制或者需要以控件中心为基准进行绘图时特别有用。
3. 画雷达
• 示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
timer = new QTimer(this);
connect(timer,&QTimer::timeout,[=](){
//不断变化扇形的启动位置
startAngle += 30;
if(startAngle >= 360){
startAngle = 0;
}
update();
});
timer->setInterval(100);
timer->start();
}
void Widget::paintEvent(QPaintEvent *event){
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);//抗锯齿
//设置背景色为黑色
QBrush brush(Qt::black);
painter.setBrush(brush);
painter.drawRect(rect());
//平移坐标轴到窗口正中间
painter.translate(rect().center());
//最小圆的半径
int rEve = height() / 2 / 7;//800 600 600/7
int dataTmp = rEve * 7;//用height()/2导致突出,上面那行代码除不尽
//设置画笔,绿色,像素4
QPen pen(Qt::green,4);
painter.setPen(pen);
painter.setBrush(Qt::NoBrush);//不要画刷,否则只能看到最外面的圈
for(int i = 1;i <= 7;i++){
painter.drawEllipse(QPoint(0,0),rEve * i,rEve * i);//依次画出7个圆形
}
painter.drawLine(-rEve * 7,0,rEve * 7,0);
painter.drawLine(0,-rEve * 7,0,rEve * 7);
//设置锥形渐变
QConicalGradient conicalGradient(0,0,-startAngle);
conicalGradient.setColorAt(0,QColor(0,255,0,200));
conicalGradient.setColorAt(0.1,QColor(0,255,0,100));
conicalGradient.setColorAt(0.2,QColor(0,255,0,0));
conicalGradient.setColorAt(1,QColor(0,255,0,0));
//直接用渐变色指定画刷
painter.setBrush(conicalGradient);
painter.setPen(Qt::NoPen);
painter.drawPie(QRect(-dataTmp,-dataTmp,dataTmp * 2,dataTmp * 2),-startAngle * 16,70 * 16);
}
Widget::~Widget()
{
delete ui;
}
• 如图:

4. 仪表盘
• 示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
timer = new QTimer(this);
currentValue = 0;
mark = 0;
connect(timer,&QTimer::timeout,[=]{
if(mark == 0){
currentValue++;
if(currentValue >= 51){
mark = 1;
}
}else {
currentValue--;
if(currentValue == 0){
mark = 0;
}
}
update();
});
timer->start(50);
}
void Widget::paintEvent(QPaintEvent *event){
QPainter painter(this);
//抗锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//底色弄成黑色
painter.setBrush(QBrush(Qt::black));
painter.drawRect(rect());
//坐标轴平移到中心
painter.translate(rect().center());
//设置径向渐变
QRadialGradient radialGradient(0,0,height() / 2);
//设置颜色停靠点
radialGradient.setColorAt(0.0,QColor(255,0,0,50));//中心颜色
radialGradient.setColorAt(1.0,QColor(255,0,0,250));//外围颜色
//使用这个渐变
QBrush brush(radialGradient);
painter.setBrush(brush);
//画大圆
painter.drawEllipse(QPoint(0,0),height() / 2,height() / 2);
painter.setBrush(Qt::NoBrush);
//画小圆
painter.setPen(QPen(Qt::white,4));
painter.drawEllipse(QPoint(0,0),60,60);
//当前值
painter.setFont(QFont("华文宋体",25));
painter.drawText(QRect(-60,-60,120,120),
Qt::AlignCenter,QString::number(currentValue));
//画刻度
//1. 算出一个刻度要需要旋转的角度
double angle = 270 * 1.0 / 50;//270+1.0的作用是扩大变量类型,把int型阔成double,保留小数
//2. 设置第一个刻度需要旋转的位置
painter.save();//保存一下原点,x在3点钟方向
painter.rotate(135);
painter.setFont(QFont("华文宋体",16));
for(int i = 0;i <= 50;i++){
if(i % 10 == 0){
//画字
if(135 + angle * i < 270){
painter.rotate(180);
painter.drawText(-(height() / 2 - 20 - 10),8,QString::number(i));
painter.rotate(-180);
}else {
painter.drawText(height() / 2 - 20 - 30,8,QString::number(i));
}
painter.drawLine(height() / 2 - 20,0,height() / 2 - 3,0);//画长刻度线
}else {
painter.drawLine(height() / 2 - 8,0,height() / 2 - 3,0);
}
//画完之后就旋转
painter.rotate(angle);
}
//画指针,线
//坐标轴先回到原点
painter.restore();
painter.save();
painter.rotate(135 + angle * currentValue);//画指示在currentValue刻度的指针
painter.drawLine(60,0,height() / 2 - 20 - 10 - 28,0);
//画扇形
painter.restore();
QRect rentangle(-height() / 2 + 58,-height() / 2 + 58,height() - 116,height() - 116);
painter.setPen(Qt::NoPen);
// painter.setBrush(QColor(255,0,0,150));
painter.setBrush(QColor(235,152,50,150));
painter.drawPie(rentangle,(360 - 135) * 16,-angle * currentValue * 16);//angle前面取负数,为了让它顺时针方向画
}
Widget::~Widget()
{
delete ui;
}
• 如图:

5. 汽车仪表盘
• 如图:

• 示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QtMath>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
startAngle = 150;
setFixedSize(800,600);
startSpeed();
}
void Widget::paintEvent(QPaintEvent *event){
QPainter painter(this);
//初始化画布
initCanvas(painter);
//画小圆
drawMiddleCircle(painter,60);
//画刻度
drawScale(painter,height() / 2);
//画刻度文字
drawScaleText(painter,height() / 2);
//画指针,线
drawPointLine(painter,height() / 2 -58);
//画扇形
drawSpeedPie(painter,height() / 2 + 25);
//画渐变内圈圆
drawEllipseInnerShine(painter,120);
//画黑色内圆
drawEllipseInnerBlack(painter,80);
//画当前速度
drawCurrentSpeed(painter);
//画外环发光圈
drawEllipseOutterShine(painter,height() / 2 + 25);
//画一个汽车LOGO
drawLogo(painter,height() / 2);
}
Widget::~Widget()
{
delete ui;
}
void Widget::initCanvas(QPainter &painter)
{
//抗锯齿
painter.setRenderHint(QPainter::Antialiasing,true);
//底色弄成黑色
painter.setBrush(QBrush(Qt::black));
painter.drawRect(rect());
//坐标轴平移到中心
//painter.translate(rect().center());
QPoint cent(rect().width() / 2,rect().height()*0.6);
painter.translate(cent);
}
void Widget::drawMiddleCircle(QPainter &painter, int radius)
{
//画小圆
painter.setPen(QPen(Qt::white,4));
painter.drawEllipse(QPoint(0,0),radius,radius);
}
void Widget::drawCurrentSpeed(QPainter &painter)
{
//当前值
painter.setPen(QPen(Qt::white));
QFont font1("Arial",30);
font1.setBold(true);
painter.setFont(font1);
painter.drawText(QRect(-60,-60,120,70),
Qt::AlignCenter,QString::number(currentValue * 4));
QFont font2("Arial",15);
font2.setBold(true);
painter.setFont(font2);
painter.drawText(QRect(-60,-60,120,150),
Qt::AlignCenter,"Km/h");
}
void Widget::drawScale(QPainter &painter, int radius)
{
//画刻度
//1. 算出一个刻度要需要旋转的角度
angle = 240 * 1.0 / 60;//270+1.0的作用是扩大变量类型,把int型阔成double,保留小数
//2. 设置第一个刻度需要旋转的位置
painter.save();//保存一下原点,x在3点钟方向
painter.setPen(QPen(Qt::white,5));
painter.rotate(startAngle);
// painter.setFont(QFont("华文宋体",20));
for(int i = 0;i <= 60;i++){
if(i >= 40){
painter.setPen(QPen(Qt::red,5));
}
if(i % 5 == 0){
painter.drawLine(radius - 20,0,radius - 3,0);//画长刻度线
}else {
painter.drawLine(radius - 8,0,radius - 3,0);
}
//画完之后就旋转
painter.rotate(angle);
}
painter.restore();
painter.setPen(QPen(Qt::white,5));
}
void Widget::drawScaleText(QPainter &painter, int radius)
{
//写刻度文字
//定义半径
QFont font("Arial",20);
font.setBold(true);
painter.setFont(font);
int r = radius - 58;
for(int i = 0;i <= 60;i++){
if(i % 5 == 0){
//保存坐标系
painter.save();
//算出平移点
int delX = qCos(qDegreesToRadians(210 - angle * i)) * r;
int delY = qSin(qDegreesToRadians(210 - angle * i)) * r;
//平移坐标系
painter.translate(QPoint(delX,-delY));
//旋转坐标系
painter.rotate(-120 + angle * i); //angle=4,30*4=120的时候,实参是0,120
//写上刻度文字
painter.drawText(-30,-30,60,30,Qt::AlignCenter,QString::number(i * 4));
//恢复坐标系
painter.restore();
}
}
}
void Widget::drawPointLine(QPainter &painter,int lenth)
{
//画指针,线
//坐标轴先回到原点
painter.save();
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::white);
static const QPointF points[4] = {
QPointF(0, 0),
QPointF(200.0,1.1),
QPointF(200.0,1.1),
QPointF(0,15.0),
};
painter.rotate(startAngle + angle * currentValue);//画指示在currentValue刻度的指针
//painter.drawLine(60,0,lenth,0);
painter.drawPolygon(points, 4);
painter.restore();
}
void Widget::drawSpeedPie(QPainter &painter, int radius)
{
QRect rentangle(-radius,-radius,radius * 2,radius * 2);
painter.setPen(Qt::NoPen);
// painter.setBrush(QColor(255,0,0,150));
painter.setBrush(QColor(255,0,0,100));
painter.drawPie(rentangle,(360 - startAngle) * 16,-angle * currentValue * 16);//angle前面取负数,为了让它顺时针方向画
}
void Widget::startSpeed()
{
timer = new QTimer(this);
currentValue = 0;
mark = 0;
connect(timer,&QTimer::timeout,[=]{
if(mark == 0){
currentValue++;
if(currentValue >= 60){
mark = 1;
}
}else {
currentValue--;
if(currentValue == 0){
mark = 0;
}
}
update();
});
timer->start(50);
}
void Widget::drawEllipseInnerBlack(QPainter &painter, int radius)
{
painter.setBrush(Qt::black);
painter.drawEllipse(QPoint(0,0),radius,radius);
}
void Widget::drawEllipseInnerShine(QPainter &painter, int radius)
{
QRadialGradient radialGradient(0,0,radius);
radialGradient.setColorAt(0.0,QColor(255,0,0,200));//中心颜色
radialGradient.setColorAt(1.0,QColor(0,0,0,100));//外围颜色
painter.setBrush(radialGradient);
painter.drawEllipse(QPoint(0,0),radius,radius);
}
void Widget::drawEllipseOutterShine(QPainter &painter, int radius)
{
QRect rentangle(-radius,-radius,radius * 2,radius * 2);
painter.setPen(Qt::NoPen);
// painter.setBrush(QColor(255,0,0,150));
QRadialGradient radialGradient(0,0,radius);
radialGradient.setColorAt(1.0,QColor(255,0,0,200));
radialGradient.setColorAt(0.97,QColor(255,0,0,120));
radialGradient.setColorAt(0.9,QColor(0,0,0,0));
radialGradient.setColorAt(0,QColor(0,0,0,0));
painter.setBrush(radialGradient);
painter.drawPie(rentangle,(360 - 150) * 16,-angle * 61 * 16);
}
void Widget::drawLogo(QPainter &painter, int radius)
{
QRect rectangle(-100,radius * 0.5,200,60);
painter.drawPixmap(rectangle,QPixmap(":/icon.png"));
}
6.自定义控件
• 示例代码
• 在mybutton.cpp
cpp
#include "mybutton.h"
#include <QPaintEvent>
#include <QPainter>
MyButton::MyButton(QWidget *parent) : QWidget(parent)
{
setFixedSize(60,20);
animation = new QPropertyAnimation(this);//添加动画效果
animation->setTargetObject(this);//设置当前目标
animation->setDuration(500);//持续时间
//设置弹射方式
animation->setEasingCurve(QEasingCurve::InOutElastic);
connect(animation,&QPropertyAnimation::valueChanged,this,[=](const QVariant &value){
posX = value.toInt();
update();
});
}
void MyButton::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
int radius = height() / 2;
painter.setPen(Qt::NoPen);
painter.setBrush(isOff ? offBgBrush : onBgBrush);
painter.drawRoundedRect(this->rect(),radius,radius);
painter.setBrush(isOff ? offRBrush : onRBrush);
QPoint center;
center.setX(posX);
center.setY(radius);
painter.drawEllipse(center,radius - radius / 10,radius - radius / 10);
painter.setPen(Qt::white);
painter.drawText(this->rect(),Qt::AlignCenter,isOff ? offText : onText);
}
void MyButton::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton){
//重新设置方向
isOff ? animation->setDirection(QAbstractAnimation::Forward) :
animation->setDirection(QAbstractAnimation::Backward);
animation->start();
isOff = !isOff;
//emit isClicked();
isOff ? emit isClickedWithParams(true) : emit isClickedWithParams(false);
}
}
void MyButton::resizeEvent(QResizeEvent *event)
{
animation->setStartValue(height() / 2);//设置开始位置
animation->setEndValue(width() - height() / 2);//设置结束位置
}
• 在mybutton.h
cpp
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include <QPaintEvent>
#include <QWidget>
#include <QPropertyAnimation>
class MyButton : public QWidget
{
Q_OBJECT
public:
explicit MyButton(QWidget *parent = nullptr);
signals:
void isClicked();
void isClickedWithParams(bool);
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
private:
bool isOff = true;
QBrush offBgBrush = Qt::black;
QBrush offRBrush = Qt::red;
QBrush onBgBrush = Qt::gray;
QBrush onRBrush = Qt::green;
QString offText = "OFF";
QString onText = "ON";
QPropertyAnimation *animation;
int posX = height() / 2;
};
#endif // MYBUTTON_H
• 在widget.cpp
cpp
#include "widget.h"
#include "ui_widget.h"
#include "mybutton.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
MyButton *btn = new MyButton(this);
btn->move(100,100);
btn->setFixedSize(300,80);
connect(btn,&MyButton::isClickedWithParams,[=](bool value){
qDebug() << "btn clicked" << value;
});
}
Widget::~Widget()
{
delete ui;
}