QT中由图形生成SVG文件实现方案

一.QT的2D绘图

QT的2D绘图由三个主要的类搭起整个框架:QPainter,QPainterDevice和QPainterEngine。

1. QPainter负责绘图操作的具体执行,如画点,画线,填充,变换等。

2. QPainterDevice为QPainter用来绘图的绘图设备基类,其实际预定义的子类绘图设备包括Qwidget,QImage,QPixmap,QPicture,QPrinter,QSvgGenerator等。

3. QPainterEngine提供不同类型设备的接口,实现交互。

二.QSvgGenerator

QSvgGenerator属于QT中的QtSvg模块,是用于生成SVG文件的绘图设备类,派生于QPainterDevice基类。

使用QPainter进行绘图,并使用QPainter::begint()和end()显性地在QSvgGenerator上开始和结束绘图。在生成SVG文件时,可以指定文件名,文件名路径,SVG标签属性等。

三.Graphics View 框架

Graphics View框架为基于图元的模型视图模型,包括主要三个类:QGraphicsScene,QGraphicsView,QGraphItem,分别为场景,视图,图元。

1. QGraphicsScene:场景管理多个图元,可以传播事件给每个被管理的图元,实现图元的选择,焦点转移,提供无变换的场景的绘制。

场景是图元的容器,通过QGraphicsScene::addItem()可以将图元加入场景容器中。

场景使用render()函数在指定绘图设备上进行场景的绘制。

2. QGraphicsView:视图窗口部件,使场景内容可视化。一个场景可以同时拥有几个视图,这样就意味着相同的场景可以实现不同的可视化窗口。

视图可提供滚动条以浏览大的场景,可以选择QPainter或者OpenGL两种绘图方式绘图。可以接收键盘,鼠标事件。

视图与场景拥有不同的坐标系统,两者之间可通过mapToScreen()和mapFromScene()函数实现坐标转换。

3. QGraphicsItem:图元基类,其派生的常用标准图元有QGraphicsRectItem,QGraphicsLineItem,QGraphicsSvgItem等,另外可以自定义派生于QGraphicsItem的图元类。图元可处理鼠标,键盘,拖放,分组,碰撞检测等事件,拥有自己的坐标系统,可以变换,可以包含子图元。

四.Graphics View框架视图的SVG文件导出

Graphics View框架通过QGraphicsScene::render()函数和QGraphicsView::render()函数,实现将场景和视图上的内容绘制到任意的绘图设备上,两个函数的区别在于使用不同的坐标系统。QGraphicsScene::render()用于无变换的场景绘制,如静态几何图形,文本文档等。QGraphicsView::render()类似于实现屏幕快照,将当前视图数据绘制到指定绘图设备上。

五.示例

//创建保存SVG文件对话框

QString newPath = QFileDialog::getSaveFileName(this, tr("Save SVG"),

path, tr("SVG files (*.svg)"));

if (newPath.isEmpty())

return;

//指定文件保存路径

path = newPath;

//创建QSvgGenerator对象

QSvgGenerator generator;

generator.setFileName(path);

//创建QPainter绘图对象

QPainter painter;

//开始在QSvgGenerator对象上绘图

painter.begin(&generator);

//QGraphicsView数据导入绘图对象

view->render(&painter);

//绘图结束,QSvgGenerator对象自动生成SVG文档

painter.end();

=====================================================================

QPainter 能绘制: point, line, rectangle, ellipse, arc, chord, polygon, pie segment, Bezier curve, QPixmap, QImge
Qt支持的高级特性: antialising, alpha blending, gradient fill, vector path.
QPaint在什么上绘制呢? 在"paint device": QWidget, QPixmap, QImage, QSvgGenerator, 连接QPrinter来打印和生成PDF文档.

通常在protected void paintEvent(QPaintEvent *event)中进行绘制.
protected :
virtual void paintEvent(QPaintEvent *event) {
QPainter painter(this); // Pointer of the paint device
..
}
QPainter的3个主要设置是: pen, brush, font.
painter.setPen(QPen(..));
painter.setBruch(QBrush(..));
painter.setFont(QFont(..));
painter.setRenderHint(QPainter::Antialiasing, true);
设置了bursh之后, 画的是效果即fill.
QPainter的属性影响绘制的图形.

通常使用painter.paintXXX(..)来绘制图形.
========================================================================

The Paint System

Qt的绘画系统使得在屏幕上绘画成为可能,绘画装置使用相同的API,主要基于QPainter,QPaintDevice和QPaintEngine类。
QPainter被用来表现绘画操作,QPaintDevice是一个2维空间的抽象,能被绘制通过使用QPainter,QPaintEngine提供接口,painter用来在不同的装置上绘画。QPaintEngine类被用来在内部,隐藏于应用程序中,除非他们创建他们自己的装置类型。

这种方法的主要受益是:所有的绘制跟着相同的管线,使增加新特性很容易,提供缺省的执行为不支持的情况。
主题:
Classes for Painting
Paint Devices and Backends
Drawing and Filling
The Coordinate System
Reading and Writing Image Files
Styling
Printing with Qt

