使用qt的QPainter可以绘制出任何你想要的图形,同时也须要一定的功底;下面介绍动态正弦曲线(水波效果)的画法。

为了更好理解,分4部分去理解如何绘制。先介绍画一个画三角形,再介绍画二个画三角形,然后画静态正弦曲线(水波),最后,画动态正弦曲线(水波效果)。主要用到QPainter与QPainterPath类。

一、下面介绍一个画三角形

文件包含如图零所示

QSplineSeries QSplineSeries绘制正弦波_QT 

                                                                                        图零:包含文件

triangle.pro 

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = triangle
TEMPLATE = app


SOURCES += \
    main.cpp \
    triangle.cpp

HEADERS  += \
    triangle.h

triangle.h

#ifndef TRIANGLE_H
#define TRIANGLE_H

#include <QWidget>
#include <QPainter>
#include <QtMath>
#include <QDebug>

class Triangle : public QWidget
{
    Q_OBJECT
public:
    explicit Triangle (QWidget *parent = 0);

protected:
    void paintEvent(QPaintEvent *event);
private:

};

#endif // TRIANGLE_H

main.cpp

#include "triangle.h"
#include <QApplication>


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    Triangle myTriangle;
    myTriangle.show();

    return a.exec();
}

triangle.cpp

#include "triangle.h"
Triangle::Triangle(QWidget *parent) : QWidget(parent)
{
}

void Triangle::paintEvent(QPaintEvent *event)
{
   Q_UNUSED(event);
   QPainter painter(this);  //QWidget为绘图设备,创建一个画刷对象,主要用到设置颜色和填充模式,brush,setBrush
   int width=this->width();  //获取QWidget 窗口的宽度
   int height=this->height();//获取QWidget 窗口的高度
   QPainterPath drawtriangle;  //单独画三角形

   drawtriangle.moveTo(0, height);//左下角,第一点坐标为(0,height);
   drawtriangle.lineTo(width/2, width/2);//第二点坐标为(width/2,width/2)
   drawtriangle.lineTo(width, height);//右下角,第三坐标(width, height),移动到右下角结束点,整体形成一个闭合路径
   painter.setBrush(Qt::green);   //填充绿色
   painter.drawPath(drawtriangle);  //绘制出图形
}

效果如图一所示 

QSplineSeries QSplineSeries绘制正弦波_绘制图形_02

                                                               图一:triangle

二、画两个三角形

修改上述的triangle.cpp文件 为如下代码

#include "triangle.h"
Triangle::Triangle(QWidget *parent) : QWidget(parent)
{
}

void Triangle::paintEvent(QPaintEvent *event)
{
   Q_UNUSED(event);
   QPainter painter(this);  //QWidget为绘图设备,创建一个画刷对象,主要用到设置颜色和填充模式,brush,setBrush
   int width=this->width();  //获取QWidget 窗口的宽度
   int height=this->height();//获取QWidget 窗口的高度
   QPainterPath drawtriangle;  //单独画三角形

   drawtriangle.moveTo(0, height);//左下角,第一点坐标为(0,height);
   drawtriangle.lineTo(width/4, height/2);//第二点坐标为(width/4,height/2)
   drawtriangle.lineTo(width/2, height);//第三点坐标为(width/2,height)
   drawtriangle.lineTo(width*3/4,height/2);//第四点坐标为(width*3/4,height/2)
   drawtriangle.lineTo(width, height);//右下角,第五坐标(width, height),移动到右下角结束点,整体形成一个闭合路径
   painter.setBrush(Qt::green);   //填充绿色
   painter.drawPath(drawtriangle);  //绘制出图形
}

效果如图二所示 

QSplineSeries QSplineSeries绘制正弦波_绘制图形_03

                                                                  图二:两个三角形

 

三、画静态正弦曲线(水波)

修改上述的triangle.cpp文件 为如下代码

#include "triangle.h"
Triangle::Triangle(QWidget *parent) : QWidget(parent)
{
}


