Qt绘图原理
2016-10-15 20:53
225 查看
Qt绘图要用到QPainter类,绘图的设备通常是主部件,也可以是QLabel部件或QTextEdit部件,通过一定的算法实现可以绘制出很漂亮的图形或我们需要的图形。
绘制时需要先定义一个QPainter类对象,绘制可以选择的道具可以使Qpen(画笔)、QBrush(画刷)。使用QPen写文本时还可以指定字体(QFont类)
如下面一段代码:
其它的功能大同小异,参考Help文档,里面有各个方法的具体含义及参数意义。
这里要说的是,绘图在什么时候发生,怎样更新绘制的视图。
绘图时,需要重载QWidget类的paintEvent ( QPaintEvent * )方法,函数原型为
void QWidget::paintEvent ( QPaintEvent * ) [虚 保护] 该函数是受保护的虚函数,是绘制事件的函数,可以在派生类中被重新实现来接受绘制事件。
所以使用时要现在类中声明paintEvent函数,然后在函数定义中实现图像的绘制。注意参数要写上QPaintEvent *event
搞清楚这些后,我们就知道了,图形的绘制是在paintEvent这个函数中完成的,也就是说,不一定要把所有绘制的代码全写在paintEvent这个函数中(当然,很多教程都是这样写的,代码较长而且有一定框架时不建议这样),可以在外面的函数中实现,在paintEvent中调用相应的函数。
然后我们需要弄清楚,什么时候绘制的问题,其实在使用类的对象的时候,如果类中重写了paintEvent事件,对象就会调用一次paintEvent函数,即定义对象时会调用该绘制事件。如果要完成图像重绘或刷新图像时怎么办呢?这就要使用repaint()或update()函数完成,这两个都是QWidget类的成员函数,派生类可以直接调用这两个函数进行窗口的擦除和绘制(注意是先擦除然后在绘制),即通过repaint()或updata()调用paintEvent事件。如果需要立即重新绘制,我们建议使用repaint(),但repiant()有个缺陷,因为倘若repaint()后paintEvent函数中要调用的函数中又有repaint(),就会陷入无限循环中,而updata()则不会出现此情况,因为updata()通过某一机制会让paintEvent事件只调用一次。在绝大多数情况下,update()更好,因为它允许Qt来优化速度并且防止闪烁。
特别要注意一点,在绘制时,Qt在paintEvent事件中已经帮我们自动实现了双缓冲(X11系统需要手动去开启双缓冲),即绘制使用的就是双缓冲的方法,这与MFC有区别,MFC中需要我们自己使用双缓冲,否则在某些应用中就会出现闪烁。
QPaintEngine类提供了QPainter如何绘制给定平台上给定设备的抽象定义。
Qt为我们支持的不同画家后端提供了QPaintEngine的几个预制实现。提供的主要绘图引擎是栅格绘图引擎,其包含支持所有支持的平台上的完整功能集的软件渲染器。这是在基于QWidget的类上绘画的默认值。在Windows,X11和Mac OS X上,它是用于在QImage上绘画的后端,它用作不支持某种功能的绘画引擎的后备。此外,我们为OpenGL(可通过QGLWidget访问)和打印(允许使用QPainter绘制QPrinter对象)提供QPaintEngine实现。
如果想要使用QPainter来绘制不同的后端,则必须将QPaintEngine子类化并重新实现其所有虚函数。然后QPaintEngine实现通过子类化QPaintDevice并重新实现虚拟函数QPaintDevice :: paintEngine()来实现。
QPaintEngine是由创建它的QPaintDevice创建和拥有的。
mywidget.cpp
绘制时需要先定义一个QPainter类对象,绘制可以选择的道具可以使Qpen(画笔)、QBrush(画刷)。使用QPen写文本时还可以指定字体(QFont类)
如下面一段代码:
QPanter painter; QPen pen; pen.setColor(QColor(255,0,0)); //设置画笔为红色 painter.setPen(pen); //选择画笔 painter.drawLine(0,0,100,100); //用该红色画笔画一条线,起点(0,0),终点(100,100) painter.end(); //结束绘制。绘制时使用的任何资源都被释放。虽然有时不需要调用end(),析构函数将会执行它
其它的功能大同小异,参考Help文档,里面有各个方法的具体含义及参数意义。
这里要说的是,绘图在什么时候发生,怎样更新绘制的视图。
绘图时,需要重载QWidget类的paintEvent ( QPaintEvent * )方法,函数原型为
void QWidget::paintEvent ( QPaintEvent * ) [虚 保护] 该函数是受保护的虚函数,是绘制事件的函数,可以在派生类中被重新实现来接受绘制事件。
所以使用时要现在类中声明paintEvent函数,然后在函数定义中实现图像的绘制。注意参数要写上QPaintEvent *event
搞清楚这些后,我们就知道了,图形的绘制是在paintEvent这个函数中完成的,也就是说,不一定要把所有绘制的代码全写在paintEvent这个函数中(当然,很多教程都是这样写的,代码较长而且有一定框架时不建议这样),可以在外面的函数中实现,在paintEvent中调用相应的函数。
然后我们需要弄清楚,什么时候绘制的问题,其实在使用类的对象的时候,如果类中重写了paintEvent事件,对象就会调用一次paintEvent函数,即定义对象时会调用该绘制事件。如果要完成图像重绘或刷新图像时怎么办呢?这就要使用repaint()或update()函数完成,这两个都是QWidget类的成员函数,派生类可以直接调用这两个函数进行窗口的擦除和绘制(注意是先擦除然后在绘制),即通过repaint()或updata()调用paintEvent事件。如果需要立即重新绘制,我们建议使用repaint(),但repiant()有个缺陷,因为倘若repaint()后paintEvent函数中要调用的函数中又有repaint(),就会陷入无限循环中,而updata()则不会出现此情况,因为updata()通过某一机制会让paintEvent事件只调用一次。在绝大多数情况下,update()更好,因为它允许Qt来优化速度并且防止闪烁。
特别要注意一点,在绘制时,Qt在paintEvent事件中已经帮我们自动实现了双缓冲(X11系统需要手动去开启双缓冲),即绘制使用的就是双缓冲的方法,这与MFC有区别,MFC中需要我们自己使用双缓冲,否则在某些应用中就会出现闪烁。
QPaintEngine类提供了QPainter如何绘制给定平台上给定设备的抽象定义。
Qt为我们支持的不同画家后端提供了QPaintEngine的几个预制实现。提供的主要绘图引擎是栅格绘图引擎,其包含支持所有支持的平台上的完整功能集的软件渲染器。这是在基于QWidget的类上绘画的默认值。在Windows,X11和Mac OS X上,它是用于在QImage上绘画的后端,它用作不支持某种功能的绘画引擎的后备。此外,我们为OpenGL(可通过QGLWidget访问)和打印(允许使用QPainter绘制QPrinter对象)提供QPaintEngine实现。
如果想要使用QPainter来绘制不同的后端,则必须将QPaintEngine子类化并重新实现其所有虚函数。然后QPaintEngine实现通过子类化QPaintDevice并重新实现虚拟函数QPaintDevice :: paintEngine()来实现。
QPaintEngine是由创建它的QPaintDevice创建和拥有的。
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
namespace Ui {
class MyWidget;
}
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = 0);
~MyWidget();
protected:
//虚函数,重写绘图事件
//在窗口中的绘图,在绘图事件中实现
//绘图事件内部自动调用,当窗口状态改变时
virtual void paintEvent(QPaintEvent *);
private slots:
void on_pushButton_clicked();
private:
Ui::MyWidget *ui;
//移动位置x坐标
int x;
};
#endif // MYWIDGET_H
mywidget.cpp
#include "mywidget.h"
#include "ui_mywidget.h"
#include <QPainter>
#include <QPaintEngine>
#include <QPen>
#include <QBrush>
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyWidget)
{
ui->setupUi(this);
x = 0;
resize(1000, 600);
}
MyWidget::~MyWidget()
{
delete ui;
}
void MyWidget::paintEvent(QPaintEvent *)
{
//创建画家
//QPainter p(this);
QPainter p;
p.begin(this);
//画背景图
//drawXXXX();
//p.drawPixmap(0, 0, this->width(), this->height(), QPixmap("../Image/c++study.jpg"));
//p.drawPixmap(rect(), QPixmap("../Image/Frame.jpg"));
//设计画笔
QPen pen;
pen.setWidth(5);
pen.setColor(Qt::red);
//将画笔交给画家
p.setPen(pen);
//画直线
p.drawLine(20, 30, 100, 150);
QPen pen2;
p.setPen(pen2);
//设计画刷
QBrush brush;
brush.setColor(Qt::green);
brush.setStyle(Qt::Dense2Pattern);
//将画刷交给画家
p.setBrush(brush);
//画矩形
p.drawRect(150, 20, 200, 100);
//画圆形
p.drawEllipse(200, 300, 80, 80);
//p.drawPixmap(x, 400, QPixmap("./face.png"));
p.drawPixmap(x, 400, 100, 100, QPixmap("../Image/face.png"));
p.end();
}
void MyWidget::on_pushButton_clicked() //通过ui设计界面转到槽实现
{
//计算图片移动x坐标
x += 30;
if(x > this->width())
{
x = 0;
}
//刷新窗口
//间接调用绘图事件
update();
}
相关文章推荐
- Qt QPainter绘图原理
- Qt QPainter绘图原理
- Qt QPainter绘图原理
- Qt QPainter绘图原理
- Qt QPainter绘图原理
- Qt的跨平台绘图系统
- qt超强绘图控件qwt - 安装及配置
- 学习OpenGL-ES: 3 - 3D绘图原理
- Qt5功能包之绘图系统--坐标系
- QT中关于信号与槽机制的实现原理
- QT的信号与槽原理
- Qt 2D绘图
- QT中关于信号与槽机制的实现原理
- QT源码解析(四)剖析Qt的事件机制原理
- Android 中 Canvas 绘图之 PorterDuffXfermode 使用及工作原理详解
- QT绘图系统
- Qt之二维绘图
- CodeBlocks+MinGW+Qt编译原理
- .NET中旋转/缩放/平移绘图的原理及方法
- QT开发之mock原理