绘图的类:
QBitmap
单色 (1-位 深) 像素

QBrush
定义被QPainter绘制的形状填充样式

QColor
基于RGB,HSV,CMYK的颜色

QColormap
内存映射独立的QColors装置到独立的像素值装置

QConicalGradient
用来结合QBrush来表明一个圆锥深度的笔刷

QDirectPainter
直接通道为潜在的硬件为嵌入式的linux

QFont
指明一个绘制文本的字体

QFontMetrics
字体度量信息

QFontMetricsF
字体度量信息

QGenericMatrix
模板类代表一个N*M变化模型,N列M行

QGradient
用来结合QBrush来指明填充斜度

QIcon
可扩展的图标在不同模型和状态

QIconEngine
抽象的基类为QIcon渲染器

QIconEngineV2
抽象的基类为QIcon渲染器

QImage
硬件独立的图像表示,允许直接的通道到像素数据,能被用来作为一个绘制装置。

QImageReader
格式化独立的借口为读取图片从文件或者其他的装置

QImageWriter
格式化独立的借口为读取图片从文件或者其他的装置

QLine
使用整数精度的二维向量

QLineF
使用浮点数精度的二维向量

QLinearGradient
被用来结合QBrush来指明一个线的斜度笔刷

QMargins
定义一个矩形的四个边

QMovie
方便类为使用QImageReader播放电影

QPaintDevice
一个对象能被绘制的基类

QPaintEngine
抽象的定义QPainter怎样在一个被给的平台画一个被给的装置

QPainter
呈现一个低水平的绘制在widget和其他的绘制装置

QPainterPath
容器为绘画操作,使图像形状能被构建和再利用

QPainterPathStroker
被用来产生填充的轮廓为一个被给的绘画轨迹

QPalette
为每一个widget状态包含颜色组

QPen
定义一个QPainter怎样画一个形状的线和轮廓

QPicture
绘画装置记录和重演QPainter的命令

QPixmap
屏幕下的图像表示,能被用作一个绘画装置

QPixmapCache
为pixmap的应用宽度缓存

QPoint
定义一个点在平面,使用整数精度

QPointF
定义一个点在平面,使用浮点数精度

QPolygon
使用整数精度的向量点

QPolygonF
使用浮点数精度的向量点

QRadialGradient
被用来结合QBrush来指明一个辐射的斜度笔刷

QRect
使用整数精度在平面定义一个矩形

QRectF
使用浮点数精度在平面定义一个矩形

QRegion
为painter指定一个区域

QSize
使用整数精度定义一个二维对象的大小

QSizeF
使用浮点数精度定义一个二维对象的大小

QStylePainter
方便的类为在一个widget内部画一个QStyle元素

QSvgGenerator
绘画装置用来创建SVG

QSvgRenderer
用来绘制SVG文件的内容到绘制装置

QSvgWidget
Widget被用来显示矢量图(svg)文件

QTransform
指定一个坐标系统的2d变化

QVector2D
在2d空间表现一个向量或者顶点

二选一的,qt提供QtOpenGL模型,提供类使得使用OpenGL容易。模型提供一个OpenGL widget类,能被用来就像其他的qt widget,除了当它打开一个OpenGL显示缓存,那里OpenGL API能被用来渲染内容。

