您的位置:首页 > 编程语言 > Qt开发

Qt之2D绘图

2014-02-11 11:55 459 查看
Qt中提供了强大的2D绘图系统,可以使用相同的API在屏幕和绘图设备上进行绘制,主要基于QPainter、QPaintDevice和QPaintEngine这3个类。其中,QPainter类用来执行绘图操作;QPaintDevice类提供绘图设备(绘图设备类QPaintDevice是所有可以绘制的对象的基类,它的子类主要有QWidget、QPixmap、QPicture、QImage和QPrinter),是一个二维空间的抽象,可以使用QPainter在其上进行绘制;QPaintEngine类提供了一些接口,可以用于QPainter在不同的设备上进行绘制。

绘图系统中由QPainter来完成具体的绘制操作,提供了大量高度优化的函数来完成GUI编程所需要的大部分绘制工作。QPainter可以在继承自QPaintDevice类的任何对象上进行绘制操作。重点:QPainter一般在一个部件重绘(Paint Event)的处理函数paintEvent()中绘制;首先要创建QPainter对象,再进行图形的绘制,最后销毁QPainter对象。

QPainter提供的常用图形绘制函数



实例代码如下:

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>

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.drawLine(QPoint(0, 0), QPoint(100, 100));

//创建画笔
QPen pen(Qt::green, 5, Qt::DotLine, Qt::RoundCap, Qt::RoundJoin);
//使用画笔
painter.setPen(pen);
QRectF rectangle(70.0, 40.0, 80.0, 60.0);
int startAngle = 30 * 16;
int spanAngle = 120 * 16;
//绘制圆弧
painter.drawArc(rectangle, startAngle, spanAngle);

//重新设置画笔
pen.setWidth(1);
pen.setStyle(Qt::SolidLine);
painter.setPen(pen);
//绘制一个矩形
painter.drawRect(160, 20, 50, 40);
//创建画刷
QBrush brush(QColor(0, 0, 255), Qt::Dense4Pattern);
//使用画刷
painter.setBrush(brush);
//绘制椭圆
painter.drawEllipse(220, 20, 50, 50);
//设置纹理
brush.setTexture(QPixmap("../yafeilinux.png"));
//重新使用画刷
painter.setBrush(brush);
//定义四个点
static const QPointF points[4] = {
QPointF(270.0, 80.0),
QPointF(290.0, 10.0),
QPointF(350.0, 30.0),
QPointF(390.0, 70.0)
};
//使用四个点绘制多边形
painter.drawPolygon(points, 4);

//使用画刷填充一个矩形区域
painter.fillRect(QRect(10, 100, 150, 20), QBrush(Qt::darkYellow));
//擦除一个矩形区域的内容
painter.eraseRect(QRect(50, 0, 50, 120));

//线性渐变
QLinearGradient linearGradient(QPointF(40, 190), QPointF(70, 190));
//插入颜色
linearGradient.setColorAt(0, Qt::yellow);
linearGradient.setColorAt(0.5, Qt::red);
linearGradient.setColorAt(1, Qt::green);
//指定渐变区域以外的区域的扩散方式
linearGradient.setSpread(QGradient::RepeatSpread);
//使用渐变作为画刷
painter.setBrush(linearGradient);
painter.drawRect(10, 170, 90, 40);

//辐射渐变
QRadialGradient radialGradient(QPointF(200, 190), 50, QPointF(275, 200));
radialGradient.setColorAt(0, QColor(255, 255, 100, 150));
radialGradient.setColorAt(1, QColor(0, 0, 0, 50));
painter.setBrush(radialGradient);
painter.drawEllipse(QPointF(200, 190), 50, 50);

//锥形渐变
QConicalGradient conicalGradient(QPointF(350, 190), 60);
conicalGradient.setColorAt(0.2, Qt::cyan);
conicalGradient.setColorAt(0.9, Qt::black);
painter.setBrush(conicalGradient);
painter.drawEllipse(QPointF(350, 190), 50, 50);

//画笔使用线性渐变来绘制直线和文字
painter.setPen(QPen(linearGradient,2));
painter.drawLine(0, 280, 100, 280);
painter.drawText(150, 280, tr("helloQt!"));
}采用QPainter::QPainter(QPaintDevice* device)构造函数创建的对象会立即开始在设备上绘制,自动调用begin()函数,然后在QPainter的析构函数中调用end()函数结束绘制。

渐变填充:在Qt中,QGradient类就是用来和QBrush一起制定渐变填充的。

1、线性渐变在开始点和结束点之间插入颜色;

2、辐射渐变在焦点和环绕它的圆环间插入颜色;

3、锥形渐变在圆心周围插入颜色;

这3钟渐变分别由QGradient的3个子类来表示:QLinearQradient表示线性渐变、QRadialGradient表示辐射渐变和QConicalGradient表示锥形渐变。