void Triangle::paintEvent(QPaintEvent *event)
{
     Q_UNUSED(event);
     QPainter painter(this);  //QWidget为绘图设备,创建一个画刷对象,主要用到设置颜色和填充模式,brush,setBrush
     int width=this->width();  //获取QWidget 窗口的宽度
     int height=this->height(); //获取QWidget 窗口的高度
     //正弦曲线公式 y = A * sin(ωx + φ) + k
     double w = M_PI/100;  //w为角速度 ,可以理解为波浪的密度,越大密度越大
     double A = 20;    //  A表示振幅,可以理解为水波的高度,越大高度越高
     double k = 20;    //  k表示y轴偏移


     QPainterPath wave; //波浪区域
     wave.moveTo(0, height);//第一点坐标为(0,height);
     double m_offset = 6; //初相位,初值该值不一样,获得waveY也不一样,可试验该值为不同值的时候,曲线的起始点的区别        //
     for(int x = 0; x <= width; x+=1)  //x从0~w的值而改变,从而得到正弦曲线
     {
          double waveY = (double)(A * sin(w * x + m_offset)) + k;// waveY随着x的值改变而改变,从而得到正弦曲线
          wave.lineTo(x, waveY);   //从上一个绘制点画一条线到(x,waveY);
     }
     wave.lineTo(width, height); //右下角,坐标(width, height),移动到右下角结束点,整体形成一个闭合路径
     painter.setBrush(Qt::green); //填充绿色
     painter.drawPath(wave);      //绘制出图形
}

效果如图三所示  

                       

QSplineSeries QSplineSeries绘制正弦波_绘制图形_04

                                                                                   图三:正弦曲线(水波)  

 

四、画动态正弦曲线(水波效果)

相对于静态态正弦曲线,动态正弦曲线产生水波效果主要依靠,初相位的改变与定时器的刷新。基于上面的代码只需修改“double m_offset = 6;”为“double m_offset += 6”; //初相位改变,增加timerEvent// 定时器事件,定时器的刷新;初相位每次加6,每次曲线的起始点不一样,加上定时器的刷新,从而产生动态的效果。

修改上述的triangle.h文件 为如下代码

#ifndef TRIANGLE_H
#define TRIANGLE_H

#include <QWidget>
#include <QPainter>
#include <QtMath>
#include <QDebug>

class Triangle : public QWidget
{
    Q_OBJECT
public:
    explicit Triangle (QWidget *parent = 0);

protected:
    void paintEvent(QPaintEvent *event);
    void timerEvent(QTimerEvent *event);
private:
    double m_offset;
};

#endif // TRIANGLE_H

修改上述的triangle.cpp文件 为如下代码

#include "triangle.h"
Triangle::Triangle(QWidget *parent) : QWidget(parent)
{   
     this->startTimer(80);
}


void Triangle::paintEvent(QPaintEvent *event)
{
     Q_UNUSED(event);

     QPainter painter(this);  //QWidget为绘图设备,创建一个画刷对象,主要用到设置颜色和填充模式,brush,setBrush
     int width=this->width();  //获取QWidget 窗口的宽度
     int height=this->height(); //获取QWidget 窗口的高度
     //正弦曲线公式 y = A * sin(ωx + φ) + k
     double w = M_PI/100;  //w为角速度 ,可以理解为波浪的密度,越大密度越大
     double A = 20;    //  A表示振幅,可以理解为水波的高度,越大高度越高
     double k = 20;    //  k表示y轴偏移


     QPainterPath wave; //波浪区域
     wave.moveTo(0, height);//第一点坐标为(0,height);
     m_offset += 6; //初相位每次加6,每次曲线的起始点不一样,加上定时器的刷新,从而产生动态的效果
     for(int x = 0; x <= width; x+=1)  //x从0~w的值而改变,从而得到正弦曲线
     {
          double waveY = (double)(A * sin(w * x + m_offset)) + k;// waveY随着x的值改变而改变,从而得到正弦曲线
          wave.lineTo(x, waveY);   //从上一个绘制点画一条线到(x,waveY);
     }
     wave.lineTo(width, height); //右下角,坐标(width, height),移动到右下角结束点,整体形成一个闭合路径
     painter.setBrush(Qt::green); //填充绿色
     painter.drawPath(wave);      //绘制出图形
}
void Triangle::timerEvent(QTimerEvent *event)
{
    Q_UNUSED(event);
    this->update();
}

效果如图四所示 

QSplineSeries QSplineSeries绘制正弦波_QSplineSeries_05

                                                                                  图四:动态正弦曲线(水波效果)