2D绘图
Qt4中的2D绘图部分称为Arthur绘图系统.它由3个类支撑整个框架,QPainter,QPainterDevice和QPainterEngine.QPainter用来执行具体的绘图相关操作
如画点,画线,填充,变换,alpha通道等。QPainterDevice是QPainter用来绘图的绘图设备,Qt中有几种预定义的绘图设备,如QWidget,QPixamp,QPrinter
等.他们都从QPaintDevice继承。QPaintEngine类提供了不同类型设备的接口,QPaintEngine对程序员不透明,由QPainter,QPaintDevice类与其进行交互。
从Qt4.2开始,Graphics View框架取代了QCanvas,QGraphics View框架使用了MVC模式,适合对大量2D图元的管理,Grphics View框架中,场景(scene)
存储了图形数据,它通过视图(view)以多种表现形式,每个图元(item)可以单独进行控制.
Arthur绘图基础
在Arthur绘图框架中的基本绘图元素是画笔,画刷。
QPainter类具有GUI程序需要的绝大多数函数,能够绘制基本图形(点,线,矩形,多边形等)以及复杂的图形(如绘图路径).使用绘图路径(QPaintPath)的优点是复杂形状
的图形之用生成一次,以后再使用的时候是需要调用QPainter::drawPath()就可以了。QPainterPath对象可以用来填充,绘制轮廓。
线和轮廓都可以用画笔(QPen)进行绘制,画刷(QBrush)进行填充。画笔定义了风格(线形),宽度,笔尖画刷以及端点是如何绘制的(cap-style),端点的连接方式(join-style)
.画刷用来填充画笔绘制的图形,可以定制不同的填充模式和颜色的画刷。
当绘制文字时,字体使用QFont类定义,Qt使用指定字体的属性,如果没有匹配的字体,Qt将使用最接近的字体。字体属性可以通过QFontInfo来获取。字体的度量(measurement)
使用QFontMetrics类来获取。QFontDatabase类可以获得底层窗口系统所有可用的字体.
通常情况下QPainter以默认的坐标系统进行绘制,也可以用QMatrix类对坐标进行变换。
当绘制时,可以使用QPainter::RenderHint来告诉绘图引擎是否启用饭锯齿功能使图变得平滑。
QPainter::RenderHint的可取如表6-1中的值
------------------------------------------------------------------------------------------------
QPainter::Antialiasing 告诉绘图引擎应该在可能的情况下进行边的反锯齿绘制
QPainter::TextAntialiasing 尽可能的情况下文字的反锯齿绘制
QPainter::SmoothPixmapTransform 使用平滑的pixmap变换算法(双线性插值算法),而不是近邻插值算法
-------------------------------------------------------------------------------------------------
QPainter的绘图函数
-------------------------------------------------------------------------------------------------
drawArc() 弧
drawChord() 弦
drawConvexPolygon() 凸多边形
drawEllipse() 椭圆
drawImage() QImage表示的图像
drawLine() 线
drawLines() 多条线
drawPath() 路径
drawPicture() 按QPainter指令绘制
drawPie() 扇形
drawPixmap() QPixmap表示的图像
drawPoint() 点
drawPoints() 多个点
drawPolygon() 多边形
drawPolyline() 多折线
drawRect() 矩形
drawRects() 多个矩形
drawRoundRect() 圆角矩形
drawText() 文字
drawTiledPixmap() 平铺图像
drawLineSegments() 绘制折线
------------------------------------------------------------------------------------------------
drawPicture()函数负责绘制QPicture中存储的QPainter指令,QPicture是可以记录QPainter绘图指令的类.它将QPainter的绘图指令串行化为平台无关的存储格式。
下面的代码将记录的绘图指令重绘。
QPicture picture;
picture.load("mypicture.pic");
QPainter painter(this);
painter.drawPicture(0,0,picture);//在(0,0)处重放绘图指令,也可以使用QPicture::play()完成相同的功能
使用画笔
画笔的属性包括线型,线宽,颜色等。画笔的属性可以在构造函数中指定,也可以使用setStyle(),setWidth(),setBrush(),setCapStyle(),setJoinStyle()等函数
逐项设定画笔的各项属性.Qt中使用Qt::PenStyle定义了6种画笔风格,分别是Qt::SolidLine,Qt::DashLine,Qt::DotLine,Qt::DashDotLine,Qt::DashDotDotLine,
Qt::CustomDashLine.自定义线风格(Qt::CustomDashLine),需要使用QPen的setDashPattern()函数来设定自定义风格.
下面代码设置了一个自定义QPen
QPen pen;
QVector customDashes;
qreal blank=4;
dashes<<2< pen.setDashPattern(customDashes);

端点风格(cap style)
端点风格决定了线的端点样式,它只对线宽大于1的线有效。Qt种定义了三种端点风格用枚举类型Qt::PenCapStyle表示,分别为Qt::SqureCap,QT::FlatCap,Qt::RoundCap,
连接风格(Join style)
连接风格是两条线如何连接,连接风格对线宽大于等于1的线有效。Qt定义了四种连接方式用枚举类型Qt::PenStyle表示.分别是Qt::MiterJoin,Qt::BevelJoin,Qt::RoundJoin.
Qt::SvgMiterJoin.

2.画刷
在Qt中图形使用QBrush进行填充,画刷包括填充颜色和风格(填充模式).在Qt中,颜色使用QColor类表示,QColor支持RGB,HSV,CMYK颜色模型。QColor还支持alpha混合的轮廓和
填充。基本模式填充包括有各种点,线组合的模式。Qt支持RGB,HSV,和CMYK颜色模型。RGB是面向硬件的模型。颜色由红绿蓝三种基色混合而成。HSV模型比较符合人对颜色的感觉,由
色调(0-359),饱和度(0-255),亮度(0-255)组成.CMYK由青,洋红,黄,黑四种基色组成。主要用于打印机等硬件拷贝设备上。每个颜色分量的取值是0-255.另外QColor还可以用
SVG1.0中定义的任何颜色名为参数初始化.

Qt4提供了渐变填充的画刷,渐变填充包括两个要素,颜色的变化和路径的变化。颜色变化可以指定从一种颜色渐变到另外一种颜色。也可以在变化的路径上指定一些点的颜色进行分段渐变。
Qt4中,提供了三种渐变填充:线性(QLinearGradient),圆形(QRadialGradient)和圆锥渐变(QConicalGradient).所有的类都从QGradient类继承.

