使用qt的QPainter可以绘制出任何你想要的图形,同时也须要一定的功底;下面介绍动态正弦曲线(水波效果)的画法。
为了更好理解,分4部分去理解如何绘制。先介绍画一个画三角形,再介绍画二个画三角形,然后画静态正弦曲线(水波),最后,画动态正弦曲线(水波效果)。主要用到QPainter与QPainterPath类。
文件包含如图零所示
图零:包含文件
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
#include
#include
#include
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
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); //绘制出图形
}
效果如图一所示
图一: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); //绘制出图形
}
效果如图二所示
图二:两个三角形
修改上述的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); //绘制出图形
}
效果如图三所示
图三:正弦曲线(水波)
相对于静态态正弦曲线,动态正弦曲线产生水波效果主要依靠,初相位的改变与定时器的刷新。基于上面的代码只需修改“double m_offset = 6;”为“double m_offset += 6”; //初相位改变,增加timerEvent// 定时器事件,定时器的刷新;初相位每次加6,每次曲线的起始点不一样,加上定时器的刷新,从而产生动态的效果。
修改上述的triangle.h文件 为如下代码
#ifndef TRIANGLE_H
#define TRIANGLE_H
#include
#include
#include
#include
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();
}
效果如图四所示
图四:动态正弦曲线(水波效果)