抗锯齿渲染

QPainter进行绘制时可以使用QPainter::setRenderHint()函数渲染提示来指定是否要使用坑锯齿功能,其功能主要是对图像的边缘进行平滑处理,使其看起来更加柔和流畅。

坐标变换

QPainter的逻辑坐标与绘图设备(绘图设备的默认坐标系统中原点是(0, 0))的物理坐标之间的映射由QPainter的变换矩阵、视口和窗口处理,逻辑坐标和物理坐标默认是一致的。绘图时可以使用QPainter::scale()函数缩放坐标系统;使用QPainter::rotate()函数顺时针旋转坐标系统;使用QPainter::translate()函数平移坐标系统;使用QPainter::shear()围绕原点来扭曲坐标系统。

1、基本变换

坐标系统的2D变换由QTransform类实现,而且QTransform类对象可以存储多个变换操作,当同样的变换要多次使用时,建议使用QTransform类对象。坐标系统的变换是通过变换矩阵实现的,可以在平面上变换一个点到另一个点。进行所有变换操作的变换矩阵都可以使用QPainter::worldTransform()函数获得,如果要设置一个变换矩阵,可以使用QPainter::setWorldTransform()函数,这两个函数也可以分别使QPainter::transform()和QPainter::setTransform()函数来替代。

在进行变换操作时,可能需要多次改变坐标系统再恢复,这样就显得很乱,而且很容易出现操作错误。这时可以使用QPainter::save()函数来保存QPainter的变换矩阵,它会把变换矩阵保存到一个内部栈中,然后在需要恢复变换矩阵时再使用QPainter::restore()函数将其弹出。

2、窗口——视口转换

使用QPainter绘制时会使用到逻辑坐标,然后再转换为绘图设备的物理坐标。逻辑坐标到物理坐标的映射由QPainter的worldTransform()函数、QPainter的viewport()以及window()函数进行处理。其中,视口表示物理坐标下制定的一个任意矩形,而窗口表示逻辑坐标下的相同矩形。默认的,逻辑坐标和屋里坐标是重合的,都相当于绘图设备上的矩形。一个很好的办法是让视口和窗口维持相同的宽高比来防止变形:

int side = qMin(width(), height());
int x = (width() / 2);
int y = (height() / 2);
//设置窗口—视口转换
painter.setViewport(x, y, side, side);
窗口——视口转换仅仅是线性变换,不会执行裁剪操作,这就意味着如果绘制范围超出了当前设置的窗口,那么仍然会使用相同的线性代数方法将绘制变换到视口上。

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>

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.fillRect(rect(), Qt::white);
painter.setPen(QPen(Qt::red, 11));
//绘制一条线段
painter.drawLine(QPoint(5, 6), QPoint(100, 99));
//将坐标系统进行平移,使(200, 150)点作为原点
painter.translate(200, 150);
//开启抗锯齿
painter.setRenderHint(QPainter::Antialiasing);
//重新绘制相同的线段
painter.drawLine(QPoint(5, 6), QPoint(100, 99));

//保存painter的状态
painter.save();
//将坐标系统旋转90度
painter.rotate(90);
painter.setPen(Qt::cyan);
//重新绘制相同的线段
painter.drawLine(QPoint(5, 6), QPoint(100, 99));
//恢复painter的状态
painter.restore();

painter.setBrush(Qt::darkGreen);
//绘制一个矩形
painter.drawRect(-50, -50, 100, 50);
painter.save();
//将坐标系统进行缩放
painter.scale(0.5, 0.4);
painter.setBrush(Qt::yellow);
//重新绘制相同的矩形
painter.drawRect(-50, -50, 100, 50);
painter.restore();

painter.setPen(Qt::blue);
painter.setBrush(Qt::darkYellow);
//绘制一个椭圆
painter.drawEllipse(QRect(60, -100, 50, 50));
//将坐标系统进行扭曲
painter.shear(1.5, -0.7);
painter.setBrush(Qt::darkGray);
//重新绘制相同的椭圆
painter.drawEllipse(QRect(60, -100, 50, 50));
}
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QToolTip>
#include <QMouseEvent>
#include <QTimer>

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
setMouseTracking(true);

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
angle = 0;
}

Widget::~Widget()
{
delete ui;
}

void Widget::paintEvent(QPaintEvent *event)
{
angle += 10;
if(angle == 360)
angle = 0;
int side = qMin(width(), height());
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QTransform transform;
transform.translate(width()/2, height()/2);
transform.scale(side/300.0, side/300.0);
transform.rotate(angle);
painter.setWorldTransform(transform);
painter.drawEllipse(-120, -120, 240, 240);
painter.drawLine(0, 0, 100, 0);
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
QString pos = QString("%1,%2").arg(event->pos().x()).arg(event->pos().y());
QToolTip::showText(event->globalPos(), pos, this);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Qt 2D绘图