------------------
线性渐变填充
线性渐变填充指定两个控制点,画刷在两个控制点之间进行颜色插值。通过创建QLinearGradient对象来设置画刷.
QLinearGradient linearGradient(0,0,200,100);
linearGradient.setColorAt(0,Qt::red);
linearGradient.setColorAt(0.5,Qt::green);
linearGradient.setColorAt(1,Qt::blue);
painter.setBrush(linearGradient);
painter.drawRect(0,0,200,100);
在QGradient构造函数中指定线行填充的两点分别为(0,0),(100,100).setColorAt()函数在0-1之间设置指定位置的颜
------------------
圆形渐变填充
圆形渐变填充需要指定圆心,半径和焦点。画刷在焦点和圆上的所有点之间进行颜色插值。创建QRadialGradient对象设置画刷
QRadialGradient radialGradient(50,50,50,30,30);
radialGradient.setColorAt(0.2,Qt::cyan);
radialGradient.setColorAt(0.8,Qt::yellow);
radialGradient.setColorAt(1,Qt::magenta);
painter.setBrush(radialGradient);
painter.drawEllipse(0,0,100,100);
-------------------------------
圆锥渐变填充
圆锥渐变填充指定圆心和开始角,画刷沿圆心逆时针对颜色进行插值,创建QConicalGradient对象并设置画刷.
QConicalGradient conicalGradient(60,40,30);
conicalGradient.setColorAt(0,Qt::gray);
conicalGradient.setColorAt(0.4,Qt::darkGreen);
conicalGradient.setColorAt(0.6,Qt::darkMagenta);
conicalGradient.setColorAt(1,Qt::drakBlue);
painter.setBrush(conicalGradient);
painter.drawEllipse(0,0,100,100);
---------------------------------
为了实现自定义填充,还可以使用QPixmap或者QImage对象进行纹理填充。两种图像分别使用setTexture()和setTextureImage()函数加载纹理.
======================================================================================================================
双缓冲绘图
在Qt4中,所有的窗口部件默认都使用双缓冲进行绘图。使用双缓冲,可以减轻绘制的闪烁感。在有些情况下,用户要关闭双缓冲,自己管理绘图。下面的语句设置了窗口部件
的Qt::WA_PaintOnScreen属性 ,就关闭了窗口部件的双缓冲.
mywidget->setAttribute(Qt::WA_PaintOnScreen);
由于Qt4不再提供异或笔,组合模式QPainter::CompostionMode_Xor()并不是异或笔,Qt4只提供了QRubberBand实现矩形和直线的绘图反馈。因此要实现在绘图中动态
反馈必须使用其他方法。程序中使用双环冲来解决这个问题。在绘图过程中,一个缓冲区绘制临时内存,一个缓冲区保存绘制好的内容,最后进行合并。
在交互绘图过程中,程序将图像缓冲区复制到临时缓冲区,并在临时缓冲区上绘制,绘制完毕在将结果复制到图像缓冲区,如果没有交互复制,则直接将图像缓冲区绘制显示到屏幕上。
------------------------
使用alpha通道
在windows,Mac OSX和有XRender扩展的X11系统上,Qt4能够支持Alpha通道,通过使用Alpha通道,可以实现半透明效果,QColor类中定义了Alpha通道的透明度,0表示完全透明
255表示完全不透明。注意QWidget类有一个属性windowOpacity,通过setWindowOpacity(qreal level)可以设置窗口的透明度。但该属性和Alpha通道的原理并不相同,Qt4在
Windows和Mac OS X平台上才支持该属性,但在X11平台上却需要Composite扩展才能工作。(alpha通道使用的是X11的xRender扩展).
---------------------------------------
绘图设备
QPaintDevice类是实际的绘制设备的基类.QPainter能够在QPaintDevice子类上进行绘制,如QWidget,QImage,QPixmap,QGLWidget,QGLPixelBuffer,QPicture,QPrinter
QSvgGenerator.要实现自己的绘图设备,必须从QPaintDevice类继承并实现其虚函数QPaintDevice::paintEngine()以告之QPainter能够在这个特定的设备上绘制图形,同时还需要从
QPaintEngine类继承自定义的图形绘制引擎。

1 QWidget
QWidget是所有用户界面元素的基类,窗口部件时用户界面的原子元素,他接受鼠标,键盘,窗口系统的其他事件并在屏幕上绘制自己。
2 QImage
QImage类提供了与硬件无关的图像表示,它为直接操作像素提供优化,QImage支持单色,8-bit,32-bit和alpha混合图像,使用QImage的优点在于可以获得平台无关的绘制操作,另外还有一个好处
时图像可以不必在GUI线程中处理。
3 QPixmap
QPixmap时后台显示的图像,它为在屏幕上显示图像提供优化,不同于QImage,pixmap的图像数据用户不可见,而且由底层窗口系统管理,为了优化QPixmap图像,Qt提供了QPixmapCache类来存储
临时的pixmap.Qt还提供了QPixmap的继承类QBitmap类,QBitmap表示单色的pixmap,主要用来创建自定义的QCursor和QBrush对象,构造QRegion对象,设置pixmap和窗口部件的掩码。
4 OPenGLWidget
Qt提供了QtOpenGL模块来实现OpenGL操作,QGLWidget允许使用OpenGL API进行绘制。同时QGLWidget时QWidget的子类,因此QPainter也可以在上面绘制。这样可以使Qt能够利用OpenGl
完成绘制操作,如变换和绘制pixmap
5 pixel Buffer
QGLPixelBuffer从QPaintDevice继承,封装了OpenGL pbuffer.使用pbuffer绘制通常时全硬件加速,这比使用QPixmap绘制更为迅速。
6 FrameBuffer
QGLFrameBufferObject从QPaintDevice继承,QGLFrameBufferObject封装了OpenGL frameBuffer对象,FrameBuffer对戏那个用来实现后台屏幕绘制,比pixel buffer更好一些。
7 picture
QPicture类时能够记录和重演QPainter命令的绘图设备,picture串行化painter的命令为平台无关的格式,QPicture同时也于分辨率无关,如QPicuture能够在不同的设备上(svg,pdf,ps
打印机和屏幕)有一只的显示。QPicture::load()和QPicture::save()函数分别完成载入和存储图像。
8 Printer
QPrinter类时在打印机上绘制的绘图设备,在Windows和MAC OS X上,QPrinter使用内建的打印机驱动程序,在X11上,QPrinter山城postscript代码并发送给lpr,lp或者其他打印程序,QPrinter可以在任意其他QPrintEngine对象上打印,也可以直接生成PDF文件。
QPrintEngine类定义了QPrinter如何和其他打印机系统交互的接口,主要创建自己的打印引擎时,可以从QPaintEngine和QPaintEngine上继承。
======================================================================================================

坐标系统与坐标变换

1. Qt坐标系统由QPainter控制,同时也由 QPaintDevice和QPaintEngine类控制.QPaintDevice类是绘图设备的基类,QWidget,QPixmap,QImage,和QPrinter都是QPaintDevice类的子类。Qt绘图设备默认坐标原点是左上角,X轴向右增长,Y轴向下增长,默认的单位在基于像素的设备上是像素,在打印机设备上是1/72英寸(0.35毫米).QPainter的逻辑坐标与QPainterDevice的物理坐标之间的映射由QPainter的变换矩阵,视口和窗口处理。逻辑坐标和物理坐标也是一直的。QPainter也支持坐标变换(如旋转和伸缩);

2. 坐标变换。
通常QPainer在设备的坐标系统上绘制图形,但QPainter也支持坐标变换。可以通过QPainter::scale()函数进行比例变换。使用QPainter::rotate()函数进行旋转变换。平移变换则使用QPainter::translate()函数,QPainter::shear()函数对图形进行扭曲操作,所有变换操作的变换矩阵都可以通过QPainter::wordMatrix()函数取出。不同的变换矩阵可以使用堆栈保存。
用QPainter::save()保存变换矩阵到堆栈,用QPainter::restore()函数将其弹出堆栈。
QMatrix定义了系统的二维变换。QMatrix对象实际上定义了一个3x3矩阵。
--------------
m11 m12 0
m21 m22 0
dx dy 1
---------------
x\\'=m11*x+m21*y+dx;
y\\'=m22*y+m12*x+dy;
其中dx,dy表示水平和垂直偏移量,m11,m22表示水平和垂直方向上的比例。m12和m21表示水平和垂直方向上的扭曲程度。
矩阵可以通过setMatrix函数进行设置,然后可以使用translate(),rotate(),scale(),shear()等函数进行变换.Qt4.3中引入QTransform类表示变换矩阵。与QMatrix不同的是,QTransform()支持透视变换。使用toAffine()函数可以将QTransform对象转换为QMatrix对象。这将丢失QTransform的透视变换数据。逻辑坐标和物理坐标的变换由QPainter的worldMatrix()函数。以及QPainter的viewport()和window()函数处理。视口表示物理坐标下的任意矩形。而在窗口表示在逻辑坐标下的相同矩形。默认情况下逻辑坐标与物理坐标时相同的。与绘图设备上的矩形也是一致的。使用窗口-视口变换可以使逻辑坐标符合自定义要求,这个机制通常用来完成设备无关的绘图代码。例如,可以设置逻辑坐标(-100,-100)到(100,100)且在原点(0,0),通过调用QPainter::setWindow()函数可以完成下列操作。
QPainter painter(this);
painter.setWindow(QRect(-100,-100,200,200));
现在,逻辑坐标的(-100,-100)对应着绘图设备的(0,0),这样可以绘制独立于设备,始终在指定逻辑坐标上工作。设置窗口或视口矩形实际上是执行线性变换。本质上是窗口四个角映射到对应的视口四个角,反之亦然,因此保持视口和窗口x轴和y轴之间的比例变换一致,保证变换没有变形。窗口-视口变换只是线性变换,不执行裁剪操作,例如当绘制超出窗口后,这些绘制仍然 通过线性变换映射到
视口进行绘制。Qt的绘制过程是进行坐标变换,在进行窗口-视口变换。

==================================================================================================================
使用不同的字体

Qt提供了Font类来表示字体,当创建QFont对象时,Qt会使用指定的字体,如果没有对应的字体,Qt将寻找一种最接近的已安装字体。字体信息可以通过
QFontInfo取出,并可用QFontMetrics取得字体的相关数据。函数exactMatch()判断底层窗口系统中是否有完全对应的字体。使用QApplication::setFont()可以设置应用程序默认的字体,如果选择的字体不包括所有要显示的字符,QFont将会尝试寻找最基接近的字体。当QPainter绘制指定的字体中不存在的字符时
将绘制一个空心的正方行。
绘图路径 --QPainterPath
绘图路径(painter path)由基本图元(矩形,椭圆,直线,曲线)组成,绘图路径可以是闭合的路径,如矩形和圆,或者是非闭合的路径,如直线和曲线。绘图路径在Qt中使用QPainterPth类表示,
它提供了绘图操作的容器,可以使图形能够复用。绘图路径可以进行填充,显示轮廓和裁剪。要生成可填充的轮廓的绘图路径,可以使用QPainterPathStroker类.使用QPainterPath的优点是复杂的
图形只需创建一次,就可以多次使用。QPainterPath对象可以时只有起点的空路径,或者从其他QPainterPath对象复制,创建了QPainterPath对象后,可以使用lineTo(),cubicTo(),
quadTo()函数将直线和曲线添加到路径中来,直线和曲线从currentPosition()开始绘制。currentPosition()总是返回最后的子路经绘制的终点。使用moveTo()函数可以在不增加路径的情况下移动currentPositon(),它关闭了一个子路经,开始一个新的子路经。closeSubPath()也可以关闭当前路径,并从currentPosition()连接一条直线到绘图路径的起点。QPainter可以使用addEllipse(),addPath(),addRect(),addRegion(),addText()将Qt的一些基本图元加入绘图路径。一个已有的绘图路径可以通过connectPath()函数加入到另一个绘图路径中。
如下代码绘制了一个箭头:
QPainterPath path;
path.moveTo(10,100);
path.cubicTo(10,100,100,10,200,70);
path.lineTo(200,50);
path.lineTo(220,80);
path.lineTo(200,110);
path.lineTo(200,90);
path.cuticTo(200,100,100,50,50,100);

QPainter painter(this);
QPen pen(QColor(255,0,0),2);
painter.setPen(pen);
painter.drawPath(path);

Qt提供了两种填充方式,Qt::OddEventFill和Qt::WindingFill.Qt::OddEvent时默认的填充规则,它指定QPainterPath使用奇偶填充规则,该规则判断一个点是否在论经图形内的方法是从该店画一条水平线到路径外,计算水平线和路径的交点数,如果交点时奇数个则说明该点在路径图形内。QPainterPath还有一些函数可以获取路径信息,如elementAt()函数可以取出指定的子路经元素,
isEmpty()函数判断当前路径是否为空。controlPointRect()函数返回路径中所有的点和控制点的矩形,该函数运行速度比返回精确包容框boundingRect()函数快得多。contains()函数判断一个点或一个矩形是否在路径内。intersects()判断指定的矩形与路径是否相交.QPainterPath可以将矩形图形转换为其他图形,如使用toFillPolygon(),toFillPolygon(),toSubpathPOlygons()函数将路径转化为多边形。
QPainterPath还可以使用文字作为路径,下面的代码演示了文字路径,并使用线性渐变填充。
QLinearGradient linearGrad(QPointF(200,0),QPointF(1000,0));
linearGrad.setColorAt(0,Qt::black);
linearGrad.setColorAt(1,Qt::white);
QFont font("隶书",80);
font.setBold(true);
QPainterPath textPath();
textPath.addText(200,300,font,tr("电子工业出版社"));
painter.setBrush(linearGrad);
painter.drawPath(textPath);

===========================================================================
QImage和QPixmap绘图设备
Qt提供了4个处理图像的类。QImage,QPixmap,QBitmap,QPicure.他们有着各自的特点。QImage优化了I/O操作,可以直接存取操作像素数据。QPixmap主要用来在屏幕上显示图像。QBitmap从QPixmap继承,只能表示两种颜色,QPicture是可以记录和重放QPrinter命令的类。QImage提供了与硬件无关的图像表示方法。通过QImage可以直接存取像素数据,QImage也可以用作绘图设备。
QImage支持的图像颜色可以是单色,8位,32位和alpha混合的格式。因为QImage从QPainterDevice继承,所以QPainter可以直接在QImage上绘图。除了绘制文字格式外(QFont依赖于底层的GUI).其他的绘制操作可以在任意线程中完成,如果要在其他线程中绘制文字,可以使用QPainterPath。QImage对象具有隐式共享,作为传值参数,可以使用数据流及进行比较等特性。
读入图像可以通过QImage构造函数,load(),loadFromData()几种方法完成。还可以通过QImage的静态函数fromData()由指定数据构造一个QImage对象。既可以从文件系统装入,也可以从Qt应用程序的嵌入式资源中读取,使用save()可以保存QImage对象。可以通过QImageReader::supportedImageFormats()和QImageWriter::supportedImageFormats()获取QImage支持的所有文件格式列表。
------------------------------------------
QImage函数
--------------------------------------------------------------------------------------------------------------------------------------------------
几何函数 size(),widt(),dotsPermeterX(),dotsPerMeterY()函数获取图像大小和比例信息。
rect()函数返回图像的包容矩形,valid()测试给定的坐标是否在此矩形内。offset()获取图像和其他图像之间的相对偏移量。setOffset()函数设置偏移量。
颜色函数 某个像素的颜色可以通过pixel函数获取,返回值是QRgb类型,对于单色和256色图像,colorTable()返回调色板,numColors返回调色板中的条目数.用pixelIndex()
函数获取像素的颜色索引,然后使用color()函数取出实际的颜色值.hasAlphaChannel()函数返回图像是否使用了alpha通道。allGray(),isGrayscale()测试图像是否为灰度图像。
文字 text()函数返回图像附属的文字,textKeys()返回文字的键值表。setText()函数改变图像附属文字.
低级信息 depth()函数获取图像颜色位数.支持1,8,32位.format().bytesPerLine()和numBytes()函数返回图像的数据存储信息.serieralNumber()函数取得唯一标识QImage对象的数字.
--------------------------------------------------------------------------------------------------------------------------------------------------

QImage的8位和单色图像采用颜色索引表的方式存取,32为的图像则直接存储ARGB值.因此他们的像素操作函数也不相同,对32位的图像,setPixel()函数可以改变指定像素的QRgb颜色值,对8位和
单色图像,setPixel()改变在预定义颜色表中的索引值,如果要改变颜色表,可以使用setColor()函数。QImage提供scanLine()函数返回指定行的数据。bits()函数返回第一个像素的指针。每个像素在QImage中都使用整数形式表示。单色图像使用一位的索引指向只有两种颜色的调色板,有两种类型的单色图像,big endia(MSB),little endian(LSB).256色图像使用8位颜色调色板,调色板的数据类型是QVector,QRgb实际上时无符号整数型,存储ARGB的格式是0xAARRGGBB.32位的图像直接存储,有三种类型的存储格式:RGB,ARGB和已预乘的ARGB。在已预乘ARGB中,红绿蓝三色已经和alpha相乘并模除255.allGray()和isGrayscale()函数可以判断一个彩色图像能否安全转化为灰度图像。图像的格式用format()函数读取出,convertToFormat()可以进行图像格式转化,QImage支持的存储格式如下:
QImage::Format_Mono 单色图像(MSB)
QImage::Format_MonoLSB 单色图像(LSB)
QImage::Format_Indexed8 使用颜色表的256色图像
QImage::Format_RGB32 不支持Alpha通道的32位图像
QImage::FOrmat_ARGB32 含Alpha通道的32位图像
QImage::Format_ARGB32_Premultiplied 已预乘的含Alpha通道的32位图像.

-----------------------------------
QPixmap
QPixmap主要完成屏幕后台(off-screen)缓冲区绘图。QPixmap对象可以使用QLabel或QAbstractButton子类(QPushButton,QToolButton)显示,QLabel通过设置pixmap属性,QAbstractButton通过设置icon属性来完成,除了使用构造函数初始化,QPixmap对象还可以使用静态函数grabWidget()和grabWindow()函数创建,并绘制指定的窗口和窗口部件.QPixmap中的像素数据时内部的,并且由底层的窗口系统进行管理,如果要存取像素,只有通过QPrinter函数将QPixmap对戏那个转换为QImage对象,根据底层系统的不同,QPixmap可以RGB32或者混合alpha格式存储,如果图像有Alpha通道且底层系统允许,则优先使用混合alpha格式,因此QPixmap时依赖于底层系统的,在X11上和Mac上,QPixmap存储在服务器端,QImage存储在客户点,在windows上,这两个类表达方式时相同的。QImage和QPixmap可以相互转换,通常QImage载入图像并进行直接操作,然后转换为QPixmap在屏幕上显示。如果不需要操作像素,就直接使用QPixmap.在windows上,QPixmap还可以与HBITMAP之间相互转换,QPixmap和QImage一样使用隐式共享,也能够使用数据流。

=======================================================================================================
组合模式绘图
组合模式(Composition Mode)用来指定如何合并源图像和一个图像,最常见的是SourceOver(通常也叫alpha混合),当原像素和目标像素以这种方式混合时,源图像的alpha通道定义了像素的透明度。组合模式绘图只支持Format_ARGB32_Premultiplied和Format_ARGB32格格式,而且应该优先使用Format_ARGB32_Premultiplied格式,设置了组合模式后,它对所有的绘图操作都有效,如画笔,画刷,渐变效果和pixmap/image绘制。QPainter::CompositeMode枚举类型中前12中组合类型是T.Porter和T.Duff于1984年在沦为(Compositing Digital Image)中阐明的12种混合规则(Porter-Duff规则)混合的计算方法在此给出。以便理解混合的过程。
首先定义混合的因子 :
As: 原像素的alpha分量
Cs: 原像素种计算好(premultiplied)色彩分量
Ad: 目标像素的alpha分量
Cd; 目标像素计算好的色彩分量
Fs: 原像素在输出结果种占有的比例
Fd: 目标像素在输出结果种占有的比例
Ar: 输出结果种的Alpha分量
Cr: 输出结果种计算好的色彩分量
Porter和Duff定义了选择混合因子Fs和Fd产生不同的视觉效果的12种规则,最终结果种的Alpha值和色彩值由下面的公式决定
Fs=f(Ad);
Fd=f(As);
Ar=AsxFs+AdxFd
Cr=CsxFs+CdxFd
每种类型的Fs和Fd取值如表所示
------------------------------------------------------------------------------------------
常 量 Fs Fd 说明
QPainter::CompositionMode_SourceOver 1 1-As 默认模式,源alpha和目标像素混合
QPainter::CompositionMode_DestinationOver 1-Ad 1 和SourceOver相反,目标Alpha和源像素混合
QPainter::CompositionMode_Clear N/A N/A 清除目标像素
QPainter::CompositionMode_Source N/A N/A 输出源像素
QPainter::CompositionMode_SourceIn Ad 0 在目标部分的源替代目标
QPainter::CompositionMode_DestinationI 0 As 于SourceIn相反
QPainter::CompositionMode_SourceOut 1-Ad 0 在目标之外的源替代目标
QPainter::CompositionMode_DestinationOut 0 1-As 于SourceOut相反
Qpainter::CompositionMode_SourceAtop Ad 1-As 在目标部分的源和目标组合
QPainter::CompositionMode_DestinationAtop 1-Ad As 与sourceatop相反
QPainter::CompositionMode_Xor 1-Ad 1-As 在目标之外的源和源之外的目标混合
--------------------------------------------------------------------------------------------------------
注意,上面的说明并没有完全概括各种混合的含义,要准确理解他们可以看公式并进行实践,畜类上面12种Porter_Duff规则外,Qt还支持12种扩展混合模式。下面给出计算公式需要注意如果结果中alpha值和色彩值超过0-255的范围,数值将会被截断

1 QPainter::CompositionMode_Plus 源和目标相加,该操作实现动画中两幅图像的溶解和过度过程。Cr=Cs+Cd Ar=As+Ad
2 QPainter::CompositionMode_Multiply 源和目标进行正片叠底(multiply)操作。结果的颜色至少是源和目标种较暗的颜色。任何颜色和黑色作该操作产生黑色。任何颜色和白色作
该操作将不会改变。Cr=CsxCd+Csx(1-Ad)+Cdx(1-As) Ar=AsxAd+Asx(1-Ad)+Adx(1-As)=As+Ad-AsxAd
3 QPainter::CompositionMode_Screen 源和目标互补然后相乘结果的颜色至少是源和目标种较亮的颜色。任何颜色和黑色进行滤色操作不会改变,任何颜色和白色进行滤色操
作还是白色
4 QPainter::CompositionMode_Overlay 根据目标颜色值不同,进行相乘操作或滤色操作,源色彩保持亮度和阴影覆盖在目标上。目标颜色和源颜色混合以反应目标的亮度。
5 QPainter::CompositionMode_Darken 选择源和目标种较暗的颜色
6 QPainter::CompositionMode_Lighten 选择源和目标种较亮的颜色
7 QPainter::CompositoinMode_ColorDodge 加亮目标颜色以反应源颜色,绘制黑色将没有效果
8 QPainter::CompositionMode_ColorBurn 使目标颜色变暗以反应源颜色,绘制白色没有效果。
9 QPainter::CompositionMode_HardLight 根据源的颜色,决定是正片叠底还是滤色操作。如果源颜色高于0.5,目标颜色将变亮。即进行滤色操作。如果源颜色亮度值低于0.5,目标将
会变暗,相当于进行了正片叠底操作。如果源亮度值等于0.5,目标不会改变,变亮或者变暗成都取决于源颜色和0.5的差,绘制纯黑色和纯白
色结果还是纯黑或纯白。
10 QPainter::CompositionMode_SoftLight 根据源的颜色,决定进行变暗(darken)操作还是变亮(lighten)操作。如果源颜色比0.5亮,目标将变亮,即进行了滤色操作。如果源颜色
比0.5暗,目标将变暗,相当于进行了颜色加深(burn)操作,如果等于0.5.目标不会发生改变。变亮或者变暗的程度取决于源颜色和0.5的差
值。
11 QPainter::CompositionMode_Difference 源和目标种较暗的颜色减去较亮的颜色,绘制导致白色反转成目标颜色黑色没化

12 Qpainter::CompositionMode_Exclusion 和上一条规则的效果类似,但对比对较低一些,绘制白色将导致反转成目标颜色,绘制黑色没有

你可能感兴趣的:(Qt)